diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 00:47:55 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 00:47:55 +0000 |
commit | 26a029d407be480d791972afb5975cf62c9360a6 (patch) | |
tree | f435a8308119effd964b339f76abb83a57c29483 /toolkit/components/protobuf | |
parent | Initial commit. (diff) | |
download | firefox-26a029d407be480d791972afb5975cf62c9360a6.tar.xz firefox-26a029d407be480d791972afb5975cf62c9360a6.zip |
Adding upstream version 124.0.1.upstream/124.0.1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'toolkit/components/protobuf')
225 files changed, 139209 insertions, 0 deletions
diff --git a/toolkit/components/protobuf/14174.patch b/toolkit/components/protobuf/14174.patch new file mode 100644 index 0000000000..37b6117f5b --- /dev/null +++ b/toolkit/components/protobuf/14174.patch @@ -0,0 +1,38 @@ +From 292f3191dc63394cac1dbe9b31843ca3bd287812 Mon Sep 17 00:00:00 2001 +From: serge-sans-paille <sguelton@mozilla.com> +Date: Fri, 22 Sep 2023 10:06:44 +0200 +Subject: [PATCH] Remove <iostream> from the common.h header + +<iostream> embeds a global constructor (to initialize std::cout and +such), typically `static ios_base::Init __ioinit;` in libstdc++). + +This header is not directly necessary in the common header and has a +small impact on every compilation unit that includes it. + +As an example, removing that header dependency in turns suppresses 33 global +constructors from the firefox core library libxul. +--- +diff --git a/toolkit/components/protobuf/src/google/protobuf/message_lite.cc b/toolkit/components/protobuf/src/google/protobuf/message_lite.cc +index da66c1965b4c4..a1790b167fdbd 100644 +--- a/toolkit/components/protobuf/src/google/protobuf/message_lite.cc ++++ b/toolkit/components/protobuf/src/google/protobuf/message_lite.cc +@@ -38,6 +38,7 @@ + #include <climits> + #include <cstdint> + #include <string> ++#include <istream> + + #include <google/protobuf/stubs/logging.h> + #include <google/protobuf/stubs/common.h> +diff --git a/toolkit/components/protobuf/src/google/protobuf/stubs/common.h b/toolkit/components/protobuf/src/google/protobuf/stubs/common.h +index ebb1ca0e677cc..58739784db804 100644 +--- a/toolkit/components/protobuf/src/google/protobuf/stubs/common.h ++++ b/toolkit/components/protobuf/src/google/protobuf/stubs/common.h +@@ -36,7 +36,6 @@ + #define GOOGLE_PROTOBUF_COMMON_H__ + + #include <algorithm> +-#include <iostream> + #include <map> + #include <memory> + #include <set> diff --git a/toolkit/components/protobuf/COPYING.txt b/toolkit/components/protobuf/COPYING.txt new file mode 100644 index 0000000000..705db579c9 --- /dev/null +++ b/toolkit/components/protobuf/COPYING.txt @@ -0,0 +1,33 @@ +Copyright 2008, Google Inc. +All rights reserved. + +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. + +Code generated by the Protocol Buffer compiler is owned by the owner +of the input file used when generating it. This code is not +standalone and requires a support library to be linked with it. This +support library is itself covered by the above license. diff --git a/toolkit/components/protobuf/README.txt b/toolkit/components/protobuf/README.txt new file mode 100644 index 0000000000..14a65b897a --- /dev/null +++ b/toolkit/components/protobuf/README.txt @@ -0,0 +1,28 @@ +Protocol Buffers (protobuf) source is available at: + + https://github.com/google/protobuf + +This code is covered under the BSD license (see COPYING.txt). Documentation is +available at https://developers.google.com/protocol-buffers/. + +The tree's current version of the protobuf library is 21.6. + +We do not include the protobuf tests or the protoc compiler. + +-------------------------------------------------------------------------------- + +# Upgrading the Protobuf Library + +1. Get a new protobuf release from https://github.com/google/protobuf/releases + +2. Run `$ ./toolkit/components/protobuf/upgrade_protobuf.sh ~/path/to/release/checkout/of/protobuf`. + +3. Update the moz.build to export the new set of headers and add any new .cc + files to the unified sources and remove old ones. Note that we only + need: + - files contained in the `libprotobuf_lite_la_SOURCES` target + (https://github.com/protocolbuffers/protobuf/blob/main/src/Makefile.am) + - the header files they need + - gzip streams (for devtools) + +4. Re-generate all .pb.cc and .pb.h files using `$ ./toolkit/components/protobuf/regenerate_cpp_files.sh`. diff --git a/toolkit/components/protobuf/moz.build b/toolkit/components/protobuf/moz.build new file mode 100644 index 0000000000..31855811f6 --- /dev/null +++ b/toolkit/components/protobuf/moz.build @@ -0,0 +1,160 @@ +# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*- +# vim: set filetype=python: +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +Library('protobuf') + +with Files('**'): + BUG_COMPONENT = ('Core', 'General') + +EXPORTS.google.protobuf += [ + 'src/google/protobuf/any.h', + 'src/google/protobuf/arena.h', + 'src/google/protobuf/arena_impl.h', + 'src/google/protobuf/arenastring.h', + 'src/google/protobuf/arenaz_sampler.h', + 'src/google/protobuf/endian.h', + 'src/google/protobuf/explicitly_constructed.h', + 'src/google/protobuf/extension_set.h', + 'src/google/protobuf/extension_set_inl.h', + 'src/google/protobuf/generated_enum_util.h', + 'src/google/protobuf/generated_message_tctable_decl.h', + 'src/google/protobuf/generated_message_tctable_impl.h', + 'src/google/protobuf/generated_message_util.h', + 'src/google/protobuf/has_bits.h', + 'src/google/protobuf/implicit_weak_message.h', + 'src/google/protobuf/inlined_string_field.h', + 'src/google/protobuf/map.h', + 'src/google/protobuf/map_entry_lite.h', + 'src/google/protobuf/map_field_lite.h', + 'src/google/protobuf/map_type_handler.h', + 'src/google/protobuf/message_lite.h', + 'src/google/protobuf/metadata_lite.h', + 'src/google/protobuf/parse_context.h', + 'src/google/protobuf/port.h', + 'src/google/protobuf/port_def.inc', + 'src/google/protobuf/port_undef.inc', + 'src/google/protobuf/repeated_field.h', + 'src/google/protobuf/repeated_ptr_field.h', + 'src/google/protobuf/wire_format_lite.h', +] + +EXPORTS.google.protobuf.io += [ + 'src/google/protobuf/io/coded_stream.h', + 'src/google/protobuf/io/gzip_stream.h', + 'src/google/protobuf/io/io_win32.h', + 'src/google/protobuf/io/strtod.h', + 'src/google/protobuf/io/zero_copy_stream.h', + 'src/google/protobuf/io/zero_copy_stream_impl.h', + 'src/google/protobuf/io/zero_copy_stream_impl_lite.h', +] + +EXPORTS.google.protobuf.stubs += [ + 'src/google/protobuf/stubs/bytestream.h', + 'src/google/protobuf/stubs/callback.h', + 'src/google/protobuf/stubs/casts.h', + 'src/google/protobuf/stubs/common.h', + 'src/google/protobuf/stubs/hash.h', + 'src/google/protobuf/stubs/int128.h', + 'src/google/protobuf/stubs/logging.h', + 'src/google/protobuf/stubs/macros.h', + 'src/google/protobuf/stubs/map_util.h', + 'src/google/protobuf/stubs/mutex.h', + 'src/google/protobuf/stubs/once.h', + 'src/google/protobuf/stubs/platform_macros.h', + 'src/google/protobuf/stubs/port.h', + 'src/google/protobuf/stubs/status.h', + # 'src/google/protobuf/stubs/statusor.h', # Unused file + 'src/google/protobuf/stubs/stl_util.h', + 'src/google/protobuf/stubs/stringpiece.h', + 'src/google/protobuf/stubs/stringprintf.h', + 'src/google/protobuf/stubs/strutil.h', + 'src/google/protobuf/stubs/time.h', +] + +UNIFIED_SOURCES += [ + # 'src/google/protobuf/any_lite.cc', # Unused file + 'src/google/protobuf/arena.cc', + 'src/google/protobuf/arenastring.cc', + # 'src/google/protobuf/arenaz_sampler.cc', # Unused file + # 'src/google/protobuf/io/strtod.cc', # Unused file + 'src/google/protobuf/io/zero_copy_stream.cc', + 'src/google/protobuf/stubs/stringpiece.cc', + 'src/google/protobuf/stubs/structurally_valid.cc', + 'src/google/protobuf/stubs/strutil.cc', +] + +SOURCES += [ + 'src/google/protobuf/extension_set.cc', # port_def conflicts + 'src/google/protobuf/generated_enum_util.cc', # port_def conflicts + 'src/google/protobuf/generated_message_tctable_lite.cc', + 'src/google/protobuf/generated_message_util.cc', # port_def conflicts + 'src/google/protobuf/implicit_weak_message.cc', # port_def conflicts + # 'src/google/protobuf/inlined_string_field.cc', # Unused file # port_def conflicts + 'src/google/protobuf/io/coded_stream.cc', # port_def conflicts + 'src/google/protobuf/io/gzip_stream.cc', # technically not in libprotobuf-lite.cmake but devtools/shared/heapsnapshot/HeapSnapshot.cpp uses it. + 'src/google/protobuf/io/io_win32.cc', # port_def conflicts + 'src/google/protobuf/io/zero_copy_stream_impl.cc', # port_def conflicts + 'src/google/protobuf/io/zero_copy_stream_impl_lite.cc', # port_def conflicts + 'src/google/protobuf/map.cc', # port_def conflicts + 'src/google/protobuf/message_lite.cc', # port_def conflicts + 'src/google/protobuf/parse_context.cc', # port_def conflicts + 'src/google/protobuf/repeated_field.cc', # port_def conflicts + 'src/google/protobuf/repeated_ptr_field.cc', # port_def conflicts + # 'src/google/protobuf/stubs/bytestream.cc', # Unused file # port_def conflicts + 'src/google/protobuf/stubs/common.cc', # port_def conflicts + 'src/google/protobuf/stubs/int128.cc', # port_def conflicts + 'src/google/protobuf/stubs/status.cc', # port_def conflicts + # 'src/google/protobuf/stubs/statusor.cc', # Unused file. # port_def conflicts + # 'src/google/protobuf/stubs/stringprintf.cc', # Unused file # port_def conflicts + # 'src/google/protobuf/stubs/time.cc', # Unused file # GetCurrentTime conflict in winbase.h + 'src/google/protobuf/wire_format_lite.cc', # port_def conflicts +] + +# We allow warnings for third-party code that can be updated from upstream. +AllowCompilerWarnings() + +FINAL_LIBRARY = 'xul' + +DEFINES['GOOGLE_PROTOBUF_NO_RTTI'] = True +DEFINES['GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER'] = True + +# Suppress warnings in third-party code. +if CONFIG['CC_TYPE'] in ('clang', 'gcc'): + CXXFLAGS += [ + '-Wno-ignored-qualifiers', + '-Wno-maybe-uninitialized', + '-Wno-return-type', + '-Wno-sign-compare', + '-Wno-subobject-linkage', + '-Wno-unused-function', + ] + if CONFIG['CC_TYPE'] == 'clang': + CXXFLAGS += [ + '-Wno-comma', + '-Wno-null-conversion', + '-Wno-unused-local-typedef', + ] +elif CONFIG['CC_TYPE'] == 'clang-cl': + CXXFLAGS += [ + '-Wno-macro-redefined', # 'WIN32_LEAN_AND_MEAN' : macro redefinition + '-Wno-sign-compare', + ] + +if CONFIG['OS_TARGET'] == 'WINNT': + DEFINES['NOGDI'] = True # wingdi.h defines ERROR as 0 and conflicts with logging.h + +if CONFIG['MOZ_USE_PTHREADS']: + DEFINES['HAVE_PTHREAD'] = True + +# Needed for the gzip streams. +DEFINES['HAVE_ZLIB'] = True + +if CONFIG["MOZ_WIDGET_TOOLKIT"] == "gtk": + CXXFLAGS += CONFIG['MOZ_GTK3_CFLAGS'] + +# Work around bug 1841201. +if CONFIG['TARGET_CPU'] in ('mips32', 'mips64'): + DEFINES['musttail'] = 'nomusttail' diff --git a/toolkit/components/protobuf/regenerate_cpp_files.sh b/toolkit/components/protobuf/regenerate_cpp_files.sh new file mode 100755 index 0000000000..848e6f538e --- /dev/null +++ b/toolkit/components/protobuf/regenerate_cpp_files.sh @@ -0,0 +1,31 @@ +#!/usr/bin/env bash + +set -e + +if which protoc >/dev/null ; then + echo "Using $(which protoc) to regenerate .pb.cc and .pb.h files." +else + echo "protoc not found in your path. Cannot regenerate the .pb.cc and .pb.h files." + exit 1 +fi + +regenerate() { + DIR="$1" + PROTO="$2" + echo + echo "${DIR}${PROTO}:" + pushd "$DIR" >/dev/null + protoc --cpp_out=. "$PROTO" + popd >/dev/null +} + +cd $(dirname $0) +cd ../../.. # Top level. + +regenerate devtools/shared/heapsnapshot/ CoreDump.proto +regenerate toolkit/components/reputationservice/chromium/chrome/common/safe_browsing/ csd.proto +regenerate toolkit/components/url-classifier/chromium/ safebrowsing.proto +command cp third_party/content_analysis_sdk/proto/content_analysis/sdk/analysis.proto toolkit/components/contentanalysis/content_analysis/sdk/analysis.proto +regenerate toolkit/components/contentanalysis/content_analysis/sdk/ analysis.proto +command cp third_party/rust/viaduct/src/fetch_msg_types.proto toolkit/components/viaduct/fetch_msg_types.proto +regenerate toolkit/components/viaduct/ fetch_msg_types.proto diff --git a/toolkit/components/protobuf/src/google/protobuf/any.cc b/toolkit/components/protobuf/src/google/protobuf/any.cc new file mode 100644 index 0000000000..346fa19f17 --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/any.cc @@ -0,0 +1,82 @@ +// 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. + +#include <google/protobuf/any.h> + +#include <google/protobuf/arenastring.h> +#include <google/protobuf/descriptor.h> +#include <google/protobuf/generated_message_util.h> +#include <google/protobuf/message.h> + +// Must be included last. +#include <google/protobuf/port_def.inc> + +namespace google { +namespace protobuf { +namespace internal { + +bool AnyMetadata::PackFrom(Arena* arena, const Message& message) { + return PackFrom(arena, message, kTypeGoogleApisComPrefix); +} + +bool AnyMetadata::PackFrom(Arena* arena, const Message& message, + StringPiece type_url_prefix) { + type_url_->Set( + GetTypeUrl(message.GetDescriptor()->full_name(), type_url_prefix), arena); + return message.SerializeToString(value_->Mutable(arena)); +} + +bool AnyMetadata::UnpackTo(Message* message) const { + if (!InternalIs(message->GetDescriptor()->full_name())) { + return false; + } + return message->ParseFromString(value_->Get()); +} + +bool GetAnyFieldDescriptors(const Message& message, + const FieldDescriptor** type_url_field, + const FieldDescriptor** value_field) { + const Descriptor* descriptor = message.GetDescriptor(); + if (descriptor->full_name() != kAnyFullTypeName) { + return false; + } + *type_url_field = descriptor->FindFieldByNumber(1); + *value_field = descriptor->FindFieldByNumber(2); + return (*type_url_field != nullptr && + (*type_url_field)->type() == FieldDescriptor::TYPE_STRING && + *value_field != nullptr && + (*value_field)->type() == FieldDescriptor::TYPE_BYTES); +} + +} // namespace internal +} // namespace protobuf +} // namespace google + +#include <google/protobuf/port_undef.inc> diff --git a/toolkit/components/protobuf/src/google/protobuf/any.h b/toolkit/components/protobuf/src/google/protobuf/any.h new file mode 100644 index 0000000000..92ea2bb2c7 --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/any.h @@ -0,0 +1,157 @@ +// 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. + +#ifndef GOOGLE_PROTOBUF_ANY_H__ +#define GOOGLE_PROTOBUF_ANY_H__ + +#include <string> + +#include <google/protobuf/stubs/common.h> +#include <google/protobuf/arenastring.h> +#include <google/protobuf/message_lite.h> + +// Must be included last. +#include <google/protobuf/port_def.inc> + +namespace google { +namespace protobuf { + +class FieldDescriptor; +class Message; + +namespace internal { + +extern const char kAnyFullTypeName[]; // "google.protobuf.Any". +extern const char kTypeGoogleApisComPrefix[]; // "type.googleapis.com/". +extern const char kTypeGoogleProdComPrefix[]; // "type.googleprod.com/". + +std::string GetTypeUrl(StringPiece message_name, + StringPiece type_url_prefix); + +// Helper class used to implement google::protobuf::Any. +class PROTOBUF_EXPORT AnyMetadata { + typedef ArenaStringPtr UrlType; + typedef ArenaStringPtr ValueType; + public: + // AnyMetadata does not take ownership of "type_url" and "value". + constexpr AnyMetadata(UrlType* type_url, ValueType* value) + : type_url_(type_url), value_(value) {} + + // Packs a message using the default type URL prefix: "type.googleapis.com". + // The resulted type URL will be "type.googleapis.com/<message_full_name>". + // Returns false if serializing the message failed. + template <typename T> + bool PackFrom(Arena* arena, const T& message) { + return InternalPackFrom(arena, message, kTypeGoogleApisComPrefix, + T::FullMessageName()); + } + + bool PackFrom(Arena* arena, const Message& message); + + // Packs a message using the given type URL prefix. The type URL will be + // constructed by concatenating the message type's full name to the prefix + // with an optional "/" separator if the prefix doesn't already end with "/". + // For example, both PackFrom(message, "type.googleapis.com") and + // PackFrom(message, "type.googleapis.com/") yield the same result type + // URL: "type.googleapis.com/<message_full_name>". + // Returns false if serializing the message failed. + template <typename T> + bool PackFrom(Arena* arena, const T& message, + StringPiece type_url_prefix) { + return InternalPackFrom(arena, message, type_url_prefix, + T::FullMessageName()); + } + + bool PackFrom(Arena* arena, const Message& message, + StringPiece type_url_prefix); + + // Unpacks the payload into the given message. Returns false if the message's + // type doesn't match the type specified in the type URL (i.e., the full + // name after the last "/" of the type URL doesn't match the message's actual + // full name) or parsing the payload has failed. + template <typename T> + bool UnpackTo(T* message) const { + return InternalUnpackTo(T::FullMessageName(), message); + } + + bool UnpackTo(Message* message) const; + + // Checks whether the type specified in the type URL matches the given type. + // A type is considered matching if its full name matches the full name after + // the last "/" in the type URL. + template <typename T> + bool Is() const { + return InternalIs(T::FullMessageName()); + } + + private: + bool InternalPackFrom(Arena* arena, const MessageLite& message, + StringPiece type_url_prefix, + StringPiece type_name); + bool InternalUnpackTo(StringPiece type_name, + MessageLite* message) const; + bool InternalIs(StringPiece type_name) const; + + UrlType* type_url_; + ValueType* value_; + + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(AnyMetadata); +}; + +// Get the proto type name from Any::type_url value. For example, passing +// "type.googleapis.com/rpc.QueryOrigin" will return "rpc.QueryOrigin" in +// *full_type_name. Returns false if the type_url does not have a "/" +// in the type url separating the full type name. +// +// NOTE: this function is available publicly as a static method on the +// generated message type: google::protobuf::Any::ParseAnyTypeUrl() +bool ParseAnyTypeUrl(StringPiece type_url, std::string* full_type_name); + +// Get the proto type name and prefix from Any::type_url value. For example, +// passing "type.googleapis.com/rpc.QueryOrigin" will return +// "type.googleapis.com/" in *url_prefix and "rpc.QueryOrigin" in +// *full_type_name. Returns false if the type_url does not have a "/" in the +// type url separating the full type name. +bool ParseAnyTypeUrl(StringPiece type_url, std::string* url_prefix, + std::string* full_type_name); + +// See if message is of type google.protobuf.Any, if so, return the descriptors +// for "type_url" and "value" fields. +bool GetAnyFieldDescriptors(const Message& message, + const FieldDescriptor** type_url_field, + const FieldDescriptor** value_field); + +} // namespace internal +} // namespace protobuf +} // namespace google + +#include <google/protobuf/port_undef.inc> + +#endif // GOOGLE_PROTOBUF_ANY_H__ diff --git a/toolkit/components/protobuf/src/google/protobuf/any.pb.cc b/toolkit/components/protobuf/src/google/protobuf/any.pb.cc new file mode 100644 index 0000000000..c02f9eb7f8 --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/any.pb.cc @@ -0,0 +1,368 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: google/protobuf/any.proto + +#include <google/protobuf/any.pb.h> + +#include <algorithm> + +#include <google/protobuf/io/coded_stream.h> +#include <google/protobuf/extension_set.h> +#include <google/protobuf/wire_format_lite.h> +#include <google/protobuf/descriptor.h> +#include <google/protobuf/generated_message_reflection.h> +#include <google/protobuf/reflection_ops.h> +#include <google/protobuf/wire_format.h> +// @@protoc_insertion_point(includes) +#include <google/protobuf/port_def.inc> + +PROTOBUF_PRAGMA_INIT_SEG + +namespace _pb = ::PROTOBUF_NAMESPACE_ID; +namespace _pbi = _pb::internal; + +#if defined(__llvm__) + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wuninitialized" +#endif // __llvm__ +PROTOBUF_NAMESPACE_OPEN +PROTOBUF_CONSTEXPR Any::Any( + ::_pbi::ConstantInitialized): _impl_{ + /*decltype(_impl_.type_url_)*/{&::_pbi::fixed_address_empty_string, ::_pbi::ConstantInitialized{}} + , /*decltype(_impl_.value_)*/{&::_pbi::fixed_address_empty_string, ::_pbi::ConstantInitialized{}} + , /*decltype(_impl_._cached_size_)*/{} + , /*decltype(_impl_._any_metadata_)*/{&_impl_.type_url_, &_impl_.value_}} {} +struct AnyDefaultTypeInternal { + PROTOBUF_CONSTEXPR AnyDefaultTypeInternal() + : _instance(::_pbi::ConstantInitialized{}) {} + ~AnyDefaultTypeInternal() {} + union { + Any _instance; + }; +}; +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 AnyDefaultTypeInternal _Any_default_instance_; +PROTOBUF_NAMESPACE_CLOSE +static ::_pb::Metadata file_level_metadata_google_2fprotobuf_2fany_2eproto[1]; +static constexpr ::_pb::EnumDescriptor const** file_level_enum_descriptors_google_2fprotobuf_2fany_2eproto = nullptr; +static constexpr ::_pb::ServiceDescriptor const** file_level_service_descriptors_google_2fprotobuf_2fany_2eproto = nullptr; + +const uint32_t TableStruct_google_2fprotobuf_2fany_2eproto::offsets[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = { + ~0u, // no _has_bits_ + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Any, _internal_metadata_), + ~0u, // no _extensions_ + ~0u, // no _oneof_case_ + ~0u, // no _weak_field_map_ + ~0u, // no _inlined_string_donated_ + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Any, _impl_.type_url_), + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Any, _impl_.value_), +}; +static const ::_pbi::MigrationSchema schemas[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = { + { 0, -1, -1, sizeof(::PROTOBUF_NAMESPACE_ID::Any)}, +}; + +static const ::_pb::Message* const file_default_instances[] = { + &::PROTOBUF_NAMESPACE_ID::_Any_default_instance_._instance, +}; + +const char descriptor_table_protodef_google_2fprotobuf_2fany_2eproto[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = + "\n\031google/protobuf/any.proto\022\017google.prot" + "obuf\"&\n\003Any\022\020\n\010type_url\030\001 \001(\t\022\r\n\005value\030\002" + " \001(\014Bv\n\023com.google.protobufB\010AnyProtoP\001Z" + ",google.golang.org/protobuf/types/known/" + "anypb\242\002\003GPB\252\002\036Google.Protobuf.WellKnownT" + "ypesb\006proto3" + ; +static ::_pbi::once_flag descriptor_table_google_2fprotobuf_2fany_2eproto_once; +const ::_pbi::DescriptorTable descriptor_table_google_2fprotobuf_2fany_2eproto = { + false, false, 212, descriptor_table_protodef_google_2fprotobuf_2fany_2eproto, + "google/protobuf/any.proto", + &descriptor_table_google_2fprotobuf_2fany_2eproto_once, nullptr, 0, 1, + schemas, file_default_instances, TableStruct_google_2fprotobuf_2fany_2eproto::offsets, + file_level_metadata_google_2fprotobuf_2fany_2eproto, file_level_enum_descriptors_google_2fprotobuf_2fany_2eproto, + file_level_service_descriptors_google_2fprotobuf_2fany_2eproto, +}; +PROTOBUF_ATTRIBUTE_WEAK const ::_pbi::DescriptorTable* descriptor_table_google_2fprotobuf_2fany_2eproto_getter() { + return &descriptor_table_google_2fprotobuf_2fany_2eproto; +} + +// Force running AddDescriptors() at dynamic initialization time. +PROTOBUF_ATTRIBUTE_INIT_PRIORITY2 static ::_pbi::AddDescriptorsRunner dynamic_init_dummy_google_2fprotobuf_2fany_2eproto(&descriptor_table_google_2fprotobuf_2fany_2eproto); +PROTOBUF_NAMESPACE_OPEN + +// =================================================================== + +bool Any::GetAnyFieldDescriptors( + const ::PROTOBUF_NAMESPACE_ID::Message& message, + const ::PROTOBUF_NAMESPACE_ID::FieldDescriptor** type_url_field, + const ::PROTOBUF_NAMESPACE_ID::FieldDescriptor** value_field) { + return ::_pbi::GetAnyFieldDescriptors( + message, type_url_field, value_field); +} +bool Any::ParseAnyTypeUrl( + ::PROTOBUF_NAMESPACE_ID::ConstStringParam type_url, + std::string* full_type_name) { + return ::_pbi::ParseAnyTypeUrl(type_url, full_type_name); +} + +class Any::_Internal { + public: +}; + +Any::Any(::PROTOBUF_NAMESPACE_ID::Arena* arena, + bool is_message_owned) + : ::PROTOBUF_NAMESPACE_ID::Message(arena, is_message_owned) { + SharedCtor(arena, is_message_owned); + // @@protoc_insertion_point(arena_constructor:google.protobuf.Any) +} +Any::Any(const Any& from) + : ::PROTOBUF_NAMESPACE_ID::Message() { + Any* const _this = this; (void)_this; + new (&_impl_) Impl_{ + decltype(_impl_.type_url_){} + , decltype(_impl_.value_){} + , /*decltype(_impl_._cached_size_)*/{} + , /*decltype(_impl_._any_metadata_)*/{&_impl_.type_url_, &_impl_.value_}}; + + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); + _impl_.type_url_.InitDefault(); + #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + _impl_.type_url_.Set("", GetArenaForAllocation()); + #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (!from._internal_type_url().empty()) { + _this->_impl_.type_url_.Set(from._internal_type_url(), + _this->GetArenaForAllocation()); + } + _impl_.value_.InitDefault(); + #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + _impl_.value_.Set("", GetArenaForAllocation()); + #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (!from._internal_value().empty()) { + _this->_impl_.value_.Set(from._internal_value(), + _this->GetArenaForAllocation()); + } + // @@protoc_insertion_point(copy_constructor:google.protobuf.Any) +} + +inline void Any::SharedCtor( + ::_pb::Arena* arena, bool is_message_owned) { + (void)arena; + (void)is_message_owned; + new (&_impl_) Impl_{ + decltype(_impl_.type_url_){} + , decltype(_impl_.value_){} + , /*decltype(_impl_._cached_size_)*/{} + , /*decltype(_impl_._any_metadata_)*/{&_impl_.type_url_, &_impl_.value_} + }; + _impl_.type_url_.InitDefault(); + #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + _impl_.type_url_.Set("", GetArenaForAllocation()); + #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + _impl_.value_.InitDefault(); + #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + _impl_.value_.Set("", GetArenaForAllocation()); + #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING +} + +Any::~Any() { + // @@protoc_insertion_point(destructor:google.protobuf.Any) + if (auto *arena = _internal_metadata_.DeleteReturnArena<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>()) { + (void)arena; + return; + } + SharedDtor(); +} + +inline void Any::SharedDtor() { + GOOGLE_DCHECK(GetArenaForAllocation() == nullptr); + _impl_.type_url_.Destroy(); + _impl_.value_.Destroy(); + _impl_._any_metadata_.~AnyMetadata(); +} + +void Any::SetCachedSize(int size) const { + _impl_._cached_size_.Set(size); +} + +void Any::Clear() { +// @@protoc_insertion_point(message_clear_start:google.protobuf.Any) + uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + _impl_.type_url_.ClearToEmpty(); + _impl_.value_.ClearToEmpty(); + _internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); +} + +const char* Any::_InternalParse(const char* ptr, ::_pbi::ParseContext* ctx) { +#define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure + while (!ctx->Done(&ptr)) { + uint32_t tag; + ptr = ::_pbi::ReadTag(ptr, &tag); + switch (tag >> 3) { + // string type_url = 1; + case 1: + if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 10)) { + auto str = _internal_mutable_type_url(); + ptr = ::_pbi::InlineGreedyStringParser(str, ptr, ctx); + CHK_(ptr); + CHK_(::_pbi::VerifyUTF8(str, "google.protobuf.Any.type_url")); + } else + goto handle_unusual; + continue; + // bytes value = 2; + case 2: + if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 18)) { + auto str = _internal_mutable_value(); + ptr = ::_pbi::InlineGreedyStringParser(str, ptr, ctx); + CHK_(ptr); + } else + goto handle_unusual; + continue; + default: + goto handle_unusual; + } // switch + handle_unusual: + if ((tag == 0) || ((tag & 7) == 4)) { + CHK_(ptr); + ctx->SetLastTag(tag); + goto message_done; + } + ptr = UnknownFieldParse( + tag, + _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(), + ptr, ctx); + CHK_(ptr != nullptr); + } // while +message_done: + return ptr; +failure: + ptr = nullptr; + goto message_done; +#undef CHK_ +} + +uint8_t* Any::_InternalSerialize( + uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const { + // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.Any) + uint32_t cached_has_bits = 0; + (void) cached_has_bits; + + // string type_url = 1; + if (!this->_internal_type_url().empty()) { + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::VerifyUtf8String( + this->_internal_type_url().data(), static_cast<int>(this->_internal_type_url().length()), + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::SERIALIZE, + "google.protobuf.Any.type_url"); + target = stream->WriteStringMaybeAliased( + 1, this->_internal_type_url(), target); + } + + // bytes value = 2; + if (!this->_internal_value().empty()) { + target = stream->WriteBytesMaybeAliased( + 2, this->_internal_value(), target); + } + + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + target = ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( + _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.Any) + return target; +} + +size_t Any::ByteSizeLong() const { +// @@protoc_insertion_point(message_byte_size_start:google.protobuf.Any) + size_t total_size = 0; + + uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + // string type_url = 1; + if (!this->_internal_type_url().empty()) { + total_size += 1 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize( + this->_internal_type_url()); + } + + // bytes value = 2; + if (!this->_internal_value().empty()) { + total_size += 1 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::BytesSize( + this->_internal_value()); + } + + return MaybeComputeUnknownFieldsSize(total_size, &_impl_._cached_size_); +} + +const ::PROTOBUF_NAMESPACE_ID::Message::ClassData Any::_class_data_ = { + ::PROTOBUF_NAMESPACE_ID::Message::CopyWithSourceCheck, + Any::MergeImpl +}; +const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*Any::GetClassData() const { return &_class_data_; } + + +void Any::MergeImpl(::PROTOBUF_NAMESPACE_ID::Message& to_msg, const ::PROTOBUF_NAMESPACE_ID::Message& from_msg) { + auto* const _this = static_cast<Any*>(&to_msg); + auto& from = static_cast<const Any&>(from_msg); + // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.Any) + GOOGLE_DCHECK_NE(&from, _this); + uint32_t cached_has_bits = 0; + (void) cached_has_bits; + + if (!from._internal_type_url().empty()) { + _this->_internal_set_type_url(from._internal_type_url()); + } + if (!from._internal_value().empty()) { + _this->_internal_set_value(from._internal_value()); + } + _this->_internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); +} + +void Any::CopyFrom(const Any& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.Any) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool Any::IsInitialized() const { + return true; +} + +void Any::InternalSwap(Any* other) { + using std::swap; + auto* lhs_arena = GetArenaForAllocation(); + auto* rhs_arena = other->GetArenaForAllocation(); + _internal_metadata_.InternalSwap(&other->_internal_metadata_); + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::InternalSwap( + &_impl_.type_url_, lhs_arena, + &other->_impl_.type_url_, rhs_arena + ); + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::InternalSwap( + &_impl_.value_, lhs_arena, + &other->_impl_.value_, rhs_arena + ); +} + +::PROTOBUF_NAMESPACE_ID::Metadata Any::GetMetadata() const { + return ::_pbi::AssignDescriptors( + &descriptor_table_google_2fprotobuf_2fany_2eproto_getter, &descriptor_table_google_2fprotobuf_2fany_2eproto_once, + file_level_metadata_google_2fprotobuf_2fany_2eproto[0]); +} + +// @@protoc_insertion_point(namespace_scope) +PROTOBUF_NAMESPACE_CLOSE +PROTOBUF_NAMESPACE_OPEN +template<> PROTOBUF_NOINLINE ::PROTOBUF_NAMESPACE_ID::Any* +Arena::CreateMaybeMessage< ::PROTOBUF_NAMESPACE_ID::Any >(Arena* arena) { + return Arena::CreateMessageInternal< ::PROTOBUF_NAMESPACE_ID::Any >(arena); +} +PROTOBUF_NAMESPACE_CLOSE + +// @@protoc_insertion_point(global_scope) +#if defined(__llvm__) + #pragma clang diagnostic pop +#endif // __llvm__ +#include <google/protobuf/port_undef.inc> diff --git a/toolkit/components/protobuf/src/google/protobuf/any.pb.h b/toolkit/components/protobuf/src/google/protobuf/any.pb.h new file mode 100644 index 0000000000..ac51c9bcac --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/any.pb.h @@ -0,0 +1,384 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: google/protobuf/any.proto + +#ifndef GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2fany_2eproto +#define GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2fany_2eproto + +#include <limits> +#include <string> + +#include <google/protobuf/port_def.inc> +#if PROTOBUF_VERSION < 3021000 +#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 3021006 < 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. +#endif + +#include <google/protobuf/port_undef.inc> +#include <google/protobuf/io/coded_stream.h> +#include <google/protobuf/arena.h> +#include <google/protobuf/arenastring.h> +#include <google/protobuf/generated_message_util.h> +#include <google/protobuf/metadata_lite.h> +#include <google/protobuf/generated_message_reflection.h> +#include <google/protobuf/message.h> +#include <google/protobuf/repeated_field.h> // IWYU pragma: export +#include <google/protobuf/extension_set.h> // IWYU pragma: export +#include <google/protobuf/unknown_field_set.h> +// @@protoc_insertion_point(includes) +#include <google/protobuf/port_def.inc> +#define PROTOBUF_INTERNAL_EXPORT_google_2fprotobuf_2fany_2eproto PROTOBUF_EXPORT +PROTOBUF_NAMESPACE_OPEN +namespace internal { +class AnyMetadata; +} // namespace internal +PROTOBUF_NAMESPACE_CLOSE + +// Internal implementation detail -- do not use these members. +struct PROTOBUF_EXPORT TableStruct_google_2fprotobuf_2fany_2eproto { + static const uint32_t offsets[]; +}; +PROTOBUF_EXPORT extern const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable descriptor_table_google_2fprotobuf_2fany_2eproto; +PROTOBUF_NAMESPACE_OPEN +class Any; +struct AnyDefaultTypeInternal; +PROTOBUF_EXPORT extern AnyDefaultTypeInternal _Any_default_instance_; +PROTOBUF_NAMESPACE_CLOSE +PROTOBUF_NAMESPACE_OPEN +template<> PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::Any* Arena::CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::Any>(Arena*); +PROTOBUF_NAMESPACE_CLOSE +PROTOBUF_NAMESPACE_OPEN + +// =================================================================== + +class PROTOBUF_EXPORT Any final : + public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.Any) */ { + public: + inline Any() : Any(nullptr) {} + ~Any() override; + explicit PROTOBUF_CONSTEXPR Any(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized); + + Any(const Any& from); + Any(Any&& from) noexcept + : Any() { + *this = ::std::move(from); + } + + inline Any& operator=(const Any& from) { + CopyFrom(from); + return *this; + } + inline Any& operator=(Any&& from) noexcept { + if (this == &from) return *this; + if (GetOwningArena() == from.GetOwningArena() + #ifdef PROTOBUF_FORCE_COPY_IN_MOVE + && GetOwningArena() != nullptr + #endif // !PROTOBUF_FORCE_COPY_IN_MOVE + ) { + InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* descriptor() { + return GetDescriptor(); + } + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() { + return default_instance().GetMetadata().descriptor; + } + static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() { + return default_instance().GetMetadata().reflection; + } + static const Any& default_instance() { + return *internal_default_instance(); + } + static inline const Any* internal_default_instance() { + return reinterpret_cast<const Any*>( + &_Any_default_instance_); + } + static constexpr int kIndexInFileMessages = + 0; + + // implements Any ----------------------------------------------- + + bool PackFrom(const ::PROTOBUF_NAMESPACE_ID::Message& message) { + GOOGLE_DCHECK_NE(&message, this); + return _impl_._any_metadata_.PackFrom(GetArena(), message); + } + bool PackFrom(const ::PROTOBUF_NAMESPACE_ID::Message& message, + ::PROTOBUF_NAMESPACE_ID::ConstStringParam type_url_prefix) { + GOOGLE_DCHECK_NE(&message, this); + return _impl_._any_metadata_.PackFrom(GetArena(), message, type_url_prefix); + } + bool UnpackTo(::PROTOBUF_NAMESPACE_ID::Message* message) const { + return _impl_._any_metadata_.UnpackTo(message); + } + static bool GetAnyFieldDescriptors( + const ::PROTOBUF_NAMESPACE_ID::Message& message, + const ::PROTOBUF_NAMESPACE_ID::FieldDescriptor** type_url_field, + const ::PROTOBUF_NAMESPACE_ID::FieldDescriptor** value_field); + template <typename T, class = typename std::enable_if<!std::is_convertible<T, const ::PROTOBUF_NAMESPACE_ID::Message&>::value>::type> + bool PackFrom(const T& message) { + return _impl_._any_metadata_.PackFrom<T>(GetArena(), message); + } + template <typename T, class = typename std::enable_if<!std::is_convertible<T, const ::PROTOBUF_NAMESPACE_ID::Message&>::value>::type> + bool PackFrom(const T& message, + ::PROTOBUF_NAMESPACE_ID::ConstStringParam type_url_prefix) { + return _impl_._any_metadata_.PackFrom<T>(GetArena(), message, type_url_prefix);} + template <typename T, class = typename std::enable_if<!std::is_convertible<T, const ::PROTOBUF_NAMESPACE_ID::Message&>::value>::type> + bool UnpackTo(T* message) const { + return _impl_._any_metadata_.UnpackTo<T>(message); + } + template<typename T> bool Is() const { + return _impl_._any_metadata_.Is<T>(); + } + static bool ParseAnyTypeUrl(::PROTOBUF_NAMESPACE_ID::ConstStringParam type_url, + std::string* full_type_name); + friend void swap(Any& a, Any& b) { + a.Swap(&b); + } + inline void Swap(Any* other) { + if (other == this) return; + #ifdef PROTOBUF_FORCE_COPY_IN_SWAP + if (GetOwningArena() != nullptr && + GetOwningArena() == other->GetOwningArena()) { + #else // PROTOBUF_FORCE_COPY_IN_SWAP + if (GetOwningArena() == other->GetOwningArena()) { + #endif // !PROTOBUF_FORCE_COPY_IN_SWAP + InternalSwap(other); + } else { + ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(Any* other) { + if (other == this) return; + GOOGLE_DCHECK(GetOwningArena() == other->GetOwningArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + Any* New(::PROTOBUF_NAMESPACE_ID::Arena* arena = nullptr) const final { + return CreateMaybeMessage<Any>(arena); + } + using ::PROTOBUF_NAMESPACE_ID::Message::CopyFrom; + void CopyFrom(const Any& from); + using ::PROTOBUF_NAMESPACE_ID::Message::MergeFrom; + void MergeFrom( const Any& from) { + Any::MergeImpl(*this, from); + } + private: + static void MergeImpl(::PROTOBUF_NAMESPACE_ID::Message& to_msg, const ::PROTOBUF_NAMESPACE_ID::Message& from_msg); + public: + PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + bool IsInitialized() const final; + + size_t ByteSizeLong() const final; + const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final; + uint8_t* _InternalSerialize( + uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final; + int GetCachedSize() const final { return _impl_._cached_size_.Get(); } + + private: + void SharedCtor(::PROTOBUF_NAMESPACE_ID::Arena* arena, bool is_message_owned); + void SharedDtor(); + void SetCachedSize(int size) const final; + void InternalSwap(Any* other); + + private: + friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata; + static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() { + return "google.protobuf.Any"; + } + protected: + explicit Any(::PROTOBUF_NAMESPACE_ID::Arena* arena, + bool is_message_owned = false); + public: + + static const ClassData _class_data_; + const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*GetClassData() const final; + + ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final; + + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + + enum : int { + kTypeUrlFieldNumber = 1, + kValueFieldNumber = 2, + }; + // string type_url = 1; + void clear_type_url(); + const std::string& type_url() const; + template <typename ArgT0 = const std::string&, typename... ArgT> + void set_type_url(ArgT0&& arg0, ArgT... args); + std::string* mutable_type_url(); + PROTOBUF_NODISCARD std::string* release_type_url(); + void set_allocated_type_url(std::string* type_url); + private: + const std::string& _internal_type_url() const; + inline PROTOBUF_ALWAYS_INLINE void _internal_set_type_url(const std::string& value); + std::string* _internal_mutable_type_url(); + public: + + // bytes value = 2; + void clear_value(); + const std::string& value() const; + template <typename ArgT0 = const std::string&, typename... ArgT> + void set_value(ArgT0&& arg0, ArgT... args); + std::string* mutable_value(); + PROTOBUF_NODISCARD std::string* release_value(); + void set_allocated_value(std::string* value); + private: + const std::string& _internal_value() const; + inline PROTOBUF_ALWAYS_INLINE void _internal_set_value(const std::string& value); + std::string* _internal_mutable_value(); + public: + + // @@protoc_insertion_point(class_scope:google.protobuf.Any) + private: + class _Internal; + + template <typename T> friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper; + typedef void InternalArenaConstructable_; + typedef void DestructorSkippable_; + struct Impl_ { + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr type_url_; + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr value_; + mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_; + ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata _any_metadata_; + }; + union { Impl_ _impl_; }; + friend struct ::TableStruct_google_2fprotobuf_2fany_2eproto; +}; +// =================================================================== + + +// =================================================================== + +#ifdef __GNUC__ + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wstrict-aliasing" +#endif // __GNUC__ +// Any + +// string type_url = 1; +inline void Any::clear_type_url() { + _impl_.type_url_.ClearToEmpty(); +} +inline const std::string& Any::type_url() const { + // @@protoc_insertion_point(field_get:google.protobuf.Any.type_url) + return _internal_type_url(); +} +template <typename ArgT0, typename... ArgT> +inline PROTOBUF_ALWAYS_INLINE +void Any::set_type_url(ArgT0&& arg0, ArgT... args) { + + _impl_.type_url_.Set(static_cast<ArgT0 &&>(arg0), args..., GetArenaForAllocation()); + // @@protoc_insertion_point(field_set:google.protobuf.Any.type_url) +} +inline std::string* Any::mutable_type_url() { + std::string* _s = _internal_mutable_type_url(); + // @@protoc_insertion_point(field_mutable:google.protobuf.Any.type_url) + return _s; +} +inline const std::string& Any::_internal_type_url() const { + return _impl_.type_url_.Get(); +} +inline void Any::_internal_set_type_url(const std::string& value) { + + _impl_.type_url_.Set(value, GetArenaForAllocation()); +} +inline std::string* Any::_internal_mutable_type_url() { + + return _impl_.type_url_.Mutable(GetArenaForAllocation()); +} +inline std::string* Any::release_type_url() { + // @@protoc_insertion_point(field_release:google.protobuf.Any.type_url) + return _impl_.type_url_.Release(); +} +inline void Any::set_allocated_type_url(std::string* type_url) { + if (type_url != nullptr) { + + } else { + + } + _impl_.type_url_.SetAllocated(type_url, GetArenaForAllocation()); +#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (_impl_.type_url_.IsDefault()) { + _impl_.type_url_.Set("", GetArenaForAllocation()); + } +#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + // @@protoc_insertion_point(field_set_allocated:google.protobuf.Any.type_url) +} + +// bytes value = 2; +inline void Any::clear_value() { + _impl_.value_.ClearToEmpty(); +} +inline const std::string& Any::value() const { + // @@protoc_insertion_point(field_get:google.protobuf.Any.value) + return _internal_value(); +} +template <typename ArgT0, typename... ArgT> +inline PROTOBUF_ALWAYS_INLINE +void Any::set_value(ArgT0&& arg0, ArgT... args) { + + _impl_.value_.SetBytes(static_cast<ArgT0 &&>(arg0), args..., GetArenaForAllocation()); + // @@protoc_insertion_point(field_set:google.protobuf.Any.value) +} +inline std::string* Any::mutable_value() { + std::string* _s = _internal_mutable_value(); + // @@protoc_insertion_point(field_mutable:google.protobuf.Any.value) + return _s; +} +inline const std::string& Any::_internal_value() const { + return _impl_.value_.Get(); +} +inline void Any::_internal_set_value(const std::string& value) { + + _impl_.value_.Set(value, GetArenaForAllocation()); +} +inline std::string* Any::_internal_mutable_value() { + + return _impl_.value_.Mutable(GetArenaForAllocation()); +} +inline std::string* Any::release_value() { + // @@protoc_insertion_point(field_release:google.protobuf.Any.value) + return _impl_.value_.Release(); +} +inline void Any::set_allocated_value(std::string* value) { + if (value != nullptr) { + + } else { + + } + _impl_.value_.SetAllocated(value, GetArenaForAllocation()); +#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (_impl_.value_.IsDefault()) { + _impl_.value_.Set("", GetArenaForAllocation()); + } +#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + // @@protoc_insertion_point(field_set_allocated:google.protobuf.Any.value) +} + +#ifdef __GNUC__ + #pragma GCC diagnostic pop +#endif // __GNUC__ + +// @@protoc_insertion_point(namespace_scope) + +PROTOBUF_NAMESPACE_CLOSE + +// @@protoc_insertion_point(global_scope) + +#include <google/protobuf/port_undef.inc> +#endif // GOOGLE_PROTOBUF_INCLUDED_GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2fany_2eproto diff --git a/toolkit/components/protobuf/src/google/protobuf/any.proto b/toolkit/components/protobuf/src/google/protobuf/any.proto new file mode 100644 index 0000000000..e2c2042fdc --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/any.proto @@ -0,0 +1,158 @@ +// 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. + +syntax = "proto3"; + +package google.protobuf; + +option csharp_namespace = "Google.Protobuf.WellKnownTypes"; +option go_package = "google.golang.org/protobuf/types/known/anypb"; +option java_package = "com.google.protobuf"; +option java_outer_classname = "AnyProto"; +option java_multiple_files = true; +option objc_class_prefix = "GPB"; + +// `Any` contains an arbitrary serialized protocol buffer message along with a +// URL that describes the type of the serialized message. +// +// Protobuf library provides support to pack/unpack Any values in the form +// of utility functions or additional generated methods of the Any type. +// +// Example 1: Pack and unpack a message in C++. +// +// Foo foo = ...; +// Any any; +// any.PackFrom(foo); +// ... +// if (any.UnpackTo(&foo)) { +// ... +// } +// +// Example 2: Pack and unpack a message in Java. +// +// Foo foo = ...; +// Any any = Any.pack(foo); +// ... +// if (any.is(Foo.class)) { +// foo = any.unpack(Foo.class); +// } +// +// Example 3: Pack and unpack a message in Python. +// +// foo = Foo(...) +// any = Any() +// any.Pack(foo) +// ... +// if any.Is(Foo.DESCRIPTOR): +// any.Unpack(foo) +// ... +// +// Example 4: Pack and unpack a message in Go +// +// foo := &pb.Foo{...} +// any, err := anypb.New(foo) +// if err != nil { +// ... +// } +// ... +// foo := &pb.Foo{} +// if err := any.UnmarshalTo(foo); err != nil { +// ... +// } +// +// The pack methods provided by protobuf library will by default use +// 'type.googleapis.com/full.type.name' as the type URL and the unpack +// methods only use the fully qualified type name after the last '/' +// in the type URL, for example "foo.bar.com/x/y.z" will yield type +// name "y.z". +// +// +// JSON +// +// The JSON representation of an `Any` value uses the regular +// representation of the deserialized, embedded message, with an +// additional field `@type` which contains the type URL. Example: +// +// package google.profile; +// message Person { +// string first_name = 1; +// string last_name = 2; +// } +// +// { +// "@type": "type.googleapis.com/google.profile.Person", +// "firstName": <string>, +// "lastName": <string> +// } +// +// If the embedded message type is well-known and has a custom JSON +// representation, that representation will be embedded adding a field +// `value` which holds the custom JSON in addition to the `@type` +// field. Example (for message [google.protobuf.Duration][]): +// +// { +// "@type": "type.googleapis.com/google.protobuf.Duration", +// "value": "1.212s" +// } +// +message Any { + // A URL/resource name that uniquely identifies the type of the serialized + // protocol buffer message. This string must contain at least + // one "/" character. The last segment of the URL's path must represent + // the fully qualified name of the type (as in + // `path/google.protobuf.Duration`). The name should be in a canonical form + // (e.g., leading "." is not accepted). + // + // In practice, teams usually precompile into the binary all types that they + // expect it to use in the context of Any. However, for URLs which use the + // scheme `http`, `https`, or no scheme, one can optionally set up a type + // server that maps type URLs to message definitions as follows: + // + // * If no scheme is provided, `https` is assumed. + // * An HTTP GET on the URL must yield a [google.protobuf.Type][] + // value in binary format, or produce an error. + // * Applications are allowed to cache lookup results based on the + // URL, or have them precompiled into a binary to avoid any + // lookup. Therefore, binary compatibility needs to be preserved + // on changes to types. (Use versioned type names to manage + // breaking changes.) + // + // Note: this functionality is not currently available in the official + // protobuf release, and it is not used for type URLs beginning with + // type.googleapis.com. + // + // Schemes other than `http`, `https` (or the empty scheme) might be + // used with implementation specific semantics. + // + string type_url = 1; + + // Must be a valid serialized protocol buffer of the above specified type. + bytes value = 2; +} diff --git a/toolkit/components/protobuf/src/google/protobuf/any_lite.cc b/toolkit/components/protobuf/src/google/protobuf/any_lite.cc new file mode 100644 index 0000000000..f283a31b0c --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/any_lite.cc @@ -0,0 +1,96 @@ +// 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. + +#include <google/protobuf/io/zero_copy_stream_impl_lite.h> +#include <google/protobuf/stubs/strutil.h> +#include <google/protobuf/any.h> +#include <google/protobuf/arenastring.h> +#include <google/protobuf/generated_message_util.h> + +namespace google { +namespace protobuf { +namespace internal { + +std::string GetTypeUrl(StringPiece message_name, + StringPiece type_url_prefix) { + if (!type_url_prefix.empty() && + type_url_prefix[type_url_prefix.size() - 1] == '/') { + return StrCat(type_url_prefix, message_name); + } else { + return StrCat(type_url_prefix, "/", message_name); + } +} + +const char kAnyFullTypeName[] = "google.protobuf.Any"; +const char kTypeGoogleApisComPrefix[] = "type.googleapis.com/"; +const char kTypeGoogleProdComPrefix[] = "type.googleprod.com/"; + +bool AnyMetadata::InternalPackFrom(Arena* arena, const MessageLite& message, + StringPiece type_url_prefix, + StringPiece type_name) { + type_url_->Set(GetTypeUrl(type_name, type_url_prefix), arena); + return message.SerializeToString(value_->Mutable(arena)); +} + +bool AnyMetadata::InternalUnpackTo(StringPiece type_name, + MessageLite* message) const { + if (!InternalIs(type_name)) { + return false; + } + return message->ParseFromString(value_->Get()); +} + +bool AnyMetadata::InternalIs(StringPiece type_name) const { + StringPiece type_url = type_url_->Get(); + return type_url.size() >= type_name.size() + 1 && + type_url[type_url.size() - type_name.size() - 1] == '/' && + HasSuffixString(type_url, type_name); +} + +bool ParseAnyTypeUrl(StringPiece type_url, std::string* url_prefix, + std::string* full_type_name) { + size_t pos = type_url.find_last_of('/'); + if (pos == std::string::npos || pos + 1 == type_url.size()) { + return false; + } + if (url_prefix) { + *url_prefix = std::string(type_url.substr(0, pos + 1)); + } + *full_type_name = std::string(type_url.substr(pos + 1)); + return true; +} + +bool ParseAnyTypeUrl(StringPiece type_url, std::string* full_type_name) { + return ParseAnyTypeUrl(type_url, nullptr, full_type_name); +} + +} // namespace internal +} // namespace protobuf +} // namespace google diff --git a/toolkit/components/protobuf/src/google/protobuf/api.pb.cc b/toolkit/components/protobuf/src/google/protobuf/api.pb.cc new file mode 100644 index 0000000000..24b60497cd --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/api.pb.cc @@ -0,0 +1,1309 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: google/protobuf/api.proto + +#include <google/protobuf/api.pb.h> + +#include <algorithm> + +#include <google/protobuf/io/coded_stream.h> +#include <google/protobuf/extension_set.h> +#include <google/protobuf/wire_format_lite.h> +#include <google/protobuf/descriptor.h> +#include <google/protobuf/generated_message_reflection.h> +#include <google/protobuf/reflection_ops.h> +#include <google/protobuf/wire_format.h> +// @@protoc_insertion_point(includes) +#include <google/protobuf/port_def.inc> + +PROTOBUF_PRAGMA_INIT_SEG + +namespace _pb = ::PROTOBUF_NAMESPACE_ID; +namespace _pbi = _pb::internal; + +PROTOBUF_NAMESPACE_OPEN +PROTOBUF_CONSTEXPR Api::Api( + ::_pbi::ConstantInitialized): _impl_{ + /*decltype(_impl_.methods_)*/{} + , /*decltype(_impl_.options_)*/{} + , /*decltype(_impl_.mixins_)*/{} + , /*decltype(_impl_.name_)*/{&::_pbi::fixed_address_empty_string, ::_pbi::ConstantInitialized{}} + , /*decltype(_impl_.version_)*/{&::_pbi::fixed_address_empty_string, ::_pbi::ConstantInitialized{}} + , /*decltype(_impl_.source_context_)*/nullptr + , /*decltype(_impl_.syntax_)*/0 + , /*decltype(_impl_._cached_size_)*/{}} {} +struct ApiDefaultTypeInternal { + PROTOBUF_CONSTEXPR ApiDefaultTypeInternal() + : _instance(::_pbi::ConstantInitialized{}) {} + ~ApiDefaultTypeInternal() {} + union { + Api _instance; + }; +}; +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 ApiDefaultTypeInternal _Api_default_instance_; +PROTOBUF_CONSTEXPR Method::Method( + ::_pbi::ConstantInitialized): _impl_{ + /*decltype(_impl_.options_)*/{} + , /*decltype(_impl_.name_)*/{&::_pbi::fixed_address_empty_string, ::_pbi::ConstantInitialized{}} + , /*decltype(_impl_.request_type_url_)*/{&::_pbi::fixed_address_empty_string, ::_pbi::ConstantInitialized{}} + , /*decltype(_impl_.response_type_url_)*/{&::_pbi::fixed_address_empty_string, ::_pbi::ConstantInitialized{}} + , /*decltype(_impl_.request_streaming_)*/false + , /*decltype(_impl_.response_streaming_)*/false + , /*decltype(_impl_.syntax_)*/0 + , /*decltype(_impl_._cached_size_)*/{}} {} +struct MethodDefaultTypeInternal { + PROTOBUF_CONSTEXPR MethodDefaultTypeInternal() + : _instance(::_pbi::ConstantInitialized{}) {} + ~MethodDefaultTypeInternal() {} + union { + Method _instance; + }; +}; +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 MethodDefaultTypeInternal _Method_default_instance_; +PROTOBUF_CONSTEXPR Mixin::Mixin( + ::_pbi::ConstantInitialized): _impl_{ + /*decltype(_impl_.name_)*/{&::_pbi::fixed_address_empty_string, ::_pbi::ConstantInitialized{}} + , /*decltype(_impl_.root_)*/{&::_pbi::fixed_address_empty_string, ::_pbi::ConstantInitialized{}} + , /*decltype(_impl_._cached_size_)*/{}} {} +struct MixinDefaultTypeInternal { + PROTOBUF_CONSTEXPR MixinDefaultTypeInternal() + : _instance(::_pbi::ConstantInitialized{}) {} + ~MixinDefaultTypeInternal() {} + union { + Mixin _instance; + }; +}; +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 MixinDefaultTypeInternal _Mixin_default_instance_; +PROTOBUF_NAMESPACE_CLOSE +static ::_pb::Metadata file_level_metadata_google_2fprotobuf_2fapi_2eproto[3]; +static constexpr ::_pb::EnumDescriptor const** file_level_enum_descriptors_google_2fprotobuf_2fapi_2eproto = nullptr; +static constexpr ::_pb::ServiceDescriptor const** file_level_service_descriptors_google_2fprotobuf_2fapi_2eproto = nullptr; + +const uint32_t TableStruct_google_2fprotobuf_2fapi_2eproto::offsets[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = { + ~0u, // no _has_bits_ + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Api, _internal_metadata_), + ~0u, // no _extensions_ + ~0u, // no _oneof_case_ + ~0u, // no _weak_field_map_ + ~0u, // no _inlined_string_donated_ + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Api, _impl_.name_), + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Api, _impl_.methods_), + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Api, _impl_.options_), + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Api, _impl_.version_), + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Api, _impl_.source_context_), + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Api, _impl_.mixins_), + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Api, _impl_.syntax_), + ~0u, // no _has_bits_ + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Method, _internal_metadata_), + ~0u, // no _extensions_ + ~0u, // no _oneof_case_ + ~0u, // no _weak_field_map_ + ~0u, // no _inlined_string_donated_ + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Method, _impl_.name_), + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Method, _impl_.request_type_url_), + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Method, _impl_.request_streaming_), + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Method, _impl_.response_type_url_), + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Method, _impl_.response_streaming_), + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Method, _impl_.options_), + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Method, _impl_.syntax_), + ~0u, // no _has_bits_ + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Mixin, _internal_metadata_), + ~0u, // no _extensions_ + ~0u, // no _oneof_case_ + ~0u, // no _weak_field_map_ + ~0u, // no _inlined_string_donated_ + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Mixin, _impl_.name_), + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Mixin, _impl_.root_), +}; +static const ::_pbi::MigrationSchema schemas[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = { + { 0, -1, -1, sizeof(::PROTOBUF_NAMESPACE_ID::Api)}, + { 13, -1, -1, sizeof(::PROTOBUF_NAMESPACE_ID::Method)}, + { 26, -1, -1, sizeof(::PROTOBUF_NAMESPACE_ID::Mixin)}, +}; + +static const ::_pb::Message* const file_default_instances[] = { + &::PROTOBUF_NAMESPACE_ID::_Api_default_instance_._instance, + &::PROTOBUF_NAMESPACE_ID::_Method_default_instance_._instance, + &::PROTOBUF_NAMESPACE_ID::_Mixin_default_instance_._instance, +}; + +const char descriptor_table_protodef_google_2fprotobuf_2fapi_2eproto[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = + "\n\031google/protobuf/api.proto\022\017google.prot" + "obuf\032$google/protobuf/source_context.pro" + "to\032\032google/protobuf/type.proto\"\201\002\n\003Api\022\014" + "\n\004name\030\001 \001(\t\022(\n\007methods\030\002 \003(\0132\027.google.p" + "rotobuf.Method\022(\n\007options\030\003 \003(\0132\027.google" + ".protobuf.Option\022\017\n\007version\030\004 \001(\t\0226\n\016sou" + "rce_context\030\005 \001(\0132\036.google.protobuf.Sour" + "ceContext\022&\n\006mixins\030\006 \003(\0132\026.google.proto" + "buf.Mixin\022\'\n\006syntax\030\007 \001(\0162\027.google.proto" + "buf.Syntax\"\325\001\n\006Method\022\014\n\004name\030\001 \001(\t\022\030\n\020r" + "equest_type_url\030\002 \001(\t\022\031\n\021request_streami" + "ng\030\003 \001(\010\022\031\n\021response_type_url\030\004 \001(\t\022\032\n\022r" + "esponse_streaming\030\005 \001(\010\022(\n\007options\030\006 \003(\013" + "2\027.google.protobuf.Option\022\'\n\006syntax\030\007 \001(" + "\0162\027.google.protobuf.Syntax\"#\n\005Mixin\022\014\n\004n" + "ame\030\001 \001(\t\022\014\n\004root\030\002 \001(\tBv\n\023com.google.pr" + "otobufB\010ApiProtoP\001Z,google.golang.org/pr" + "otobuf/types/known/apipb\242\002\003GPB\252\002\036Google." + "Protobuf.WellKnownTypesb\006proto3" + ; +static const ::_pbi::DescriptorTable* const descriptor_table_google_2fprotobuf_2fapi_2eproto_deps[2] = { + &::descriptor_table_google_2fprotobuf_2fsource_5fcontext_2eproto, + &::descriptor_table_google_2fprotobuf_2ftype_2eproto, +}; +static ::_pbi::once_flag descriptor_table_google_2fprotobuf_2fapi_2eproto_once; +const ::_pbi::DescriptorTable descriptor_table_google_2fprotobuf_2fapi_2eproto = { + false, false, 751, descriptor_table_protodef_google_2fprotobuf_2fapi_2eproto, + "google/protobuf/api.proto", + &descriptor_table_google_2fprotobuf_2fapi_2eproto_once, descriptor_table_google_2fprotobuf_2fapi_2eproto_deps, 2, 3, + schemas, file_default_instances, TableStruct_google_2fprotobuf_2fapi_2eproto::offsets, + file_level_metadata_google_2fprotobuf_2fapi_2eproto, file_level_enum_descriptors_google_2fprotobuf_2fapi_2eproto, + file_level_service_descriptors_google_2fprotobuf_2fapi_2eproto, +}; +PROTOBUF_ATTRIBUTE_WEAK const ::_pbi::DescriptorTable* descriptor_table_google_2fprotobuf_2fapi_2eproto_getter() { + return &descriptor_table_google_2fprotobuf_2fapi_2eproto; +} + +// Force running AddDescriptors() at dynamic initialization time. +PROTOBUF_ATTRIBUTE_INIT_PRIORITY2 static ::_pbi::AddDescriptorsRunner dynamic_init_dummy_google_2fprotobuf_2fapi_2eproto(&descriptor_table_google_2fprotobuf_2fapi_2eproto); +PROTOBUF_NAMESPACE_OPEN + +// =================================================================== + +class Api::_Internal { + public: + static const ::PROTOBUF_NAMESPACE_ID::SourceContext& source_context(const Api* msg); +}; + +const ::PROTOBUF_NAMESPACE_ID::SourceContext& +Api::_Internal::source_context(const Api* msg) { + return *msg->_impl_.source_context_; +} +void Api::clear_options() { + _impl_.options_.Clear(); +} +void Api::clear_source_context() { + if (GetArenaForAllocation() == nullptr && _impl_.source_context_ != nullptr) { + delete _impl_.source_context_; + } + _impl_.source_context_ = nullptr; +} +Api::Api(::PROTOBUF_NAMESPACE_ID::Arena* arena, + bool is_message_owned) + : ::PROTOBUF_NAMESPACE_ID::Message(arena, is_message_owned) { + SharedCtor(arena, is_message_owned); + // @@protoc_insertion_point(arena_constructor:google.protobuf.Api) +} +Api::Api(const Api& from) + : ::PROTOBUF_NAMESPACE_ID::Message() { + Api* const _this = this; (void)_this; + new (&_impl_) Impl_{ + decltype(_impl_.methods_){from._impl_.methods_} + , decltype(_impl_.options_){from._impl_.options_} + , decltype(_impl_.mixins_){from._impl_.mixins_} + , decltype(_impl_.name_){} + , decltype(_impl_.version_){} + , decltype(_impl_.source_context_){nullptr} + , decltype(_impl_.syntax_){} + , /*decltype(_impl_._cached_size_)*/{}}; + + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); + _impl_.name_.InitDefault(); + #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + _impl_.name_.Set("", GetArenaForAllocation()); + #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (!from._internal_name().empty()) { + _this->_impl_.name_.Set(from._internal_name(), + _this->GetArenaForAllocation()); + } + _impl_.version_.InitDefault(); + #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + _impl_.version_.Set("", GetArenaForAllocation()); + #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (!from._internal_version().empty()) { + _this->_impl_.version_.Set(from._internal_version(), + _this->GetArenaForAllocation()); + } + if (from._internal_has_source_context()) { + _this->_impl_.source_context_ = new ::PROTOBUF_NAMESPACE_ID::SourceContext(*from._impl_.source_context_); + } + _this->_impl_.syntax_ = from._impl_.syntax_; + // @@protoc_insertion_point(copy_constructor:google.protobuf.Api) +} + +inline void Api::SharedCtor( + ::_pb::Arena* arena, bool is_message_owned) { + (void)arena; + (void)is_message_owned; + new (&_impl_) Impl_{ + decltype(_impl_.methods_){arena} + , decltype(_impl_.options_){arena} + , decltype(_impl_.mixins_){arena} + , decltype(_impl_.name_){} + , decltype(_impl_.version_){} + , decltype(_impl_.source_context_){nullptr} + , decltype(_impl_.syntax_){0} + , /*decltype(_impl_._cached_size_)*/{} + }; + _impl_.name_.InitDefault(); + #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + _impl_.name_.Set("", GetArenaForAllocation()); + #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + _impl_.version_.InitDefault(); + #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + _impl_.version_.Set("", GetArenaForAllocation()); + #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING +} + +Api::~Api() { + // @@protoc_insertion_point(destructor:google.protobuf.Api) + if (auto *arena = _internal_metadata_.DeleteReturnArena<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>()) { + (void)arena; + return; + } + SharedDtor(); +} + +inline void Api::SharedDtor() { + GOOGLE_DCHECK(GetArenaForAllocation() == nullptr); + _impl_.methods_.~RepeatedPtrField(); + _impl_.options_.~RepeatedPtrField(); + _impl_.mixins_.~RepeatedPtrField(); + _impl_.name_.Destroy(); + _impl_.version_.Destroy(); + if (this != internal_default_instance()) delete _impl_.source_context_; +} + +void Api::SetCachedSize(int size) const { + _impl_._cached_size_.Set(size); +} + +void Api::Clear() { +// @@protoc_insertion_point(message_clear_start:google.protobuf.Api) + uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + _impl_.methods_.Clear(); + _impl_.options_.Clear(); + _impl_.mixins_.Clear(); + _impl_.name_.ClearToEmpty(); + _impl_.version_.ClearToEmpty(); + if (GetArenaForAllocation() == nullptr && _impl_.source_context_ != nullptr) { + delete _impl_.source_context_; + } + _impl_.source_context_ = nullptr; + _impl_.syntax_ = 0; + _internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); +} + +const char* Api::_InternalParse(const char* ptr, ::_pbi::ParseContext* ctx) { +#define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure + while (!ctx->Done(&ptr)) { + uint32_t tag; + ptr = ::_pbi::ReadTag(ptr, &tag); + switch (tag >> 3) { + // string name = 1; + case 1: + if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 10)) { + auto str = _internal_mutable_name(); + ptr = ::_pbi::InlineGreedyStringParser(str, ptr, ctx); + CHK_(ptr); + CHK_(::_pbi::VerifyUTF8(str, "google.protobuf.Api.name")); + } else + goto handle_unusual; + continue; + // repeated .google.protobuf.Method methods = 2; + case 2: + if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 18)) { + ptr -= 1; + do { + ptr += 1; + ptr = ctx->ParseMessage(_internal_add_methods(), ptr); + CHK_(ptr); + if (!ctx->DataAvailable(ptr)) break; + } while (::PROTOBUF_NAMESPACE_ID::internal::ExpectTag<18>(ptr)); + } else + goto handle_unusual; + continue; + // repeated .google.protobuf.Option options = 3; + case 3: + if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 26)) { + ptr -= 1; + do { + ptr += 1; + ptr = ctx->ParseMessage(_internal_add_options(), ptr); + CHK_(ptr); + if (!ctx->DataAvailable(ptr)) break; + } while (::PROTOBUF_NAMESPACE_ID::internal::ExpectTag<26>(ptr)); + } else + goto handle_unusual; + continue; + // string version = 4; + case 4: + if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 34)) { + auto str = _internal_mutable_version(); + ptr = ::_pbi::InlineGreedyStringParser(str, ptr, ctx); + CHK_(ptr); + CHK_(::_pbi::VerifyUTF8(str, "google.protobuf.Api.version")); + } else + goto handle_unusual; + continue; + // .google.protobuf.SourceContext source_context = 5; + case 5: + if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 42)) { + ptr = ctx->ParseMessage(_internal_mutable_source_context(), ptr); + CHK_(ptr); + } else + goto handle_unusual; + continue; + // repeated .google.protobuf.Mixin mixins = 6; + case 6: + if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 50)) { + ptr -= 1; + do { + ptr += 1; + ptr = ctx->ParseMessage(_internal_add_mixins(), ptr); + CHK_(ptr); + if (!ctx->DataAvailable(ptr)) break; + } while (::PROTOBUF_NAMESPACE_ID::internal::ExpectTag<50>(ptr)); + } else + goto handle_unusual; + continue; + // .google.protobuf.Syntax syntax = 7; + case 7: + if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 56)) { + uint64_t val = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr); + CHK_(ptr); + _internal_set_syntax(static_cast<::PROTOBUF_NAMESPACE_ID::Syntax>(val)); + } else + goto handle_unusual; + continue; + default: + goto handle_unusual; + } // switch + handle_unusual: + if ((tag == 0) || ((tag & 7) == 4)) { + CHK_(ptr); + ctx->SetLastTag(tag); + goto message_done; + } + ptr = UnknownFieldParse( + tag, + _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(), + ptr, ctx); + CHK_(ptr != nullptr); + } // while +message_done: + return ptr; +failure: + ptr = nullptr; + goto message_done; +#undef CHK_ +} + +uint8_t* Api::_InternalSerialize( + uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const { + // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.Api) + uint32_t cached_has_bits = 0; + (void) cached_has_bits; + + // string name = 1; + if (!this->_internal_name().empty()) { + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::VerifyUtf8String( + this->_internal_name().data(), static_cast<int>(this->_internal_name().length()), + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::SERIALIZE, + "google.protobuf.Api.name"); + target = stream->WriteStringMaybeAliased( + 1, this->_internal_name(), target); + } + + // repeated .google.protobuf.Method methods = 2; + for (unsigned i = 0, + n = static_cast<unsigned>(this->_internal_methods_size()); i < n; i++) { + const auto& repfield = this->_internal_methods(i); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite:: + InternalWriteMessage(2, repfield, repfield.GetCachedSize(), target, stream); + } + + // repeated .google.protobuf.Option options = 3; + for (unsigned i = 0, + n = static_cast<unsigned>(this->_internal_options_size()); i < n; i++) { + const auto& repfield = this->_internal_options(i); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite:: + InternalWriteMessage(3, repfield, repfield.GetCachedSize(), target, stream); + } + + // string version = 4; + if (!this->_internal_version().empty()) { + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::VerifyUtf8String( + this->_internal_version().data(), static_cast<int>(this->_internal_version().length()), + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::SERIALIZE, + "google.protobuf.Api.version"); + target = stream->WriteStringMaybeAliased( + 4, this->_internal_version(), target); + } + + // .google.protobuf.SourceContext source_context = 5; + if (this->_internal_has_source_context()) { + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite:: + InternalWriteMessage(5, _Internal::source_context(this), + _Internal::source_context(this).GetCachedSize(), target, stream); + } + + // repeated .google.protobuf.Mixin mixins = 6; + for (unsigned i = 0, + n = static_cast<unsigned>(this->_internal_mixins_size()); i < n; i++) { + const auto& repfield = this->_internal_mixins(i); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite:: + InternalWriteMessage(6, repfield, repfield.GetCachedSize(), target, stream); + } + + // .google.protobuf.Syntax syntax = 7; + if (this->_internal_syntax() != 0) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteEnumToArray( + 7, this->_internal_syntax(), target); + } + + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + target = ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( + _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.Api) + return target; +} + +size_t Api::ByteSizeLong() const { +// @@protoc_insertion_point(message_byte_size_start:google.protobuf.Api) + size_t total_size = 0; + + uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + // repeated .google.protobuf.Method methods = 2; + total_size += 1UL * this->_internal_methods_size(); + for (const auto& msg : this->_impl_.methods_) { + total_size += + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::MessageSize(msg); + } + + // repeated .google.protobuf.Option options = 3; + total_size += 1UL * this->_internal_options_size(); + for (const auto& msg : this->_impl_.options_) { + total_size += + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::MessageSize(msg); + } + + // repeated .google.protobuf.Mixin mixins = 6; + total_size += 1UL * this->_internal_mixins_size(); + for (const auto& msg : this->_impl_.mixins_) { + total_size += + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::MessageSize(msg); + } + + // string name = 1; + if (!this->_internal_name().empty()) { + total_size += 1 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize( + this->_internal_name()); + } + + // string version = 4; + if (!this->_internal_version().empty()) { + total_size += 1 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize( + this->_internal_version()); + } + + // .google.protobuf.SourceContext source_context = 5; + if (this->_internal_has_source_context()) { + total_size += 1 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::MessageSize( + *_impl_.source_context_); + } + + // .google.protobuf.Syntax syntax = 7; + if (this->_internal_syntax() != 0) { + total_size += 1 + + ::_pbi::WireFormatLite::EnumSize(this->_internal_syntax()); + } + + return MaybeComputeUnknownFieldsSize(total_size, &_impl_._cached_size_); +} + +const ::PROTOBUF_NAMESPACE_ID::Message::ClassData Api::_class_data_ = { + ::PROTOBUF_NAMESPACE_ID::Message::CopyWithSourceCheck, + Api::MergeImpl +}; +const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*Api::GetClassData() const { return &_class_data_; } + + +void Api::MergeImpl(::PROTOBUF_NAMESPACE_ID::Message& to_msg, const ::PROTOBUF_NAMESPACE_ID::Message& from_msg) { + auto* const _this = static_cast<Api*>(&to_msg); + auto& from = static_cast<const Api&>(from_msg); + // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.Api) + GOOGLE_DCHECK_NE(&from, _this); + uint32_t cached_has_bits = 0; + (void) cached_has_bits; + + _this->_impl_.methods_.MergeFrom(from._impl_.methods_); + _this->_impl_.options_.MergeFrom(from._impl_.options_); + _this->_impl_.mixins_.MergeFrom(from._impl_.mixins_); + if (!from._internal_name().empty()) { + _this->_internal_set_name(from._internal_name()); + } + if (!from._internal_version().empty()) { + _this->_internal_set_version(from._internal_version()); + } + if (from._internal_has_source_context()) { + _this->_internal_mutable_source_context()->::PROTOBUF_NAMESPACE_ID::SourceContext::MergeFrom( + from._internal_source_context()); + } + if (from._internal_syntax() != 0) { + _this->_internal_set_syntax(from._internal_syntax()); + } + _this->_internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); +} + +void Api::CopyFrom(const Api& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.Api) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool Api::IsInitialized() const { + return true; +} + +void Api::InternalSwap(Api* other) { + using std::swap; + auto* lhs_arena = GetArenaForAllocation(); + auto* rhs_arena = other->GetArenaForAllocation(); + _internal_metadata_.InternalSwap(&other->_internal_metadata_); + _impl_.methods_.InternalSwap(&other->_impl_.methods_); + _impl_.options_.InternalSwap(&other->_impl_.options_); + _impl_.mixins_.InternalSwap(&other->_impl_.mixins_); + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::InternalSwap( + &_impl_.name_, lhs_arena, + &other->_impl_.name_, rhs_arena + ); + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::InternalSwap( + &_impl_.version_, lhs_arena, + &other->_impl_.version_, rhs_arena + ); + ::PROTOBUF_NAMESPACE_ID::internal::memswap< + PROTOBUF_FIELD_OFFSET(Api, _impl_.syntax_) + + sizeof(Api::_impl_.syntax_) + - PROTOBUF_FIELD_OFFSET(Api, _impl_.source_context_)>( + reinterpret_cast<char*>(&_impl_.source_context_), + reinterpret_cast<char*>(&other->_impl_.source_context_)); +} + +::PROTOBUF_NAMESPACE_ID::Metadata Api::GetMetadata() const { + return ::_pbi::AssignDescriptors( + &descriptor_table_google_2fprotobuf_2fapi_2eproto_getter, &descriptor_table_google_2fprotobuf_2fapi_2eproto_once, + file_level_metadata_google_2fprotobuf_2fapi_2eproto[0]); +} + +// =================================================================== + +class Method::_Internal { + public: +}; + +void Method::clear_options() { + _impl_.options_.Clear(); +} +Method::Method(::PROTOBUF_NAMESPACE_ID::Arena* arena, + bool is_message_owned) + : ::PROTOBUF_NAMESPACE_ID::Message(arena, is_message_owned) { + SharedCtor(arena, is_message_owned); + // @@protoc_insertion_point(arena_constructor:google.protobuf.Method) +} +Method::Method(const Method& from) + : ::PROTOBUF_NAMESPACE_ID::Message() { + Method* const _this = this; (void)_this; + new (&_impl_) Impl_{ + decltype(_impl_.options_){from._impl_.options_} + , decltype(_impl_.name_){} + , decltype(_impl_.request_type_url_){} + , decltype(_impl_.response_type_url_){} + , decltype(_impl_.request_streaming_){} + , decltype(_impl_.response_streaming_){} + , decltype(_impl_.syntax_){} + , /*decltype(_impl_._cached_size_)*/{}}; + + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); + _impl_.name_.InitDefault(); + #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + _impl_.name_.Set("", GetArenaForAllocation()); + #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (!from._internal_name().empty()) { + _this->_impl_.name_.Set(from._internal_name(), + _this->GetArenaForAllocation()); + } + _impl_.request_type_url_.InitDefault(); + #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + _impl_.request_type_url_.Set("", GetArenaForAllocation()); + #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (!from._internal_request_type_url().empty()) { + _this->_impl_.request_type_url_.Set(from._internal_request_type_url(), + _this->GetArenaForAllocation()); + } + _impl_.response_type_url_.InitDefault(); + #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + _impl_.response_type_url_.Set("", GetArenaForAllocation()); + #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (!from._internal_response_type_url().empty()) { + _this->_impl_.response_type_url_.Set(from._internal_response_type_url(), + _this->GetArenaForAllocation()); + } + ::memcpy(&_impl_.request_streaming_, &from._impl_.request_streaming_, + static_cast<size_t>(reinterpret_cast<char*>(&_impl_.syntax_) - + reinterpret_cast<char*>(&_impl_.request_streaming_)) + sizeof(_impl_.syntax_)); + // @@protoc_insertion_point(copy_constructor:google.protobuf.Method) +} + +inline void Method::SharedCtor( + ::_pb::Arena* arena, bool is_message_owned) { + (void)arena; + (void)is_message_owned; + new (&_impl_) Impl_{ + decltype(_impl_.options_){arena} + , decltype(_impl_.name_){} + , decltype(_impl_.request_type_url_){} + , decltype(_impl_.response_type_url_){} + , decltype(_impl_.request_streaming_){false} + , decltype(_impl_.response_streaming_){false} + , decltype(_impl_.syntax_){0} + , /*decltype(_impl_._cached_size_)*/{} + }; + _impl_.name_.InitDefault(); + #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + _impl_.name_.Set("", GetArenaForAllocation()); + #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + _impl_.request_type_url_.InitDefault(); + #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + _impl_.request_type_url_.Set("", GetArenaForAllocation()); + #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + _impl_.response_type_url_.InitDefault(); + #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + _impl_.response_type_url_.Set("", GetArenaForAllocation()); + #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING +} + +Method::~Method() { + // @@protoc_insertion_point(destructor:google.protobuf.Method) + if (auto *arena = _internal_metadata_.DeleteReturnArena<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>()) { + (void)arena; + return; + } + SharedDtor(); +} + +inline void Method::SharedDtor() { + GOOGLE_DCHECK(GetArenaForAllocation() == nullptr); + _impl_.options_.~RepeatedPtrField(); + _impl_.name_.Destroy(); + _impl_.request_type_url_.Destroy(); + _impl_.response_type_url_.Destroy(); +} + +void Method::SetCachedSize(int size) const { + _impl_._cached_size_.Set(size); +} + +void Method::Clear() { +// @@protoc_insertion_point(message_clear_start:google.protobuf.Method) + uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + _impl_.options_.Clear(); + _impl_.name_.ClearToEmpty(); + _impl_.request_type_url_.ClearToEmpty(); + _impl_.response_type_url_.ClearToEmpty(); + ::memset(&_impl_.request_streaming_, 0, static_cast<size_t>( + reinterpret_cast<char*>(&_impl_.syntax_) - + reinterpret_cast<char*>(&_impl_.request_streaming_)) + sizeof(_impl_.syntax_)); + _internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); +} + +const char* Method::_InternalParse(const char* ptr, ::_pbi::ParseContext* ctx) { +#define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure + while (!ctx->Done(&ptr)) { + uint32_t tag; + ptr = ::_pbi::ReadTag(ptr, &tag); + switch (tag >> 3) { + // string name = 1; + case 1: + if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 10)) { + auto str = _internal_mutable_name(); + ptr = ::_pbi::InlineGreedyStringParser(str, ptr, ctx); + CHK_(ptr); + CHK_(::_pbi::VerifyUTF8(str, "google.protobuf.Method.name")); + } else + goto handle_unusual; + continue; + // string request_type_url = 2; + case 2: + if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 18)) { + auto str = _internal_mutable_request_type_url(); + ptr = ::_pbi::InlineGreedyStringParser(str, ptr, ctx); + CHK_(ptr); + CHK_(::_pbi::VerifyUTF8(str, "google.protobuf.Method.request_type_url")); + } else + goto handle_unusual; + continue; + // bool request_streaming = 3; + case 3: + if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 24)) { + _impl_.request_streaming_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr); + CHK_(ptr); + } else + goto handle_unusual; + continue; + // string response_type_url = 4; + case 4: + if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 34)) { + auto str = _internal_mutable_response_type_url(); + ptr = ::_pbi::InlineGreedyStringParser(str, ptr, ctx); + CHK_(ptr); + CHK_(::_pbi::VerifyUTF8(str, "google.protobuf.Method.response_type_url")); + } else + goto handle_unusual; + continue; + // bool response_streaming = 5; + case 5: + if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 40)) { + _impl_.response_streaming_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr); + CHK_(ptr); + } else + goto handle_unusual; + continue; + // repeated .google.protobuf.Option options = 6; + case 6: + if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 50)) { + ptr -= 1; + do { + ptr += 1; + ptr = ctx->ParseMessage(_internal_add_options(), ptr); + CHK_(ptr); + if (!ctx->DataAvailable(ptr)) break; + } while (::PROTOBUF_NAMESPACE_ID::internal::ExpectTag<50>(ptr)); + } else + goto handle_unusual; + continue; + // .google.protobuf.Syntax syntax = 7; + case 7: + if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 56)) { + uint64_t val = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr); + CHK_(ptr); + _internal_set_syntax(static_cast<::PROTOBUF_NAMESPACE_ID::Syntax>(val)); + } else + goto handle_unusual; + continue; + default: + goto handle_unusual; + } // switch + handle_unusual: + if ((tag == 0) || ((tag & 7) == 4)) { + CHK_(ptr); + ctx->SetLastTag(tag); + goto message_done; + } + ptr = UnknownFieldParse( + tag, + _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(), + ptr, ctx); + CHK_(ptr != nullptr); + } // while +message_done: + return ptr; +failure: + ptr = nullptr; + goto message_done; +#undef CHK_ +} + +uint8_t* Method::_InternalSerialize( + uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const { + // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.Method) + uint32_t cached_has_bits = 0; + (void) cached_has_bits; + + // string name = 1; + if (!this->_internal_name().empty()) { + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::VerifyUtf8String( + this->_internal_name().data(), static_cast<int>(this->_internal_name().length()), + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::SERIALIZE, + "google.protobuf.Method.name"); + target = stream->WriteStringMaybeAliased( + 1, this->_internal_name(), target); + } + + // string request_type_url = 2; + if (!this->_internal_request_type_url().empty()) { + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::VerifyUtf8String( + this->_internal_request_type_url().data(), static_cast<int>(this->_internal_request_type_url().length()), + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::SERIALIZE, + "google.protobuf.Method.request_type_url"); + target = stream->WriteStringMaybeAliased( + 2, this->_internal_request_type_url(), target); + } + + // bool request_streaming = 3; + if (this->_internal_request_streaming() != 0) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteBoolToArray(3, this->_internal_request_streaming(), target); + } + + // string response_type_url = 4; + if (!this->_internal_response_type_url().empty()) { + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::VerifyUtf8String( + this->_internal_response_type_url().data(), static_cast<int>(this->_internal_response_type_url().length()), + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::SERIALIZE, + "google.protobuf.Method.response_type_url"); + target = stream->WriteStringMaybeAliased( + 4, this->_internal_response_type_url(), target); + } + + // bool response_streaming = 5; + if (this->_internal_response_streaming() != 0) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteBoolToArray(5, this->_internal_response_streaming(), target); + } + + // repeated .google.protobuf.Option options = 6; + for (unsigned i = 0, + n = static_cast<unsigned>(this->_internal_options_size()); i < n; i++) { + const auto& repfield = this->_internal_options(i); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite:: + InternalWriteMessage(6, repfield, repfield.GetCachedSize(), target, stream); + } + + // .google.protobuf.Syntax syntax = 7; + if (this->_internal_syntax() != 0) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteEnumToArray( + 7, this->_internal_syntax(), target); + } + + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + target = ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( + _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.Method) + return target; +} + +size_t Method::ByteSizeLong() const { +// @@protoc_insertion_point(message_byte_size_start:google.protobuf.Method) + size_t total_size = 0; + + uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + // repeated .google.protobuf.Option options = 6; + total_size += 1UL * this->_internal_options_size(); + for (const auto& msg : this->_impl_.options_) { + total_size += + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::MessageSize(msg); + } + + // string name = 1; + if (!this->_internal_name().empty()) { + total_size += 1 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize( + this->_internal_name()); + } + + // string request_type_url = 2; + if (!this->_internal_request_type_url().empty()) { + total_size += 1 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize( + this->_internal_request_type_url()); + } + + // string response_type_url = 4; + if (!this->_internal_response_type_url().empty()) { + total_size += 1 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize( + this->_internal_response_type_url()); + } + + // bool request_streaming = 3; + if (this->_internal_request_streaming() != 0) { + total_size += 1 + 1; + } + + // bool response_streaming = 5; + if (this->_internal_response_streaming() != 0) { + total_size += 1 + 1; + } + + // .google.protobuf.Syntax syntax = 7; + if (this->_internal_syntax() != 0) { + total_size += 1 + + ::_pbi::WireFormatLite::EnumSize(this->_internal_syntax()); + } + + return MaybeComputeUnknownFieldsSize(total_size, &_impl_._cached_size_); +} + +const ::PROTOBUF_NAMESPACE_ID::Message::ClassData Method::_class_data_ = { + ::PROTOBUF_NAMESPACE_ID::Message::CopyWithSourceCheck, + Method::MergeImpl +}; +const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*Method::GetClassData() const { return &_class_data_; } + + +void Method::MergeImpl(::PROTOBUF_NAMESPACE_ID::Message& to_msg, const ::PROTOBUF_NAMESPACE_ID::Message& from_msg) { + auto* const _this = static_cast<Method*>(&to_msg); + auto& from = static_cast<const Method&>(from_msg); + // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.Method) + GOOGLE_DCHECK_NE(&from, _this); + uint32_t cached_has_bits = 0; + (void) cached_has_bits; + + _this->_impl_.options_.MergeFrom(from._impl_.options_); + if (!from._internal_name().empty()) { + _this->_internal_set_name(from._internal_name()); + } + if (!from._internal_request_type_url().empty()) { + _this->_internal_set_request_type_url(from._internal_request_type_url()); + } + if (!from._internal_response_type_url().empty()) { + _this->_internal_set_response_type_url(from._internal_response_type_url()); + } + if (from._internal_request_streaming() != 0) { + _this->_internal_set_request_streaming(from._internal_request_streaming()); + } + if (from._internal_response_streaming() != 0) { + _this->_internal_set_response_streaming(from._internal_response_streaming()); + } + if (from._internal_syntax() != 0) { + _this->_internal_set_syntax(from._internal_syntax()); + } + _this->_internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); +} + +void Method::CopyFrom(const Method& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.Method) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool Method::IsInitialized() const { + return true; +} + +void Method::InternalSwap(Method* other) { + using std::swap; + auto* lhs_arena = GetArenaForAllocation(); + auto* rhs_arena = other->GetArenaForAllocation(); + _internal_metadata_.InternalSwap(&other->_internal_metadata_); + _impl_.options_.InternalSwap(&other->_impl_.options_); + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::InternalSwap( + &_impl_.name_, lhs_arena, + &other->_impl_.name_, rhs_arena + ); + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::InternalSwap( + &_impl_.request_type_url_, lhs_arena, + &other->_impl_.request_type_url_, rhs_arena + ); + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::InternalSwap( + &_impl_.response_type_url_, lhs_arena, + &other->_impl_.response_type_url_, rhs_arena + ); + ::PROTOBUF_NAMESPACE_ID::internal::memswap< + PROTOBUF_FIELD_OFFSET(Method, _impl_.syntax_) + + sizeof(Method::_impl_.syntax_) + - PROTOBUF_FIELD_OFFSET(Method, _impl_.request_streaming_)>( + reinterpret_cast<char*>(&_impl_.request_streaming_), + reinterpret_cast<char*>(&other->_impl_.request_streaming_)); +} + +::PROTOBUF_NAMESPACE_ID::Metadata Method::GetMetadata() const { + return ::_pbi::AssignDescriptors( + &descriptor_table_google_2fprotobuf_2fapi_2eproto_getter, &descriptor_table_google_2fprotobuf_2fapi_2eproto_once, + file_level_metadata_google_2fprotobuf_2fapi_2eproto[1]); +} + +// =================================================================== + +class Mixin::_Internal { + public: +}; + +Mixin::Mixin(::PROTOBUF_NAMESPACE_ID::Arena* arena, + bool is_message_owned) + : ::PROTOBUF_NAMESPACE_ID::Message(arena, is_message_owned) { + SharedCtor(arena, is_message_owned); + // @@protoc_insertion_point(arena_constructor:google.protobuf.Mixin) +} +Mixin::Mixin(const Mixin& from) + : ::PROTOBUF_NAMESPACE_ID::Message() { + Mixin* const _this = this; (void)_this; + new (&_impl_) Impl_{ + decltype(_impl_.name_){} + , decltype(_impl_.root_){} + , /*decltype(_impl_._cached_size_)*/{}}; + + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); + _impl_.name_.InitDefault(); + #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + _impl_.name_.Set("", GetArenaForAllocation()); + #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (!from._internal_name().empty()) { + _this->_impl_.name_.Set(from._internal_name(), + _this->GetArenaForAllocation()); + } + _impl_.root_.InitDefault(); + #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + _impl_.root_.Set("", GetArenaForAllocation()); + #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (!from._internal_root().empty()) { + _this->_impl_.root_.Set(from._internal_root(), + _this->GetArenaForAllocation()); + } + // @@protoc_insertion_point(copy_constructor:google.protobuf.Mixin) +} + +inline void Mixin::SharedCtor( + ::_pb::Arena* arena, bool is_message_owned) { + (void)arena; + (void)is_message_owned; + new (&_impl_) Impl_{ + decltype(_impl_.name_){} + , decltype(_impl_.root_){} + , /*decltype(_impl_._cached_size_)*/{} + }; + _impl_.name_.InitDefault(); + #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + _impl_.name_.Set("", GetArenaForAllocation()); + #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + _impl_.root_.InitDefault(); + #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + _impl_.root_.Set("", GetArenaForAllocation()); + #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING +} + +Mixin::~Mixin() { + // @@protoc_insertion_point(destructor:google.protobuf.Mixin) + if (auto *arena = _internal_metadata_.DeleteReturnArena<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>()) { + (void)arena; + return; + } + SharedDtor(); +} + +inline void Mixin::SharedDtor() { + GOOGLE_DCHECK(GetArenaForAllocation() == nullptr); + _impl_.name_.Destroy(); + _impl_.root_.Destroy(); +} + +void Mixin::SetCachedSize(int size) const { + _impl_._cached_size_.Set(size); +} + +void Mixin::Clear() { +// @@protoc_insertion_point(message_clear_start:google.protobuf.Mixin) + uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + _impl_.name_.ClearToEmpty(); + _impl_.root_.ClearToEmpty(); + _internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); +} + +const char* Mixin::_InternalParse(const char* ptr, ::_pbi::ParseContext* ctx) { +#define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure + while (!ctx->Done(&ptr)) { + uint32_t tag; + ptr = ::_pbi::ReadTag(ptr, &tag); + switch (tag >> 3) { + // string name = 1; + case 1: + if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 10)) { + auto str = _internal_mutable_name(); + ptr = ::_pbi::InlineGreedyStringParser(str, ptr, ctx); + CHK_(ptr); + CHK_(::_pbi::VerifyUTF8(str, "google.protobuf.Mixin.name")); + } else + goto handle_unusual; + continue; + // string root = 2; + case 2: + if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 18)) { + auto str = _internal_mutable_root(); + ptr = ::_pbi::InlineGreedyStringParser(str, ptr, ctx); + CHK_(ptr); + CHK_(::_pbi::VerifyUTF8(str, "google.protobuf.Mixin.root")); + } else + goto handle_unusual; + continue; + default: + goto handle_unusual; + } // switch + handle_unusual: + if ((tag == 0) || ((tag & 7) == 4)) { + CHK_(ptr); + ctx->SetLastTag(tag); + goto message_done; + } + ptr = UnknownFieldParse( + tag, + _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(), + ptr, ctx); + CHK_(ptr != nullptr); + } // while +message_done: + return ptr; +failure: + ptr = nullptr; + goto message_done; +#undef CHK_ +} + +uint8_t* Mixin::_InternalSerialize( + uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const { + // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.Mixin) + uint32_t cached_has_bits = 0; + (void) cached_has_bits; + + // string name = 1; + if (!this->_internal_name().empty()) { + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::VerifyUtf8String( + this->_internal_name().data(), static_cast<int>(this->_internal_name().length()), + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::SERIALIZE, + "google.protobuf.Mixin.name"); + target = stream->WriteStringMaybeAliased( + 1, this->_internal_name(), target); + } + + // string root = 2; + if (!this->_internal_root().empty()) { + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::VerifyUtf8String( + this->_internal_root().data(), static_cast<int>(this->_internal_root().length()), + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::SERIALIZE, + "google.protobuf.Mixin.root"); + target = stream->WriteStringMaybeAliased( + 2, this->_internal_root(), target); + } + + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + target = ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( + _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.Mixin) + return target; +} + +size_t Mixin::ByteSizeLong() const { +// @@protoc_insertion_point(message_byte_size_start:google.protobuf.Mixin) + size_t total_size = 0; + + uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + // string name = 1; + if (!this->_internal_name().empty()) { + total_size += 1 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize( + this->_internal_name()); + } + + // string root = 2; + if (!this->_internal_root().empty()) { + total_size += 1 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize( + this->_internal_root()); + } + + return MaybeComputeUnknownFieldsSize(total_size, &_impl_._cached_size_); +} + +const ::PROTOBUF_NAMESPACE_ID::Message::ClassData Mixin::_class_data_ = { + ::PROTOBUF_NAMESPACE_ID::Message::CopyWithSourceCheck, + Mixin::MergeImpl +}; +const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*Mixin::GetClassData() const { return &_class_data_; } + + +void Mixin::MergeImpl(::PROTOBUF_NAMESPACE_ID::Message& to_msg, const ::PROTOBUF_NAMESPACE_ID::Message& from_msg) { + auto* const _this = static_cast<Mixin*>(&to_msg); + auto& from = static_cast<const Mixin&>(from_msg); + // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.Mixin) + GOOGLE_DCHECK_NE(&from, _this); + uint32_t cached_has_bits = 0; + (void) cached_has_bits; + + if (!from._internal_name().empty()) { + _this->_internal_set_name(from._internal_name()); + } + if (!from._internal_root().empty()) { + _this->_internal_set_root(from._internal_root()); + } + _this->_internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); +} + +void Mixin::CopyFrom(const Mixin& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.Mixin) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool Mixin::IsInitialized() const { + return true; +} + +void Mixin::InternalSwap(Mixin* other) { + using std::swap; + auto* lhs_arena = GetArenaForAllocation(); + auto* rhs_arena = other->GetArenaForAllocation(); + _internal_metadata_.InternalSwap(&other->_internal_metadata_); + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::InternalSwap( + &_impl_.name_, lhs_arena, + &other->_impl_.name_, rhs_arena + ); + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::InternalSwap( + &_impl_.root_, lhs_arena, + &other->_impl_.root_, rhs_arena + ); +} + +::PROTOBUF_NAMESPACE_ID::Metadata Mixin::GetMetadata() const { + return ::_pbi::AssignDescriptors( + &descriptor_table_google_2fprotobuf_2fapi_2eproto_getter, &descriptor_table_google_2fprotobuf_2fapi_2eproto_once, + file_level_metadata_google_2fprotobuf_2fapi_2eproto[2]); +} + +// @@protoc_insertion_point(namespace_scope) +PROTOBUF_NAMESPACE_CLOSE +PROTOBUF_NAMESPACE_OPEN +template<> PROTOBUF_NOINLINE ::PROTOBUF_NAMESPACE_ID::Api* +Arena::CreateMaybeMessage< ::PROTOBUF_NAMESPACE_ID::Api >(Arena* arena) { + return Arena::CreateMessageInternal< ::PROTOBUF_NAMESPACE_ID::Api >(arena); +} +template<> PROTOBUF_NOINLINE ::PROTOBUF_NAMESPACE_ID::Method* +Arena::CreateMaybeMessage< ::PROTOBUF_NAMESPACE_ID::Method >(Arena* arena) { + return Arena::CreateMessageInternal< ::PROTOBUF_NAMESPACE_ID::Method >(arena); +} +template<> PROTOBUF_NOINLINE ::PROTOBUF_NAMESPACE_ID::Mixin* +Arena::CreateMaybeMessage< ::PROTOBUF_NAMESPACE_ID::Mixin >(Arena* arena) { + return Arena::CreateMessageInternal< ::PROTOBUF_NAMESPACE_ID::Mixin >(arena); +} +PROTOBUF_NAMESPACE_CLOSE + +// @@protoc_insertion_point(global_scope) +#include <google/protobuf/port_undef.inc> diff --git a/toolkit/components/protobuf/src/google/protobuf/api.pb.h b/toolkit/components/protobuf/src/google/protobuf/api.pb.h new file mode 100644 index 0000000000..348bac8882 --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/api.pb.h @@ -0,0 +1,1437 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: google/protobuf/api.proto + +#ifndef GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2fapi_2eproto +#define GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2fapi_2eproto + +#include <limits> +#include <string> + +#include <google/protobuf/port_def.inc> +#if PROTOBUF_VERSION < 3021000 +#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 3021006 < 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. +#endif + +#include <google/protobuf/port_undef.inc> +#include <google/protobuf/io/coded_stream.h> +#include <google/protobuf/arena.h> +#include <google/protobuf/arenastring.h> +#include <google/protobuf/generated_message_util.h> +#include <google/protobuf/metadata_lite.h> +#include <google/protobuf/generated_message_reflection.h> +#include <google/protobuf/message.h> +#include <google/protobuf/repeated_field.h> // IWYU pragma: export +#include <google/protobuf/extension_set.h> // IWYU pragma: export +#include <google/protobuf/unknown_field_set.h> +#include <google/protobuf/source_context.pb.h> +#include <google/protobuf/type.pb.h> +// @@protoc_insertion_point(includes) +#include <google/protobuf/port_def.inc> +#define PROTOBUF_INTERNAL_EXPORT_google_2fprotobuf_2fapi_2eproto PROTOBUF_EXPORT +PROTOBUF_NAMESPACE_OPEN +namespace internal { +class AnyMetadata; +} // namespace internal +PROTOBUF_NAMESPACE_CLOSE + +// Internal implementation detail -- do not use these members. +struct PROTOBUF_EXPORT TableStruct_google_2fprotobuf_2fapi_2eproto { + static const uint32_t offsets[]; +}; +PROTOBUF_EXPORT extern const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable descriptor_table_google_2fprotobuf_2fapi_2eproto; +PROTOBUF_NAMESPACE_OPEN +class Api; +struct ApiDefaultTypeInternal; +PROTOBUF_EXPORT extern ApiDefaultTypeInternal _Api_default_instance_; +class Method; +struct MethodDefaultTypeInternal; +PROTOBUF_EXPORT extern MethodDefaultTypeInternal _Method_default_instance_; +class Mixin; +struct MixinDefaultTypeInternal; +PROTOBUF_EXPORT extern MixinDefaultTypeInternal _Mixin_default_instance_; +PROTOBUF_NAMESPACE_CLOSE +PROTOBUF_NAMESPACE_OPEN +template<> PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::Api* Arena::CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::Api>(Arena*); +template<> PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::Method* Arena::CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::Method>(Arena*); +template<> PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::Mixin* Arena::CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::Mixin>(Arena*); +PROTOBUF_NAMESPACE_CLOSE +PROTOBUF_NAMESPACE_OPEN + +// =================================================================== + +class PROTOBUF_EXPORT Api final : + public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.Api) */ { + public: + inline Api() : Api(nullptr) {} + ~Api() override; + explicit PROTOBUF_CONSTEXPR Api(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized); + + Api(const Api& from); + Api(Api&& from) noexcept + : Api() { + *this = ::std::move(from); + } + + inline Api& operator=(const Api& from) { + CopyFrom(from); + return *this; + } + inline Api& operator=(Api&& from) noexcept { + if (this == &from) return *this; + if (GetOwningArena() == from.GetOwningArena() + #ifdef PROTOBUF_FORCE_COPY_IN_MOVE + && GetOwningArena() != nullptr + #endif // !PROTOBUF_FORCE_COPY_IN_MOVE + ) { + InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* descriptor() { + return GetDescriptor(); + } + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() { + return default_instance().GetMetadata().descriptor; + } + static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() { + return default_instance().GetMetadata().reflection; + } + static const Api& default_instance() { + return *internal_default_instance(); + } + static inline const Api* internal_default_instance() { + return reinterpret_cast<const Api*>( + &_Api_default_instance_); + } + static constexpr int kIndexInFileMessages = + 0; + + friend void swap(Api& a, Api& b) { + a.Swap(&b); + } + inline void Swap(Api* other) { + if (other == this) return; + #ifdef PROTOBUF_FORCE_COPY_IN_SWAP + if (GetOwningArena() != nullptr && + GetOwningArena() == other->GetOwningArena()) { + #else // PROTOBUF_FORCE_COPY_IN_SWAP + if (GetOwningArena() == other->GetOwningArena()) { + #endif // !PROTOBUF_FORCE_COPY_IN_SWAP + InternalSwap(other); + } else { + ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(Api* other) { + if (other == this) return; + GOOGLE_DCHECK(GetOwningArena() == other->GetOwningArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + Api* New(::PROTOBUF_NAMESPACE_ID::Arena* arena = nullptr) const final { + return CreateMaybeMessage<Api>(arena); + } + using ::PROTOBUF_NAMESPACE_ID::Message::CopyFrom; + void CopyFrom(const Api& from); + using ::PROTOBUF_NAMESPACE_ID::Message::MergeFrom; + void MergeFrom( const Api& from) { + Api::MergeImpl(*this, from); + } + private: + static void MergeImpl(::PROTOBUF_NAMESPACE_ID::Message& to_msg, const ::PROTOBUF_NAMESPACE_ID::Message& from_msg); + public: + PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + bool IsInitialized() const final; + + size_t ByteSizeLong() const final; + const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final; + uint8_t* _InternalSerialize( + uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final; + int GetCachedSize() const final { return _impl_._cached_size_.Get(); } + + private: + void SharedCtor(::PROTOBUF_NAMESPACE_ID::Arena* arena, bool is_message_owned); + void SharedDtor(); + void SetCachedSize(int size) const final; + void InternalSwap(Api* other); + + private: + friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata; + static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() { + return "google.protobuf.Api"; + } + protected: + explicit Api(::PROTOBUF_NAMESPACE_ID::Arena* arena, + bool is_message_owned = false); + public: + + static const ClassData _class_data_; + const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*GetClassData() const final; + + ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final; + + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + + enum : int { + kMethodsFieldNumber = 2, + kOptionsFieldNumber = 3, + kMixinsFieldNumber = 6, + kNameFieldNumber = 1, + kVersionFieldNumber = 4, + kSourceContextFieldNumber = 5, + kSyntaxFieldNumber = 7, + }; + // repeated .google.protobuf.Method methods = 2; + int methods_size() const; + private: + int _internal_methods_size() const; + public: + void clear_methods(); + ::PROTOBUF_NAMESPACE_ID::Method* mutable_methods(int index); + ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::Method >* + mutable_methods(); + private: + const ::PROTOBUF_NAMESPACE_ID::Method& _internal_methods(int index) const; + ::PROTOBUF_NAMESPACE_ID::Method* _internal_add_methods(); + public: + const ::PROTOBUF_NAMESPACE_ID::Method& methods(int index) const; + ::PROTOBUF_NAMESPACE_ID::Method* add_methods(); + const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::Method >& + methods() const; + + // repeated .google.protobuf.Option options = 3; + int options_size() const; + private: + int _internal_options_size() const; + public: + void clear_options(); + ::PROTOBUF_NAMESPACE_ID::Option* mutable_options(int index); + ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::Option >* + mutable_options(); + private: + const ::PROTOBUF_NAMESPACE_ID::Option& _internal_options(int index) const; + ::PROTOBUF_NAMESPACE_ID::Option* _internal_add_options(); + public: + const ::PROTOBUF_NAMESPACE_ID::Option& options(int index) const; + ::PROTOBUF_NAMESPACE_ID::Option* add_options(); + const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::Option >& + options() const; + + // repeated .google.protobuf.Mixin mixins = 6; + int mixins_size() const; + private: + int _internal_mixins_size() const; + public: + void clear_mixins(); + ::PROTOBUF_NAMESPACE_ID::Mixin* mutable_mixins(int index); + ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::Mixin >* + mutable_mixins(); + private: + const ::PROTOBUF_NAMESPACE_ID::Mixin& _internal_mixins(int index) const; + ::PROTOBUF_NAMESPACE_ID::Mixin* _internal_add_mixins(); + public: + const ::PROTOBUF_NAMESPACE_ID::Mixin& mixins(int index) const; + ::PROTOBUF_NAMESPACE_ID::Mixin* add_mixins(); + const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::Mixin >& + mixins() const; + + // string name = 1; + void clear_name(); + const std::string& name() const; + template <typename ArgT0 = const std::string&, typename... ArgT> + void set_name(ArgT0&& arg0, ArgT... args); + std::string* mutable_name(); + PROTOBUF_NODISCARD std::string* release_name(); + void set_allocated_name(std::string* name); + private: + const std::string& _internal_name() const; + inline PROTOBUF_ALWAYS_INLINE void _internal_set_name(const std::string& value); + std::string* _internal_mutable_name(); + public: + + // string version = 4; + void clear_version(); + const std::string& version() const; + template <typename ArgT0 = const std::string&, typename... ArgT> + void set_version(ArgT0&& arg0, ArgT... args); + std::string* mutable_version(); + PROTOBUF_NODISCARD std::string* release_version(); + void set_allocated_version(std::string* version); + private: + const std::string& _internal_version() const; + inline PROTOBUF_ALWAYS_INLINE void _internal_set_version(const std::string& value); + std::string* _internal_mutable_version(); + public: + + // .google.protobuf.SourceContext source_context = 5; + bool has_source_context() const; + private: + bool _internal_has_source_context() const; + public: + void clear_source_context(); + const ::PROTOBUF_NAMESPACE_ID::SourceContext& source_context() const; + PROTOBUF_NODISCARD ::PROTOBUF_NAMESPACE_ID::SourceContext* release_source_context(); + ::PROTOBUF_NAMESPACE_ID::SourceContext* mutable_source_context(); + void set_allocated_source_context(::PROTOBUF_NAMESPACE_ID::SourceContext* source_context); + private: + const ::PROTOBUF_NAMESPACE_ID::SourceContext& _internal_source_context() const; + ::PROTOBUF_NAMESPACE_ID::SourceContext* _internal_mutable_source_context(); + public: + void unsafe_arena_set_allocated_source_context( + ::PROTOBUF_NAMESPACE_ID::SourceContext* source_context); + ::PROTOBUF_NAMESPACE_ID::SourceContext* unsafe_arena_release_source_context(); + + // .google.protobuf.Syntax syntax = 7; + void clear_syntax(); + ::PROTOBUF_NAMESPACE_ID::Syntax syntax() const; + void set_syntax(::PROTOBUF_NAMESPACE_ID::Syntax value); + private: + ::PROTOBUF_NAMESPACE_ID::Syntax _internal_syntax() const; + void _internal_set_syntax(::PROTOBUF_NAMESPACE_ID::Syntax value); + public: + + // @@protoc_insertion_point(class_scope:google.protobuf.Api) + private: + class _Internal; + + template <typename T> friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper; + typedef void InternalArenaConstructable_; + typedef void DestructorSkippable_; + struct Impl_ { + ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::Method > methods_; + ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::Option > options_; + ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::Mixin > mixins_; + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr name_; + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr version_; + ::PROTOBUF_NAMESPACE_ID::SourceContext* source_context_; + int syntax_; + mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_; + }; + union { Impl_ _impl_; }; + friend struct ::TableStruct_google_2fprotobuf_2fapi_2eproto; +}; +// ------------------------------------------------------------------- + +class PROTOBUF_EXPORT Method final : + public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.Method) */ { + public: + inline Method() : Method(nullptr) {} + ~Method() override; + explicit PROTOBUF_CONSTEXPR Method(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized); + + Method(const Method& from); + Method(Method&& from) noexcept + : Method() { + *this = ::std::move(from); + } + + inline Method& operator=(const Method& from) { + CopyFrom(from); + return *this; + } + inline Method& operator=(Method&& from) noexcept { + if (this == &from) return *this; + if (GetOwningArena() == from.GetOwningArena() + #ifdef PROTOBUF_FORCE_COPY_IN_MOVE + && GetOwningArena() != nullptr + #endif // !PROTOBUF_FORCE_COPY_IN_MOVE + ) { + InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* descriptor() { + return GetDescriptor(); + } + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() { + return default_instance().GetMetadata().descriptor; + } + static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() { + return default_instance().GetMetadata().reflection; + } + static const Method& default_instance() { + return *internal_default_instance(); + } + static inline const Method* internal_default_instance() { + return reinterpret_cast<const Method*>( + &_Method_default_instance_); + } + static constexpr int kIndexInFileMessages = + 1; + + friend void swap(Method& a, Method& b) { + a.Swap(&b); + } + inline void Swap(Method* other) { + if (other == this) return; + #ifdef PROTOBUF_FORCE_COPY_IN_SWAP + if (GetOwningArena() != nullptr && + GetOwningArena() == other->GetOwningArena()) { + #else // PROTOBUF_FORCE_COPY_IN_SWAP + if (GetOwningArena() == other->GetOwningArena()) { + #endif // !PROTOBUF_FORCE_COPY_IN_SWAP + InternalSwap(other); + } else { + ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(Method* other) { + if (other == this) return; + GOOGLE_DCHECK(GetOwningArena() == other->GetOwningArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + Method* New(::PROTOBUF_NAMESPACE_ID::Arena* arena = nullptr) const final { + return CreateMaybeMessage<Method>(arena); + } + using ::PROTOBUF_NAMESPACE_ID::Message::CopyFrom; + void CopyFrom(const Method& from); + using ::PROTOBUF_NAMESPACE_ID::Message::MergeFrom; + void MergeFrom( const Method& from) { + Method::MergeImpl(*this, from); + } + private: + static void MergeImpl(::PROTOBUF_NAMESPACE_ID::Message& to_msg, const ::PROTOBUF_NAMESPACE_ID::Message& from_msg); + public: + PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + bool IsInitialized() const final; + + size_t ByteSizeLong() const final; + const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final; + uint8_t* _InternalSerialize( + uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final; + int GetCachedSize() const final { return _impl_._cached_size_.Get(); } + + private: + void SharedCtor(::PROTOBUF_NAMESPACE_ID::Arena* arena, bool is_message_owned); + void SharedDtor(); + void SetCachedSize(int size) const final; + void InternalSwap(Method* other); + + private: + friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata; + static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() { + return "google.protobuf.Method"; + } + protected: + explicit Method(::PROTOBUF_NAMESPACE_ID::Arena* arena, + bool is_message_owned = false); + public: + + static const ClassData _class_data_; + const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*GetClassData() const final; + + ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final; + + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + + enum : int { + kOptionsFieldNumber = 6, + kNameFieldNumber = 1, + kRequestTypeUrlFieldNumber = 2, + kResponseTypeUrlFieldNumber = 4, + kRequestStreamingFieldNumber = 3, + kResponseStreamingFieldNumber = 5, + kSyntaxFieldNumber = 7, + }; + // repeated .google.protobuf.Option options = 6; + int options_size() const; + private: + int _internal_options_size() const; + public: + void clear_options(); + ::PROTOBUF_NAMESPACE_ID::Option* mutable_options(int index); + ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::Option >* + mutable_options(); + private: + const ::PROTOBUF_NAMESPACE_ID::Option& _internal_options(int index) const; + ::PROTOBUF_NAMESPACE_ID::Option* _internal_add_options(); + public: + const ::PROTOBUF_NAMESPACE_ID::Option& options(int index) const; + ::PROTOBUF_NAMESPACE_ID::Option* add_options(); + const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::Option >& + options() const; + + // string name = 1; + void clear_name(); + const std::string& name() const; + template <typename ArgT0 = const std::string&, typename... ArgT> + void set_name(ArgT0&& arg0, ArgT... args); + std::string* mutable_name(); + PROTOBUF_NODISCARD std::string* release_name(); + void set_allocated_name(std::string* name); + private: + const std::string& _internal_name() const; + inline PROTOBUF_ALWAYS_INLINE void _internal_set_name(const std::string& value); + std::string* _internal_mutable_name(); + public: + + // string request_type_url = 2; + void clear_request_type_url(); + const std::string& request_type_url() const; + template <typename ArgT0 = const std::string&, typename... ArgT> + void set_request_type_url(ArgT0&& arg0, ArgT... args); + std::string* mutable_request_type_url(); + PROTOBUF_NODISCARD std::string* release_request_type_url(); + void set_allocated_request_type_url(std::string* request_type_url); + private: + const std::string& _internal_request_type_url() const; + inline PROTOBUF_ALWAYS_INLINE void _internal_set_request_type_url(const std::string& value); + std::string* _internal_mutable_request_type_url(); + public: + + // string response_type_url = 4; + void clear_response_type_url(); + const std::string& response_type_url() const; + template <typename ArgT0 = const std::string&, typename... ArgT> + void set_response_type_url(ArgT0&& arg0, ArgT... args); + std::string* mutable_response_type_url(); + PROTOBUF_NODISCARD std::string* release_response_type_url(); + void set_allocated_response_type_url(std::string* response_type_url); + private: + const std::string& _internal_response_type_url() const; + inline PROTOBUF_ALWAYS_INLINE void _internal_set_response_type_url(const std::string& value); + std::string* _internal_mutable_response_type_url(); + public: + + // bool request_streaming = 3; + void clear_request_streaming(); + bool request_streaming() const; + void set_request_streaming(bool value); + private: + bool _internal_request_streaming() const; + void _internal_set_request_streaming(bool value); + public: + + // bool response_streaming = 5; + void clear_response_streaming(); + bool response_streaming() const; + void set_response_streaming(bool value); + private: + bool _internal_response_streaming() const; + void _internal_set_response_streaming(bool value); + public: + + // .google.protobuf.Syntax syntax = 7; + void clear_syntax(); + ::PROTOBUF_NAMESPACE_ID::Syntax syntax() const; + void set_syntax(::PROTOBUF_NAMESPACE_ID::Syntax value); + private: + ::PROTOBUF_NAMESPACE_ID::Syntax _internal_syntax() const; + void _internal_set_syntax(::PROTOBUF_NAMESPACE_ID::Syntax value); + public: + + // @@protoc_insertion_point(class_scope:google.protobuf.Method) + private: + class _Internal; + + template <typename T> friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper; + typedef void InternalArenaConstructable_; + typedef void DestructorSkippable_; + struct Impl_ { + ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::Option > options_; + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr name_; + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr request_type_url_; + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr response_type_url_; + bool request_streaming_; + bool response_streaming_; + int syntax_; + mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_; + }; + union { Impl_ _impl_; }; + friend struct ::TableStruct_google_2fprotobuf_2fapi_2eproto; +}; +// ------------------------------------------------------------------- + +class PROTOBUF_EXPORT Mixin final : + public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.Mixin) */ { + public: + inline Mixin() : Mixin(nullptr) {} + ~Mixin() override; + explicit PROTOBUF_CONSTEXPR Mixin(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized); + + Mixin(const Mixin& from); + Mixin(Mixin&& from) noexcept + : Mixin() { + *this = ::std::move(from); + } + + inline Mixin& operator=(const Mixin& from) { + CopyFrom(from); + return *this; + } + inline Mixin& operator=(Mixin&& from) noexcept { + if (this == &from) return *this; + if (GetOwningArena() == from.GetOwningArena() + #ifdef PROTOBUF_FORCE_COPY_IN_MOVE + && GetOwningArena() != nullptr + #endif // !PROTOBUF_FORCE_COPY_IN_MOVE + ) { + InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* descriptor() { + return GetDescriptor(); + } + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() { + return default_instance().GetMetadata().descriptor; + } + static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() { + return default_instance().GetMetadata().reflection; + } + static const Mixin& default_instance() { + return *internal_default_instance(); + } + static inline const Mixin* internal_default_instance() { + return reinterpret_cast<const Mixin*>( + &_Mixin_default_instance_); + } + static constexpr int kIndexInFileMessages = + 2; + + friend void swap(Mixin& a, Mixin& b) { + a.Swap(&b); + } + inline void Swap(Mixin* other) { + if (other == this) return; + #ifdef PROTOBUF_FORCE_COPY_IN_SWAP + if (GetOwningArena() != nullptr && + GetOwningArena() == other->GetOwningArena()) { + #else // PROTOBUF_FORCE_COPY_IN_SWAP + if (GetOwningArena() == other->GetOwningArena()) { + #endif // !PROTOBUF_FORCE_COPY_IN_SWAP + InternalSwap(other); + } else { + ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(Mixin* other) { + if (other == this) return; + GOOGLE_DCHECK(GetOwningArena() == other->GetOwningArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + Mixin* New(::PROTOBUF_NAMESPACE_ID::Arena* arena = nullptr) const final { + return CreateMaybeMessage<Mixin>(arena); + } + using ::PROTOBUF_NAMESPACE_ID::Message::CopyFrom; + void CopyFrom(const Mixin& from); + using ::PROTOBUF_NAMESPACE_ID::Message::MergeFrom; + void MergeFrom( const Mixin& from) { + Mixin::MergeImpl(*this, from); + } + private: + static void MergeImpl(::PROTOBUF_NAMESPACE_ID::Message& to_msg, const ::PROTOBUF_NAMESPACE_ID::Message& from_msg); + public: + PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + bool IsInitialized() const final; + + size_t ByteSizeLong() const final; + const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final; + uint8_t* _InternalSerialize( + uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final; + int GetCachedSize() const final { return _impl_._cached_size_.Get(); } + + private: + void SharedCtor(::PROTOBUF_NAMESPACE_ID::Arena* arena, bool is_message_owned); + void SharedDtor(); + void SetCachedSize(int size) const final; + void InternalSwap(Mixin* other); + + private: + friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata; + static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() { + return "google.protobuf.Mixin"; + } + protected: + explicit Mixin(::PROTOBUF_NAMESPACE_ID::Arena* arena, + bool is_message_owned = false); + public: + + static const ClassData _class_data_; + const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*GetClassData() const final; + + ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final; + + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + + enum : int { + kNameFieldNumber = 1, + kRootFieldNumber = 2, + }; + // string name = 1; + void clear_name(); + const std::string& name() const; + template <typename ArgT0 = const std::string&, typename... ArgT> + void set_name(ArgT0&& arg0, ArgT... args); + std::string* mutable_name(); + PROTOBUF_NODISCARD std::string* release_name(); + void set_allocated_name(std::string* name); + private: + const std::string& _internal_name() const; + inline PROTOBUF_ALWAYS_INLINE void _internal_set_name(const std::string& value); + std::string* _internal_mutable_name(); + public: + + // string root = 2; + void clear_root(); + const std::string& root() const; + template <typename ArgT0 = const std::string&, typename... ArgT> + void set_root(ArgT0&& arg0, ArgT... args); + std::string* mutable_root(); + PROTOBUF_NODISCARD std::string* release_root(); + void set_allocated_root(std::string* root); + private: + const std::string& _internal_root() const; + inline PROTOBUF_ALWAYS_INLINE void _internal_set_root(const std::string& value); + std::string* _internal_mutable_root(); + public: + + // @@protoc_insertion_point(class_scope:google.protobuf.Mixin) + private: + class _Internal; + + template <typename T> friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper; + typedef void InternalArenaConstructable_; + typedef void DestructorSkippable_; + struct Impl_ { + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr name_; + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr root_; + mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_; + }; + union { Impl_ _impl_; }; + friend struct ::TableStruct_google_2fprotobuf_2fapi_2eproto; +}; +// =================================================================== + + +// =================================================================== + +#ifdef __GNUC__ + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wstrict-aliasing" +#endif // __GNUC__ +// Api + +// string name = 1; +inline void Api::clear_name() { + _impl_.name_.ClearToEmpty(); +} +inline const std::string& Api::name() const { + // @@protoc_insertion_point(field_get:google.protobuf.Api.name) + return _internal_name(); +} +template <typename ArgT0, typename... ArgT> +inline PROTOBUF_ALWAYS_INLINE +void Api::set_name(ArgT0&& arg0, ArgT... args) { + + _impl_.name_.Set(static_cast<ArgT0 &&>(arg0), args..., GetArenaForAllocation()); + // @@protoc_insertion_point(field_set:google.protobuf.Api.name) +} +inline std::string* Api::mutable_name() { + std::string* _s = _internal_mutable_name(); + // @@protoc_insertion_point(field_mutable:google.protobuf.Api.name) + return _s; +} +inline const std::string& Api::_internal_name() const { + return _impl_.name_.Get(); +} +inline void Api::_internal_set_name(const std::string& value) { + + _impl_.name_.Set(value, GetArenaForAllocation()); +} +inline std::string* Api::_internal_mutable_name() { + + return _impl_.name_.Mutable(GetArenaForAllocation()); +} +inline std::string* Api::release_name() { + // @@protoc_insertion_point(field_release:google.protobuf.Api.name) + return _impl_.name_.Release(); +} +inline void Api::set_allocated_name(std::string* name) { + if (name != nullptr) { + + } else { + + } + _impl_.name_.SetAllocated(name, GetArenaForAllocation()); +#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (_impl_.name_.IsDefault()) { + _impl_.name_.Set("", GetArenaForAllocation()); + } +#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + // @@protoc_insertion_point(field_set_allocated:google.protobuf.Api.name) +} + +// repeated .google.protobuf.Method methods = 2; +inline int Api::_internal_methods_size() const { + return _impl_.methods_.size(); +} +inline int Api::methods_size() const { + return _internal_methods_size(); +} +inline void Api::clear_methods() { + _impl_.methods_.Clear(); +} +inline ::PROTOBUF_NAMESPACE_ID::Method* Api::mutable_methods(int index) { + // @@protoc_insertion_point(field_mutable:google.protobuf.Api.methods) + return _impl_.methods_.Mutable(index); +} +inline ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::Method >* +Api::mutable_methods() { + // @@protoc_insertion_point(field_mutable_list:google.protobuf.Api.methods) + return &_impl_.methods_; +} +inline const ::PROTOBUF_NAMESPACE_ID::Method& Api::_internal_methods(int index) const { + return _impl_.methods_.Get(index); +} +inline const ::PROTOBUF_NAMESPACE_ID::Method& Api::methods(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.Api.methods) + return _internal_methods(index); +} +inline ::PROTOBUF_NAMESPACE_ID::Method* Api::_internal_add_methods() { + return _impl_.methods_.Add(); +} +inline ::PROTOBUF_NAMESPACE_ID::Method* Api::add_methods() { + ::PROTOBUF_NAMESPACE_ID::Method* _add = _internal_add_methods(); + // @@protoc_insertion_point(field_add:google.protobuf.Api.methods) + return _add; +} +inline const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::Method >& +Api::methods() const { + // @@protoc_insertion_point(field_list:google.protobuf.Api.methods) + return _impl_.methods_; +} + +// repeated .google.protobuf.Option options = 3; +inline int Api::_internal_options_size() const { + return _impl_.options_.size(); +} +inline int Api::options_size() const { + return _internal_options_size(); +} +inline ::PROTOBUF_NAMESPACE_ID::Option* Api::mutable_options(int index) { + // @@protoc_insertion_point(field_mutable:google.protobuf.Api.options) + return _impl_.options_.Mutable(index); +} +inline ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::Option >* +Api::mutable_options() { + // @@protoc_insertion_point(field_mutable_list:google.protobuf.Api.options) + return &_impl_.options_; +} +inline const ::PROTOBUF_NAMESPACE_ID::Option& Api::_internal_options(int index) const { + return _impl_.options_.Get(index); +} +inline const ::PROTOBUF_NAMESPACE_ID::Option& Api::options(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.Api.options) + return _internal_options(index); +} +inline ::PROTOBUF_NAMESPACE_ID::Option* Api::_internal_add_options() { + return _impl_.options_.Add(); +} +inline ::PROTOBUF_NAMESPACE_ID::Option* Api::add_options() { + ::PROTOBUF_NAMESPACE_ID::Option* _add = _internal_add_options(); + // @@protoc_insertion_point(field_add:google.protobuf.Api.options) + return _add; +} +inline const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::Option >& +Api::options() const { + // @@protoc_insertion_point(field_list:google.protobuf.Api.options) + return _impl_.options_; +} + +// string version = 4; +inline void Api::clear_version() { + _impl_.version_.ClearToEmpty(); +} +inline const std::string& Api::version() const { + // @@protoc_insertion_point(field_get:google.protobuf.Api.version) + return _internal_version(); +} +template <typename ArgT0, typename... ArgT> +inline PROTOBUF_ALWAYS_INLINE +void Api::set_version(ArgT0&& arg0, ArgT... args) { + + _impl_.version_.Set(static_cast<ArgT0 &&>(arg0), args..., GetArenaForAllocation()); + // @@protoc_insertion_point(field_set:google.protobuf.Api.version) +} +inline std::string* Api::mutable_version() { + std::string* _s = _internal_mutable_version(); + // @@protoc_insertion_point(field_mutable:google.protobuf.Api.version) + return _s; +} +inline const std::string& Api::_internal_version() const { + return _impl_.version_.Get(); +} +inline void Api::_internal_set_version(const std::string& value) { + + _impl_.version_.Set(value, GetArenaForAllocation()); +} +inline std::string* Api::_internal_mutable_version() { + + return _impl_.version_.Mutable(GetArenaForAllocation()); +} +inline std::string* Api::release_version() { + // @@protoc_insertion_point(field_release:google.protobuf.Api.version) + return _impl_.version_.Release(); +} +inline void Api::set_allocated_version(std::string* version) { + if (version != nullptr) { + + } else { + + } + _impl_.version_.SetAllocated(version, GetArenaForAllocation()); +#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (_impl_.version_.IsDefault()) { + _impl_.version_.Set("", GetArenaForAllocation()); + } +#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + // @@protoc_insertion_point(field_set_allocated:google.protobuf.Api.version) +} + +// .google.protobuf.SourceContext source_context = 5; +inline bool Api::_internal_has_source_context() const { + return this != internal_default_instance() && _impl_.source_context_ != nullptr; +} +inline bool Api::has_source_context() const { + return _internal_has_source_context(); +} +inline const ::PROTOBUF_NAMESPACE_ID::SourceContext& Api::_internal_source_context() const { + const ::PROTOBUF_NAMESPACE_ID::SourceContext* p = _impl_.source_context_; + return p != nullptr ? *p : reinterpret_cast<const ::PROTOBUF_NAMESPACE_ID::SourceContext&>( + ::PROTOBUF_NAMESPACE_ID::_SourceContext_default_instance_); +} +inline const ::PROTOBUF_NAMESPACE_ID::SourceContext& Api::source_context() const { + // @@protoc_insertion_point(field_get:google.protobuf.Api.source_context) + return _internal_source_context(); +} +inline void Api::unsafe_arena_set_allocated_source_context( + ::PROTOBUF_NAMESPACE_ID::SourceContext* source_context) { + if (GetArenaForAllocation() == nullptr) { + delete reinterpret_cast<::PROTOBUF_NAMESPACE_ID::MessageLite*>(_impl_.source_context_); + } + _impl_.source_context_ = source_context; + if (source_context) { + + } else { + + } + // @@protoc_insertion_point(field_unsafe_arena_set_allocated:google.protobuf.Api.source_context) +} +inline ::PROTOBUF_NAMESPACE_ID::SourceContext* Api::release_source_context() { + + ::PROTOBUF_NAMESPACE_ID::SourceContext* temp = _impl_.source_context_; + _impl_.source_context_ = nullptr; +#ifdef PROTOBUF_FORCE_COPY_IN_RELEASE + auto* old = reinterpret_cast<::PROTOBUF_NAMESPACE_ID::MessageLite*>(temp); + temp = ::PROTOBUF_NAMESPACE_ID::internal::DuplicateIfNonNull(temp); + if (GetArenaForAllocation() == nullptr) { delete old; } +#else // PROTOBUF_FORCE_COPY_IN_RELEASE + if (GetArenaForAllocation() != nullptr) { + temp = ::PROTOBUF_NAMESPACE_ID::internal::DuplicateIfNonNull(temp); + } +#endif // !PROTOBUF_FORCE_COPY_IN_RELEASE + return temp; +} +inline ::PROTOBUF_NAMESPACE_ID::SourceContext* Api::unsafe_arena_release_source_context() { + // @@protoc_insertion_point(field_release:google.protobuf.Api.source_context) + + ::PROTOBUF_NAMESPACE_ID::SourceContext* temp = _impl_.source_context_; + _impl_.source_context_ = nullptr; + return temp; +} +inline ::PROTOBUF_NAMESPACE_ID::SourceContext* Api::_internal_mutable_source_context() { + + if (_impl_.source_context_ == nullptr) { + auto* p = CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::SourceContext>(GetArenaForAllocation()); + _impl_.source_context_ = p; + } + return _impl_.source_context_; +} +inline ::PROTOBUF_NAMESPACE_ID::SourceContext* Api::mutable_source_context() { + ::PROTOBUF_NAMESPACE_ID::SourceContext* _msg = _internal_mutable_source_context(); + // @@protoc_insertion_point(field_mutable:google.protobuf.Api.source_context) + return _msg; +} +inline void Api::set_allocated_source_context(::PROTOBUF_NAMESPACE_ID::SourceContext* source_context) { + ::PROTOBUF_NAMESPACE_ID::Arena* message_arena = GetArenaForAllocation(); + if (message_arena == nullptr) { + delete reinterpret_cast< ::PROTOBUF_NAMESPACE_ID::MessageLite*>(_impl_.source_context_); + } + if (source_context) { + ::PROTOBUF_NAMESPACE_ID::Arena* submessage_arena = + ::PROTOBUF_NAMESPACE_ID::Arena::InternalGetOwningArena( + reinterpret_cast<::PROTOBUF_NAMESPACE_ID::MessageLite*>(source_context)); + if (message_arena != submessage_arena) { + source_context = ::PROTOBUF_NAMESPACE_ID::internal::GetOwnedMessage( + message_arena, source_context, submessage_arena); + } + + } else { + + } + _impl_.source_context_ = source_context; + // @@protoc_insertion_point(field_set_allocated:google.protobuf.Api.source_context) +} + +// repeated .google.protobuf.Mixin mixins = 6; +inline int Api::_internal_mixins_size() const { + return _impl_.mixins_.size(); +} +inline int Api::mixins_size() const { + return _internal_mixins_size(); +} +inline void Api::clear_mixins() { + _impl_.mixins_.Clear(); +} +inline ::PROTOBUF_NAMESPACE_ID::Mixin* Api::mutable_mixins(int index) { + // @@protoc_insertion_point(field_mutable:google.protobuf.Api.mixins) + return _impl_.mixins_.Mutable(index); +} +inline ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::Mixin >* +Api::mutable_mixins() { + // @@protoc_insertion_point(field_mutable_list:google.protobuf.Api.mixins) + return &_impl_.mixins_; +} +inline const ::PROTOBUF_NAMESPACE_ID::Mixin& Api::_internal_mixins(int index) const { + return _impl_.mixins_.Get(index); +} +inline const ::PROTOBUF_NAMESPACE_ID::Mixin& Api::mixins(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.Api.mixins) + return _internal_mixins(index); +} +inline ::PROTOBUF_NAMESPACE_ID::Mixin* Api::_internal_add_mixins() { + return _impl_.mixins_.Add(); +} +inline ::PROTOBUF_NAMESPACE_ID::Mixin* Api::add_mixins() { + ::PROTOBUF_NAMESPACE_ID::Mixin* _add = _internal_add_mixins(); + // @@protoc_insertion_point(field_add:google.protobuf.Api.mixins) + return _add; +} +inline const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::Mixin >& +Api::mixins() const { + // @@protoc_insertion_point(field_list:google.protobuf.Api.mixins) + return _impl_.mixins_; +} + +// .google.protobuf.Syntax syntax = 7; +inline void Api::clear_syntax() { + _impl_.syntax_ = 0; +} +inline ::PROTOBUF_NAMESPACE_ID::Syntax Api::_internal_syntax() const { + return static_cast< ::PROTOBUF_NAMESPACE_ID::Syntax >(_impl_.syntax_); +} +inline ::PROTOBUF_NAMESPACE_ID::Syntax Api::syntax() const { + // @@protoc_insertion_point(field_get:google.protobuf.Api.syntax) + return _internal_syntax(); +} +inline void Api::_internal_set_syntax(::PROTOBUF_NAMESPACE_ID::Syntax value) { + + _impl_.syntax_ = value; +} +inline void Api::set_syntax(::PROTOBUF_NAMESPACE_ID::Syntax value) { + _internal_set_syntax(value); + // @@protoc_insertion_point(field_set:google.protobuf.Api.syntax) +} + +// ------------------------------------------------------------------- + +// Method + +// string name = 1; +inline void Method::clear_name() { + _impl_.name_.ClearToEmpty(); +} +inline const std::string& Method::name() const { + // @@protoc_insertion_point(field_get:google.protobuf.Method.name) + return _internal_name(); +} +template <typename ArgT0, typename... ArgT> +inline PROTOBUF_ALWAYS_INLINE +void Method::set_name(ArgT0&& arg0, ArgT... args) { + + _impl_.name_.Set(static_cast<ArgT0 &&>(arg0), args..., GetArenaForAllocation()); + // @@protoc_insertion_point(field_set:google.protobuf.Method.name) +} +inline std::string* Method::mutable_name() { + std::string* _s = _internal_mutable_name(); + // @@protoc_insertion_point(field_mutable:google.protobuf.Method.name) + return _s; +} +inline const std::string& Method::_internal_name() const { + return _impl_.name_.Get(); +} +inline void Method::_internal_set_name(const std::string& value) { + + _impl_.name_.Set(value, GetArenaForAllocation()); +} +inline std::string* Method::_internal_mutable_name() { + + return _impl_.name_.Mutable(GetArenaForAllocation()); +} +inline std::string* Method::release_name() { + // @@protoc_insertion_point(field_release:google.protobuf.Method.name) + return _impl_.name_.Release(); +} +inline void Method::set_allocated_name(std::string* name) { + if (name != nullptr) { + + } else { + + } + _impl_.name_.SetAllocated(name, GetArenaForAllocation()); +#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (_impl_.name_.IsDefault()) { + _impl_.name_.Set("", GetArenaForAllocation()); + } +#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + // @@protoc_insertion_point(field_set_allocated:google.protobuf.Method.name) +} + +// string request_type_url = 2; +inline void Method::clear_request_type_url() { + _impl_.request_type_url_.ClearToEmpty(); +} +inline const std::string& Method::request_type_url() const { + // @@protoc_insertion_point(field_get:google.protobuf.Method.request_type_url) + return _internal_request_type_url(); +} +template <typename ArgT0, typename... ArgT> +inline PROTOBUF_ALWAYS_INLINE +void Method::set_request_type_url(ArgT0&& arg0, ArgT... args) { + + _impl_.request_type_url_.Set(static_cast<ArgT0 &&>(arg0), args..., GetArenaForAllocation()); + // @@protoc_insertion_point(field_set:google.protobuf.Method.request_type_url) +} +inline std::string* Method::mutable_request_type_url() { + std::string* _s = _internal_mutable_request_type_url(); + // @@protoc_insertion_point(field_mutable:google.protobuf.Method.request_type_url) + return _s; +} +inline const std::string& Method::_internal_request_type_url() const { + return _impl_.request_type_url_.Get(); +} +inline void Method::_internal_set_request_type_url(const std::string& value) { + + _impl_.request_type_url_.Set(value, GetArenaForAllocation()); +} +inline std::string* Method::_internal_mutable_request_type_url() { + + return _impl_.request_type_url_.Mutable(GetArenaForAllocation()); +} +inline std::string* Method::release_request_type_url() { + // @@protoc_insertion_point(field_release:google.protobuf.Method.request_type_url) + return _impl_.request_type_url_.Release(); +} +inline void Method::set_allocated_request_type_url(std::string* request_type_url) { + if (request_type_url != nullptr) { + + } else { + + } + _impl_.request_type_url_.SetAllocated(request_type_url, GetArenaForAllocation()); +#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (_impl_.request_type_url_.IsDefault()) { + _impl_.request_type_url_.Set("", GetArenaForAllocation()); + } +#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + // @@protoc_insertion_point(field_set_allocated:google.protobuf.Method.request_type_url) +} + +// bool request_streaming = 3; +inline void Method::clear_request_streaming() { + _impl_.request_streaming_ = false; +} +inline bool Method::_internal_request_streaming() const { + return _impl_.request_streaming_; +} +inline bool Method::request_streaming() const { + // @@protoc_insertion_point(field_get:google.protobuf.Method.request_streaming) + return _internal_request_streaming(); +} +inline void Method::_internal_set_request_streaming(bool value) { + + _impl_.request_streaming_ = value; +} +inline void Method::set_request_streaming(bool value) { + _internal_set_request_streaming(value); + // @@protoc_insertion_point(field_set:google.protobuf.Method.request_streaming) +} + +// string response_type_url = 4; +inline void Method::clear_response_type_url() { + _impl_.response_type_url_.ClearToEmpty(); +} +inline const std::string& Method::response_type_url() const { + // @@protoc_insertion_point(field_get:google.protobuf.Method.response_type_url) + return _internal_response_type_url(); +} +template <typename ArgT0, typename... ArgT> +inline PROTOBUF_ALWAYS_INLINE +void Method::set_response_type_url(ArgT0&& arg0, ArgT... args) { + + _impl_.response_type_url_.Set(static_cast<ArgT0 &&>(arg0), args..., GetArenaForAllocation()); + // @@protoc_insertion_point(field_set:google.protobuf.Method.response_type_url) +} +inline std::string* Method::mutable_response_type_url() { + std::string* _s = _internal_mutable_response_type_url(); + // @@protoc_insertion_point(field_mutable:google.protobuf.Method.response_type_url) + return _s; +} +inline const std::string& Method::_internal_response_type_url() const { + return _impl_.response_type_url_.Get(); +} +inline void Method::_internal_set_response_type_url(const std::string& value) { + + _impl_.response_type_url_.Set(value, GetArenaForAllocation()); +} +inline std::string* Method::_internal_mutable_response_type_url() { + + return _impl_.response_type_url_.Mutable(GetArenaForAllocation()); +} +inline std::string* Method::release_response_type_url() { + // @@protoc_insertion_point(field_release:google.protobuf.Method.response_type_url) + return _impl_.response_type_url_.Release(); +} +inline void Method::set_allocated_response_type_url(std::string* response_type_url) { + if (response_type_url != nullptr) { + + } else { + + } + _impl_.response_type_url_.SetAllocated(response_type_url, GetArenaForAllocation()); +#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (_impl_.response_type_url_.IsDefault()) { + _impl_.response_type_url_.Set("", GetArenaForAllocation()); + } +#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + // @@protoc_insertion_point(field_set_allocated:google.protobuf.Method.response_type_url) +} + +// bool response_streaming = 5; +inline void Method::clear_response_streaming() { + _impl_.response_streaming_ = false; +} +inline bool Method::_internal_response_streaming() const { + return _impl_.response_streaming_; +} +inline bool Method::response_streaming() const { + // @@protoc_insertion_point(field_get:google.protobuf.Method.response_streaming) + return _internal_response_streaming(); +} +inline void Method::_internal_set_response_streaming(bool value) { + + _impl_.response_streaming_ = value; +} +inline void Method::set_response_streaming(bool value) { + _internal_set_response_streaming(value); + // @@protoc_insertion_point(field_set:google.protobuf.Method.response_streaming) +} + +// repeated .google.protobuf.Option options = 6; +inline int Method::_internal_options_size() const { + return _impl_.options_.size(); +} +inline int Method::options_size() const { + return _internal_options_size(); +} +inline ::PROTOBUF_NAMESPACE_ID::Option* Method::mutable_options(int index) { + // @@protoc_insertion_point(field_mutable:google.protobuf.Method.options) + return _impl_.options_.Mutable(index); +} +inline ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::Option >* +Method::mutable_options() { + // @@protoc_insertion_point(field_mutable_list:google.protobuf.Method.options) + return &_impl_.options_; +} +inline const ::PROTOBUF_NAMESPACE_ID::Option& Method::_internal_options(int index) const { + return _impl_.options_.Get(index); +} +inline const ::PROTOBUF_NAMESPACE_ID::Option& Method::options(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.Method.options) + return _internal_options(index); +} +inline ::PROTOBUF_NAMESPACE_ID::Option* Method::_internal_add_options() { + return _impl_.options_.Add(); +} +inline ::PROTOBUF_NAMESPACE_ID::Option* Method::add_options() { + ::PROTOBUF_NAMESPACE_ID::Option* _add = _internal_add_options(); + // @@protoc_insertion_point(field_add:google.protobuf.Method.options) + return _add; +} +inline const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::Option >& +Method::options() const { + // @@protoc_insertion_point(field_list:google.protobuf.Method.options) + return _impl_.options_; +} + +// .google.protobuf.Syntax syntax = 7; +inline void Method::clear_syntax() { + _impl_.syntax_ = 0; +} +inline ::PROTOBUF_NAMESPACE_ID::Syntax Method::_internal_syntax() const { + return static_cast< ::PROTOBUF_NAMESPACE_ID::Syntax >(_impl_.syntax_); +} +inline ::PROTOBUF_NAMESPACE_ID::Syntax Method::syntax() const { + // @@protoc_insertion_point(field_get:google.protobuf.Method.syntax) + return _internal_syntax(); +} +inline void Method::_internal_set_syntax(::PROTOBUF_NAMESPACE_ID::Syntax value) { + + _impl_.syntax_ = value; +} +inline void Method::set_syntax(::PROTOBUF_NAMESPACE_ID::Syntax value) { + _internal_set_syntax(value); + // @@protoc_insertion_point(field_set:google.protobuf.Method.syntax) +} + +// ------------------------------------------------------------------- + +// Mixin + +// string name = 1; +inline void Mixin::clear_name() { + _impl_.name_.ClearToEmpty(); +} +inline const std::string& Mixin::name() const { + // @@protoc_insertion_point(field_get:google.protobuf.Mixin.name) + return _internal_name(); +} +template <typename ArgT0, typename... ArgT> +inline PROTOBUF_ALWAYS_INLINE +void Mixin::set_name(ArgT0&& arg0, ArgT... args) { + + _impl_.name_.Set(static_cast<ArgT0 &&>(arg0), args..., GetArenaForAllocation()); + // @@protoc_insertion_point(field_set:google.protobuf.Mixin.name) +} +inline std::string* Mixin::mutable_name() { + std::string* _s = _internal_mutable_name(); + // @@protoc_insertion_point(field_mutable:google.protobuf.Mixin.name) + return _s; +} +inline const std::string& Mixin::_internal_name() const { + return _impl_.name_.Get(); +} +inline void Mixin::_internal_set_name(const std::string& value) { + + _impl_.name_.Set(value, GetArenaForAllocation()); +} +inline std::string* Mixin::_internal_mutable_name() { + + return _impl_.name_.Mutable(GetArenaForAllocation()); +} +inline std::string* Mixin::release_name() { + // @@protoc_insertion_point(field_release:google.protobuf.Mixin.name) + return _impl_.name_.Release(); +} +inline void Mixin::set_allocated_name(std::string* name) { + if (name != nullptr) { + + } else { + + } + _impl_.name_.SetAllocated(name, GetArenaForAllocation()); +#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (_impl_.name_.IsDefault()) { + _impl_.name_.Set("", GetArenaForAllocation()); + } +#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + // @@protoc_insertion_point(field_set_allocated:google.protobuf.Mixin.name) +} + +// string root = 2; +inline void Mixin::clear_root() { + _impl_.root_.ClearToEmpty(); +} +inline const std::string& Mixin::root() const { + // @@protoc_insertion_point(field_get:google.protobuf.Mixin.root) + return _internal_root(); +} +template <typename ArgT0, typename... ArgT> +inline PROTOBUF_ALWAYS_INLINE +void Mixin::set_root(ArgT0&& arg0, ArgT... args) { + + _impl_.root_.Set(static_cast<ArgT0 &&>(arg0), args..., GetArenaForAllocation()); + // @@protoc_insertion_point(field_set:google.protobuf.Mixin.root) +} +inline std::string* Mixin::mutable_root() { + std::string* _s = _internal_mutable_root(); + // @@protoc_insertion_point(field_mutable:google.protobuf.Mixin.root) + return _s; +} +inline const std::string& Mixin::_internal_root() const { + return _impl_.root_.Get(); +} +inline void Mixin::_internal_set_root(const std::string& value) { + + _impl_.root_.Set(value, GetArenaForAllocation()); +} +inline std::string* Mixin::_internal_mutable_root() { + + return _impl_.root_.Mutable(GetArenaForAllocation()); +} +inline std::string* Mixin::release_root() { + // @@protoc_insertion_point(field_release:google.protobuf.Mixin.root) + return _impl_.root_.Release(); +} +inline void Mixin::set_allocated_root(std::string* root) { + if (root != nullptr) { + + } else { + + } + _impl_.root_.SetAllocated(root, GetArenaForAllocation()); +#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (_impl_.root_.IsDefault()) { + _impl_.root_.Set("", GetArenaForAllocation()); + } +#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + // @@protoc_insertion_point(field_set_allocated:google.protobuf.Mixin.root) +} + +#ifdef __GNUC__ + #pragma GCC diagnostic pop +#endif // __GNUC__ +// ------------------------------------------------------------------- + +// ------------------------------------------------------------------- + + +// @@protoc_insertion_point(namespace_scope) + +PROTOBUF_NAMESPACE_CLOSE + +// @@protoc_insertion_point(global_scope) + +#include <google/protobuf/port_undef.inc> +#endif // GOOGLE_PROTOBUF_INCLUDED_GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2fapi_2eproto diff --git a/toolkit/components/protobuf/src/google/protobuf/api.proto b/toolkit/components/protobuf/src/google/protobuf/api.proto new file mode 100644 index 0000000000..3d598fc859 --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/api.proto @@ -0,0 +1,208 @@ +// 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. + +syntax = "proto3"; + +package google.protobuf; + +import "google/protobuf/source_context.proto"; +import "google/protobuf/type.proto"; + +option csharp_namespace = "Google.Protobuf.WellKnownTypes"; +option java_package = "com.google.protobuf"; +option java_outer_classname = "ApiProto"; +option java_multiple_files = true; +option objc_class_prefix = "GPB"; +option go_package = "google.golang.org/protobuf/types/known/apipb"; + +// Api is a light-weight descriptor for an API Interface. +// +// Interfaces are also described as "protocol buffer services" in some contexts, +// such as by the "service" keyword in a .proto file, but they are different +// from API Services, which represent a concrete implementation of an interface +// as opposed to simply a description of methods and bindings. They are also +// sometimes simply referred to as "APIs" in other contexts, such as the name of +// this message itself. See https://cloud.google.com/apis/design/glossary for +// detailed terminology. +message Api { + // The fully qualified name of this interface, including package name + // followed by the interface's simple name. + string name = 1; + + // The methods of this interface, in unspecified order. + repeated Method methods = 2; + + // Any metadata attached to the interface. + repeated Option options = 3; + + // A version string for this interface. If specified, must have the form + // `major-version.minor-version`, as in `1.10`. If the minor version is + // omitted, it defaults to zero. If the entire version field is empty, the + // major version is derived from the package name, as outlined below. If the + // field is not empty, the version in the package name will be verified to be + // consistent with what is provided here. + // + // The versioning schema uses [semantic + // versioning](http://semver.org) where the major version number + // indicates a breaking change and the minor version an additive, + // non-breaking change. Both version numbers are signals to users + // what to expect from different versions, and should be carefully + // chosen based on the product plan. + // + // The major version is also reflected in the package name of the + // interface, which must end in `v<major-version>`, as in + // `google.feature.v1`. For major versions 0 and 1, the suffix can + // be omitted. Zero major versions must only be used for + // experimental, non-GA interfaces. + // + // + string version = 4; + + // Source context for the protocol buffer service represented by this + // message. + SourceContext source_context = 5; + + // Included interfaces. See [Mixin][]. + repeated Mixin mixins = 6; + + // The source syntax of the service. + Syntax syntax = 7; +} + +// Method represents a method of an API interface. +message Method { + // The simple name of this method. + string name = 1; + + // A URL of the input message type. + string request_type_url = 2; + + // If true, the request is streamed. + bool request_streaming = 3; + + // The URL of the output message type. + string response_type_url = 4; + + // If true, the response is streamed. + bool response_streaming = 5; + + // Any metadata attached to the method. + repeated Option options = 6; + + // The source syntax of this method. + Syntax syntax = 7; +} + +// Declares an API Interface to be included in this interface. The including +// interface must redeclare all the methods from the included interface, but +// documentation and options are inherited as follows: +// +// - If after comment and whitespace stripping, the documentation +// string of the redeclared method is empty, it will be inherited +// from the original method. +// +// - Each annotation belonging to the service config (http, +// visibility) which is not set in the redeclared method will be +// inherited. +// +// - If an http annotation is inherited, the path pattern will be +// modified as follows. Any version prefix will be replaced by the +// version of the including interface plus the [root][] path if +// specified. +// +// Example of a simple mixin: +// +// package google.acl.v1; +// service AccessControl { +// // Get the underlying ACL object. +// rpc GetAcl(GetAclRequest) returns (Acl) { +// option (google.api.http).get = "/v1/{resource=**}:getAcl"; +// } +// } +// +// package google.storage.v2; +// service Storage { +// rpc GetAcl(GetAclRequest) returns (Acl); +// +// // Get a data record. +// rpc GetData(GetDataRequest) returns (Data) { +// option (google.api.http).get = "/v2/{resource=**}"; +// } +// } +// +// Example of a mixin configuration: +// +// apis: +// - name: google.storage.v2.Storage +// mixins: +// - name: google.acl.v1.AccessControl +// +// The mixin construct implies that all methods in `AccessControl` are +// also declared with same name and request/response types in +// `Storage`. A documentation generator or annotation processor will +// see the effective `Storage.GetAcl` method after inheriting +// documentation and annotations as follows: +// +// service Storage { +// // Get the underlying ACL object. +// rpc GetAcl(GetAclRequest) returns (Acl) { +// option (google.api.http).get = "/v2/{resource=**}:getAcl"; +// } +// ... +// } +// +// Note how the version in the path pattern changed from `v1` to `v2`. +// +// If the `root` field in the mixin is specified, it should be a +// relative path under which inherited HTTP paths are placed. Example: +// +// apis: +// - name: google.storage.v2.Storage +// mixins: +// - name: google.acl.v1.AccessControl +// root: acls +// +// This implies the following inherited HTTP annotation: +// +// service Storage { +// // Get the underlying ACL object. +// rpc GetAcl(GetAclRequest) returns (Acl) { +// option (google.api.http).get = "/v2/acls/{resource=**}:getAcl"; +// } +// ... +// } +message Mixin { + // The fully qualified name of the interface which is included. + string name = 1; + + // If non-empty specifies a path under which inherited HTTP paths + // are rooted. + string root = 2; +} diff --git a/toolkit/components/protobuf/src/google/protobuf/arena.cc b/toolkit/components/protobuf/src/google/protobuf/arena.cc new file mode 100644 index 0000000000..6ba508a5f0 --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/arena.cc @@ -0,0 +1,537 @@ +// 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. + +#include <google/protobuf/arena.h> + +#include <algorithm> +#include <atomic> +#include <cstddef> +#include <cstdint> +#include <limits> +#include <typeinfo> + +#include <google/protobuf/arena_impl.h> +#include <google/protobuf/arenaz_sampler.h> +#include <google/protobuf/port.h> + +#include <google/protobuf/stubs/mutex.h> +#ifdef ADDRESS_SANITIZER +#include <sanitizer/asan_interface.h> +#endif // ADDRESS_SANITIZER + +// Must be included last. +#include <google/protobuf/port_def.inc> + +namespace google { +namespace protobuf { +namespace internal { + +static SerialArena::Memory AllocateMemory(const AllocationPolicy* policy_ptr, + size_t last_size, size_t min_bytes) { + AllocationPolicy policy; // default policy + if (policy_ptr) policy = *policy_ptr; + size_t size; + if (last_size != 0) { + // Double the current block size, up to a limit. + auto max_size = policy.max_block_size; + size = std::min(2 * last_size, max_size); + } else { + size = policy.start_block_size; + } + // Verify that min_bytes + kBlockHeaderSize won't overflow. + GOOGLE_CHECK_LE(min_bytes, + std::numeric_limits<size_t>::max() - SerialArena::kBlockHeaderSize); + size = std::max(size, SerialArena::kBlockHeaderSize + min_bytes); + + void* mem; + if (policy.block_alloc == nullptr) { + mem = ::operator new(size); + } else { + mem = policy.block_alloc(size); + } + return {mem, size}; +} + +class GetDeallocator { + public: + GetDeallocator(const AllocationPolicy* policy, size_t* space_allocated) + : dealloc_(policy ? policy->block_dealloc : nullptr), + space_allocated_(space_allocated) {} + + void operator()(SerialArena::Memory mem) const { +#ifdef ADDRESS_SANITIZER + // This memory was provided by the underlying allocator as unpoisoned, + // so return it in an unpoisoned state. + ASAN_UNPOISON_MEMORY_REGION(mem.ptr, mem.size); +#endif // ADDRESS_SANITIZER + if (dealloc_) { + dealloc_(mem.ptr, mem.size); + } else { + internal::SizedDelete(mem.ptr, mem.size); + } + *space_allocated_ += mem.size; + } + + private: + void (*dealloc_)(void*, size_t); + size_t* space_allocated_; +}; + +SerialArena::SerialArena(Block* b, void* owner, ThreadSafeArenaStats* stats) + : space_allocated_(b->size) { + owner_ = owner; + head_ = b; + ptr_ = b->Pointer(kBlockHeaderSize + ThreadSafeArena::kSerialArenaSize); + limit_ = b->Pointer(b->size & static_cast<size_t>(-8)); + arena_stats_ = stats; +} + +SerialArena* SerialArena::New(Memory mem, void* owner, + ThreadSafeArenaStats* stats) { + GOOGLE_DCHECK_LE(kBlockHeaderSize + ThreadSafeArena::kSerialArenaSize, mem.size); + ThreadSafeArenaStats::RecordAllocateStats( + stats, /*requested=*/mem.size, /*allocated=*/mem.size, /*wasted=*/0); + auto b = new (mem.ptr) Block{nullptr, mem.size}; + return new (b->Pointer(kBlockHeaderSize)) SerialArena(b, owner, stats); +} + +template <typename Deallocator> +SerialArena::Memory SerialArena::Free(Deallocator deallocator) { + Block* b = head_; + Memory mem = {b, b->size}; + while (b->next) { + b = b->next; // We must first advance before deleting this block + deallocator(mem); + mem = {b, b->size}; + } + return mem; +} + +PROTOBUF_NOINLINE +std::pair<void*, SerialArena::CleanupNode*> +SerialArena::AllocateAlignedWithCleanupFallback( + size_t n, const AllocationPolicy* policy) { + AllocateNewBlock(n + kCleanupSize, policy); + return AllocateFromExistingWithCleanupFallback(n); +} + +PROTOBUF_NOINLINE +void* SerialArena::AllocateAlignedFallback(size_t n, + const AllocationPolicy* policy) { + AllocateNewBlock(n, policy); + return AllocateFromExisting(n); +} + +void SerialArena::AllocateNewBlock(size_t n, const AllocationPolicy* policy) { + // Sync limit to block + head_->start = reinterpret_cast<CleanupNode*>(limit_); + + // Record how much used in this block. + size_t used = ptr_ - head_->Pointer(kBlockHeaderSize); + size_t wasted = head_->size - used; + space_used_ += used; + + // TODO(sbenza): Evaluate if pushing unused space into the cached blocks is a + // win. In preliminary testing showed increased memory savings as expected, + // but with a CPU regression. The regression might have been an artifact of + // the microbenchmark. + + auto mem = AllocateMemory(policy, head_->size, n); + // We don't want to emit an expensive RMW instruction that requires + // exclusive access to a cacheline. Hence we write it in terms of a + // regular add. + auto relaxed = std::memory_order_relaxed; + space_allocated_.store(space_allocated_.load(relaxed) + mem.size, relaxed); + ThreadSafeArenaStats::RecordAllocateStats(arena_stats_, /*requested=*/n, + /*allocated=*/mem.size, wasted); + head_ = new (mem.ptr) Block{head_, mem.size}; + ptr_ = head_->Pointer(kBlockHeaderSize); + limit_ = head_->Pointer(head_->size); + +#ifdef ADDRESS_SANITIZER + ASAN_POISON_MEMORY_REGION(ptr_, limit_ - ptr_); +#endif // ADDRESS_SANITIZER +} + +uint64_t SerialArena::SpaceUsed() const { + uint64_t space_used = ptr_ - head_->Pointer(kBlockHeaderSize); + space_used += space_used_; + // Remove the overhead of the SerialArena itself. + space_used -= ThreadSafeArena::kSerialArenaSize; + return space_used; +} + +void SerialArena::CleanupList() { + Block* b = head_; + b->start = reinterpret_cast<CleanupNode*>(limit_); + do { + auto* limit = reinterpret_cast<CleanupNode*>( + b->Pointer(b->size & static_cast<size_t>(-8))); + auto it = b->start; + auto num = limit - it; + if (num > 0) { + for (; it < limit; it++) { + it->cleanup(it->elem); + } + } + b = b->next; + } while (b); +} + + +ThreadSafeArena::CacheAlignedLifecycleIdGenerator + ThreadSafeArena::lifecycle_id_generator_; +#if defined(GOOGLE_PROTOBUF_NO_THREADLOCAL) +ThreadSafeArena::ThreadCache& ThreadSafeArena::thread_cache() { + static internal::ThreadLocalStorage<ThreadCache>* thread_cache_ = + new internal::ThreadLocalStorage<ThreadCache>(); + return *thread_cache_->Get(); +} +#elif defined(PROTOBUF_USE_DLLS) +ThreadSafeArena::ThreadCache& ThreadSafeArena::thread_cache() { + static PROTOBUF_THREAD_LOCAL ThreadCache thread_cache_ = { + 0, static_cast<LifecycleIdAtomic>(-1), nullptr}; + return thread_cache_; +} +#else +PROTOBUF_THREAD_LOCAL ThreadSafeArena::ThreadCache + ThreadSafeArena::thread_cache_ = {0, static_cast<LifecycleIdAtomic>(-1), + nullptr}; +#endif + +void ThreadSafeArena::InitializeFrom(void* mem, size_t size) { + GOOGLE_DCHECK_EQ(reinterpret_cast<uintptr_t>(mem) & 7, 0u); + GOOGLE_DCHECK(!AllocPolicy()); // Reset should call InitializeWithPolicy instead. + Init(); + + // Ignore initial block if it is too small. + if (mem != nullptr && size >= kBlockHeaderSize + kSerialArenaSize) { + alloc_policy_.set_is_user_owned_initial_block(true); + SetInitialBlock(mem, size); + } +} + +void ThreadSafeArena::InitializeWithPolicy(void* mem, size_t size, + AllocationPolicy policy) { +#ifndef NDEBUG + const uint64_t old_alloc_policy = alloc_policy_.get_raw(); + // If there was a policy (e.g., in Reset()), make sure flags were preserved. +#define GOOGLE_DCHECK_POLICY_FLAGS_() \ + if (old_alloc_policy > 3) \ + GOOGLE_CHECK_EQ(old_alloc_policy & 3, alloc_policy_.get_raw() & 3) +#else +#define GOOGLE_DCHECK_POLICY_FLAGS_() +#endif // NDEBUG + + if (policy.IsDefault()) { + // Legacy code doesn't use the API above, but provides the initial block + // through ArenaOptions. I suspect most do not touch the allocation + // policy parameters. + InitializeFrom(mem, size); + GOOGLE_DCHECK_POLICY_FLAGS_(); + return; + } + GOOGLE_DCHECK_EQ(reinterpret_cast<uintptr_t>(mem) & 7, 0u); + Init(); + + // Ignore initial block if it is too small. We include an optional + // AllocationPolicy in this check, so that this can be allocated on the + // first block. + constexpr size_t kAPSize = internal::AlignUpTo8(sizeof(AllocationPolicy)); + constexpr size_t kMinimumSize = kBlockHeaderSize + kSerialArenaSize + kAPSize; + + // The value for alloc_policy_ stores whether or not allocations should be + // recorded. + alloc_policy_.set_should_record_allocs( + policy.metrics_collector != nullptr && + policy.metrics_collector->RecordAllocs()); + // Make sure we have an initial block to store the AllocationPolicy. + if (mem != nullptr && size >= kMinimumSize) { + alloc_policy_.set_is_user_owned_initial_block(true); + } else { + auto tmp = AllocateMemory(&policy, 0, kMinimumSize); + mem = tmp.ptr; + size = tmp.size; + } + SetInitialBlock(mem, size); + + auto sa = threads_.load(std::memory_order_relaxed); + // We ensured enough space so this cannot fail. + void* p; + if (!sa || !sa->MaybeAllocateAligned(kAPSize, &p)) { + GOOGLE_LOG(FATAL) << "MaybeAllocateAligned cannot fail here."; + return; + } + new (p) AllocationPolicy{policy}; + // Low bits store flags, so they mustn't be overwritten. + GOOGLE_DCHECK_EQ(0, reinterpret_cast<uintptr_t>(p) & 3); + alloc_policy_.set_policy(reinterpret_cast<AllocationPolicy*>(p)); + GOOGLE_DCHECK_POLICY_FLAGS_(); + +#undef GOOGLE_DCHECK_POLICY_FLAGS_ +} + +void ThreadSafeArena::Init() { +#ifndef NDEBUG + const bool was_message_owned = IsMessageOwned(); +#endif // NDEBUG + ThreadCache& tc = thread_cache(); + auto id = tc.next_lifecycle_id; + // We increment lifecycle_id's by multiples of two so we can use bit 0 as + // a tag. + constexpr uint64_t kDelta = 2; + constexpr uint64_t kInc = ThreadCache::kPerThreadIds * kDelta; + if (PROTOBUF_PREDICT_FALSE((id & (kInc - 1)) == 0)) { + constexpr auto relaxed = std::memory_order_relaxed; + // On platforms that don't support uint64_t atomics we can certainly not + // afford to increment by large intervals and expect uniqueness due to + // wrapping, hence we only add by 1. + id = lifecycle_id_generator_.id.fetch_add(1, relaxed) * kInc; + } + tc.next_lifecycle_id = id + kDelta; + // Message ownership is stored in tag_and_id_, and is set in the constructor. + // This flag bit must be preserved, even across calls to Reset(). + tag_and_id_ = id | (tag_and_id_ & kMessageOwnedArena); + hint_.store(nullptr, std::memory_order_relaxed); + threads_.store(nullptr, std::memory_order_relaxed); +#ifndef NDEBUG + GOOGLE_CHECK_EQ(was_message_owned, IsMessageOwned()); +#endif // NDEBUG + arena_stats_ = Sample(); +} + +void ThreadSafeArena::SetInitialBlock(void* mem, size_t size) { + SerialArena* serial = SerialArena::New({mem, size}, &thread_cache(), + arena_stats_.MutableStats()); + serial->set_next(NULL); + threads_.store(serial, std::memory_order_relaxed); + CacheSerialArena(serial); +} + +ThreadSafeArena::~ThreadSafeArena() { + // Have to do this in a first pass, because some of the destructors might + // refer to memory in other blocks. + CleanupList(); + + size_t space_allocated = 0; + auto mem = Free(&space_allocated); + + // Policy is about to get deleted. + auto* p = alloc_policy_.get(); + ArenaMetricsCollector* collector = p ? p->metrics_collector : nullptr; + + if (alloc_policy_.is_user_owned_initial_block()) { +#ifdef ADDRESS_SANITIZER + // Unpoison the initial block, now that it's going back to the user. + ASAN_UNPOISON_MEMORY_REGION(mem.ptr, mem.size); +#endif // ADDRESS_SANITIZER + space_allocated += mem.size; + } else { + GetDeallocator(alloc_policy_.get(), &space_allocated)(mem); + } + + if (collector) collector->OnDestroy(space_allocated); +} + +SerialArena::Memory ThreadSafeArena::Free(size_t* space_allocated) { + SerialArena::Memory mem = {nullptr, 0}; + auto deallocator = GetDeallocator(alloc_policy_.get(), space_allocated); + PerSerialArena([deallocator, &mem](SerialArena* a) { + if (mem.ptr) deallocator(mem); + mem = a->Free(deallocator); + }); + return mem; +} + +uint64_t ThreadSafeArena::Reset() { + // Have to do this in a first pass, because some of the destructors might + // refer to memory in other blocks. + CleanupList(); + + // Discard all blocks except the special block (if present). + size_t space_allocated = 0; + auto mem = Free(&space_allocated); + arena_stats_.RecordReset(); + + AllocationPolicy* policy = alloc_policy_.get(); + if (policy) { + auto saved_policy = *policy; + if (alloc_policy_.is_user_owned_initial_block()) { + space_allocated += mem.size; + } else { + GetDeallocator(alloc_policy_.get(), &space_allocated)(mem); + mem.ptr = nullptr; + mem.size = 0; + } + ArenaMetricsCollector* collector = saved_policy.metrics_collector; + if (collector) collector->OnReset(space_allocated); + InitializeWithPolicy(mem.ptr, mem.size, saved_policy); + } else { + GOOGLE_DCHECK(!alloc_policy_.should_record_allocs()); + // Nullptr policy + if (alloc_policy_.is_user_owned_initial_block()) { + space_allocated += mem.size; + InitializeFrom(mem.ptr, mem.size); + } else { + GetDeallocator(alloc_policy_.get(), &space_allocated)(mem); + Init(); + } + } + + return space_allocated; +} + +std::pair<void*, SerialArena::CleanupNode*> +ThreadSafeArena::AllocateAlignedWithCleanup(size_t n, + const std::type_info* type) { + SerialArena* arena; + if (PROTOBUF_PREDICT_TRUE(!alloc_policy_.should_record_allocs() && + GetSerialArenaFast(&arena))) { + return arena->AllocateAlignedWithCleanup(n, alloc_policy_.get()); + } else { + return AllocateAlignedWithCleanupFallback(n, type); + } +} + +void ThreadSafeArena::AddCleanup(void* elem, void (*cleanup)(void*)) { + SerialArena* arena; + if (PROTOBUF_PREDICT_FALSE(!GetSerialArenaFast(&arena))) { + arena = GetSerialArenaFallback(&thread_cache()); + } + arena->AddCleanup(elem, cleanup, AllocPolicy()); +} + +PROTOBUF_NOINLINE +void* ThreadSafeArena::AllocateAlignedFallback(size_t n, + const std::type_info* type) { + if (alloc_policy_.should_record_allocs()) { + alloc_policy_.RecordAlloc(type, n); + SerialArena* arena; + if (PROTOBUF_PREDICT_TRUE(GetSerialArenaFast(&arena))) { + return arena->AllocateAligned(n, alloc_policy_.get()); + } + } + return GetSerialArenaFallback(&thread_cache()) + ->AllocateAligned(n, alloc_policy_.get()); +} + +PROTOBUF_NOINLINE +std::pair<void*, SerialArena::CleanupNode*> +ThreadSafeArena::AllocateAlignedWithCleanupFallback( + size_t n, const std::type_info* type) { + if (alloc_policy_.should_record_allocs()) { + alloc_policy_.RecordAlloc(type, n); + SerialArena* arena; + if (GetSerialArenaFast(&arena)) { + return arena->AllocateAlignedWithCleanup(n, alloc_policy_.get()); + } + } + return GetSerialArenaFallback(&thread_cache()) + ->AllocateAlignedWithCleanup(n, alloc_policy_.get()); +} + +uint64_t ThreadSafeArena::SpaceAllocated() const { + SerialArena* serial = threads_.load(std::memory_order_acquire); + uint64_t res = 0; + for (; serial; serial = serial->next()) { + res += serial->SpaceAllocated(); + } + return res; +} + +uint64_t ThreadSafeArena::SpaceUsed() const { + SerialArena* serial = threads_.load(std::memory_order_acquire); + uint64_t space_used = 0; + for (; serial; serial = serial->next()) { + space_used += serial->SpaceUsed(); + } + return space_used - (alloc_policy_.get() ? sizeof(AllocationPolicy) : 0); +} + +void ThreadSafeArena::CleanupList() { + PerSerialArena([](SerialArena* a) { a->CleanupList(); }); +} + +PROTOBUF_NOINLINE +SerialArena* ThreadSafeArena::GetSerialArenaFallback(void* me) { + // Look for this SerialArena in our linked list. + SerialArena* serial = threads_.load(std::memory_order_acquire); + for (; serial; serial = serial->next()) { + if (serial->owner() == me) { + break; + } + } + + if (!serial) { + // This thread doesn't have any SerialArena, which also means it doesn't + // have any blocks yet. So we'll allocate its first block now. + serial = SerialArena::New( + AllocateMemory(alloc_policy_.get(), 0, kSerialArenaSize), me, + arena_stats_.MutableStats()); + + SerialArena* head = threads_.load(std::memory_order_relaxed); + do { + serial->set_next(head); + } while (!threads_.compare_exchange_weak( + head, serial, std::memory_order_release, std::memory_order_relaxed)); + } + + CacheSerialArena(serial); + return serial; +} + +} // namespace internal + +PROTOBUF_FUNC_ALIGN(32) +void* Arena::AllocateAlignedNoHook(size_t n) { + return impl_.AllocateAligned(n, nullptr); +} + +PROTOBUF_FUNC_ALIGN(32) +void* Arena::AllocateAlignedWithHook(size_t n, const std::type_info* type) { + return impl_.AllocateAligned(n, type); +} + +PROTOBUF_FUNC_ALIGN(32) +void* Arena::AllocateAlignedWithHookForArray(size_t n, + const std::type_info* type) { + return impl_.AllocateAligned<internal::AllocationClient::kArray>(n, type); +} + +PROTOBUF_FUNC_ALIGN(32) +std::pair<void*, internal::SerialArena::CleanupNode*> +Arena::AllocateAlignedWithCleanup(size_t n, const std::type_info* type) { + return impl_.AllocateAlignedWithCleanup(n, type); +} + +} // namespace protobuf +} // namespace google + +#include <google/protobuf/port_undef.inc> diff --git a/toolkit/components/protobuf/src/google/protobuf/arena.h b/toolkit/components/protobuf/src/google/protobuf/arena.h new file mode 100644 index 0000000000..3b5f16c389 --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/arena.h @@ -0,0 +1,851 @@ +// 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. + +// This file defines an Arena allocator for better allocation performance. + +#ifndef GOOGLE_PROTOBUF_ARENA_H__ +#define GOOGLE_PROTOBUF_ARENA_H__ + + +#include <limits> +#include <type_traits> +#include <utility> +#if defined(_MSC_VER) && !defined(_LIBCPP_STD_VER) && !_HAS_EXCEPTIONS +// Work around bugs in MSVC <typeinfo> header when _HAS_EXCEPTIONS=0. +#include <exception> +#include <typeinfo> +namespace std { +using type_info = ::type_info; +} +#else +#include <typeinfo> +#endif + +#include <type_traits> +#include <google/protobuf/arena_impl.h> +#include <google/protobuf/port.h> + +// Must be included last. +#include <google/protobuf/port_def.inc> + +#ifdef SWIG +#error "You cannot SWIG proto headers" +#endif + +namespace google { +namespace protobuf { + +struct ArenaOptions; // defined below +class Arena; // defined below +class Message; // defined in message.h +class MessageLite; +template <typename Key, typename T> +class Map; + +namespace arena_metrics { + +void EnableArenaMetrics(ArenaOptions* options); + +} // namespace arena_metrics + +namespace TestUtil { +class ReflectionTester; // defined in test_util.h +} // namespace TestUtil + +namespace internal { + +struct ArenaTestPeer; // defined in arena_test_util.h +class InternalMetadata; // defined in metadata_lite.h +class LazyField; // defined in lazy_field.h +class EpsCopyInputStream; // defined in parse_context.h +class RepeatedPtrFieldBase; // defined in repeated_ptr_field.h + +template <typename Type> +class GenericTypeHandler; // defined in repeated_field.h + +inline PROTOBUF_ALWAYS_INLINE +void* AlignTo(void* ptr, size_t align) { + return reinterpret_cast<void*>( + (reinterpret_cast<uintptr_t>(ptr) + align - 1) & (~align + 1)); +} + +// Templated cleanup methods. +template <typename T> +void arena_destruct_object(void* object) { + reinterpret_cast<T*>(object)->~T(); +} + +template <bool destructor_skippable, typename T> +struct ObjectDestructor { + constexpr static void (*destructor)(void*) = &arena_destruct_object<T>; +}; + +template <typename T> +struct ObjectDestructor<true, T> { + constexpr static void (*destructor)(void*) = nullptr; +}; + +template <typename T> +void arena_delete_object(void* object) { + delete reinterpret_cast<T*>(object); +} +} // namespace internal + +// ArenaOptions provides optional additional parameters to arena construction +// that control its block-allocation behavior. +struct ArenaOptions { + // This defines the size of the first block requested from the system malloc. + // Subsequent block sizes will increase in a geometric series up to a maximum. + size_t start_block_size; + + // This defines the maximum block size requested from system malloc (unless an + // individual arena allocation request occurs with a size larger than this + // maximum). Requested block sizes increase up to this value, then remain + // here. + size_t max_block_size; + + // An initial block of memory for the arena to use, or NULL for none. If + // provided, the block must live at least as long as the arena itself. The + // creator of the Arena retains ownership of the block after the Arena is + // destroyed. + char* initial_block; + + // The size of the initial block, if provided. + size_t initial_block_size; + + // A function pointer to an alloc method that returns memory blocks of size + // requested. By default, it contains a ptr to the malloc function. + // + // NOTE: block_alloc and dealloc functions are expected to behave like + // malloc and free, including Asan poisoning. + void* (*block_alloc)(size_t); + // A function pointer to a dealloc method that takes ownership of the blocks + // from the arena. By default, it contains a ptr to a wrapper function that + // calls free. + void (*block_dealloc)(void*, size_t); + + ArenaOptions() + : start_block_size(internal::AllocationPolicy::kDefaultStartBlockSize), + max_block_size(internal::AllocationPolicy::kDefaultMaxBlockSize), + initial_block(NULL), + initial_block_size(0), + block_alloc(nullptr), + block_dealloc(nullptr), + make_metrics_collector(nullptr) {} + + private: + // If make_metrics_collector is not nullptr, it will be called at Arena init + // time. It may return a pointer to a collector instance that will be notified + // of interesting events related to the arena. + internal::ArenaMetricsCollector* (*make_metrics_collector)(); + + internal::ArenaMetricsCollector* MetricsCollector() const { + return make_metrics_collector ? (*make_metrics_collector)() : nullptr; + } + + internal::AllocationPolicy AllocationPolicy() const { + internal::AllocationPolicy res; + res.start_block_size = start_block_size; + res.max_block_size = max_block_size; + res.block_alloc = block_alloc; + res.block_dealloc = block_dealloc; + res.metrics_collector = MetricsCollector(); + return res; + } + + friend void arena_metrics::EnableArenaMetrics(ArenaOptions*); + + friend class Arena; + friend class ArenaOptionsTestFriend; +}; + +// Support for non-RTTI environments. (The metrics hooks API uses type +// information.) +#if PROTOBUF_RTTI +#define RTTI_TYPE_ID(type) (&typeid(type)) +#else +#define RTTI_TYPE_ID(type) (NULL) +#endif + +// Arena allocator. Arena allocation replaces ordinary (heap-based) allocation +// with new/delete, and improves performance by aggregating allocations into +// larger blocks and freeing allocations all at once. Protocol messages are +// allocated on an arena by using Arena::CreateMessage<T>(Arena*), below, and +// are automatically freed when the arena is destroyed. +// +// This is a thread-safe implementation: multiple threads may allocate from the +// arena concurrently. Destruction is not thread-safe and the destructing +// thread must synchronize with users of the arena first. +// +// An arena provides two allocation interfaces: CreateMessage<T>, which works +// for arena-enabled proto2 message types as well as other types that satisfy +// the appropriate protocol (described below), and Create<T>, which works for +// any arbitrary type T. CreateMessage<T> is better when the type T supports it, +// because this interface (i) passes the arena pointer to the created object so +// that its sub-objects and internal allocations can use the arena too, and (ii) +// elides the object's destructor call when possible. Create<T> does not place +// any special requirements on the type T, and will invoke the object's +// destructor when the arena is destroyed. +// +// The arena message allocation protocol, required by +// CreateMessage<T>(Arena* arena, Args&&... args), is as follows: +// +// - The type T must have (at least) two constructors: a constructor callable +// with `args` (without `arena`), called when a T is allocated on the heap; +// and a constructor callable with `Arena* arena, Args&&... args`, called when +// a T is allocated on an arena. If the second constructor is called with a +// NULL arena pointer, it must be equivalent to invoking the first +// (`args`-only) constructor. +// +// - The type T must have a particular type trait: a nested type +// |InternalArenaConstructable_|. This is usually a typedef to |void|. If no +// such type trait exists, then the instantiation CreateMessage<T> will fail +// to compile. +// +// - The type T *may* have the type trait |DestructorSkippable_|. If this type +// trait is present in the type, then its destructor will not be called if and +// only if it was passed a non-NULL arena pointer. If this type trait is not +// present on the type, then its destructor is always called when the +// containing arena is destroyed. +// +// This protocol is implemented by all arena-enabled proto2 message classes as +// well as protobuf container types like RepeatedPtrField and Map. The protocol +// is internal to protobuf and is not guaranteed to be stable. Non-proto types +// should not rely on this protocol. +class PROTOBUF_EXPORT PROTOBUF_ALIGNAS(8) Arena final { + public: + // Default constructor with sensible default options, tuned for average + // use-cases. + inline Arena() : impl_() {} + + // Construct an arena with default options, except for the supplied + // initial block. It is more efficient to use this constructor + // instead of passing ArenaOptions if the only configuration needed + // by the caller is supplying an initial block. + inline Arena(char* initial_block, size_t initial_block_size) + : impl_(initial_block, initial_block_size) {} + + // Arena constructor taking custom options. See ArenaOptions above for + // descriptions of the options available. + explicit Arena(const ArenaOptions& options) + : impl_(options.initial_block, options.initial_block_size, + options.AllocationPolicy()) {} + + // Block overhead. Use this as a guide for how much to over-allocate the + // initial block if you want an allocation of size N to fit inside it. + // + // WARNING: if you allocate multiple objects, it is difficult to guarantee + // that a series of allocations will fit in the initial block, especially if + // Arena changes its alignment guarantees in the future! + static const size_t kBlockOverhead = + internal::ThreadSafeArena::kBlockHeaderSize + + internal::ThreadSafeArena::kSerialArenaSize; + + inline ~Arena() {} + + // TODO(protobuf-team): Fix callers to use constructor and delete this method. + void Init(const ArenaOptions&) {} + + // API to create proto2 message objects on the arena. If the arena passed in + // is NULL, then a heap allocated object is returned. Type T must be a message + // defined in a .proto file with cc_enable_arenas set to true, otherwise a + // compilation error will occur. + // + // RepeatedField and RepeatedPtrField may also be instantiated directly on an + // arena with this method. + // + // This function also accepts any type T that satisfies the arena message + // allocation protocol, documented above. + template <typename T, typename... Args> + PROTOBUF_ALWAYS_INLINE static T* CreateMessage(Arena* arena, Args&&... args) { + static_assert( + InternalHelper<T>::is_arena_constructable::value, + "CreateMessage can only construct types that are ArenaConstructable"); + // We must delegate to CreateMaybeMessage() and NOT CreateMessageInternal() + // because protobuf generated classes specialize CreateMaybeMessage() and we + // need to use that specialization for code size reasons. + return Arena::CreateMaybeMessage<T>(arena, static_cast<Args&&>(args)...); + } + + // API to create any objects on the arena. Note that only the object will + // be created on the arena; the underlying ptrs (in case of a proto2 message) + // will be still heap allocated. Proto messages should usually be allocated + // with CreateMessage<T>() instead. + // + // Note that even if T satisfies the arena message construction protocol + // (InternalArenaConstructable_ trait and optional DestructorSkippable_ + // trait), as described above, this function does not follow the protocol; + // instead, it treats T as a black-box type, just as if it did not have these + // traits. Specifically, T's constructor arguments will always be only those + // passed to Create<T>() -- no additional arena pointer is implicitly added. + // Furthermore, the destructor will always be called at arena destruction time + // (unless the destructor is trivial). Hence, from T's point of view, it is as + // if the object were allocated on the heap (except that the underlying memory + // is obtained from the arena). + template <typename T, typename... Args> + PROTOBUF_NDEBUG_INLINE static T* Create(Arena* arena, Args&&... args) { + return CreateInternal<T>(arena, std::is_convertible<T*, MessageLite*>(), + static_cast<Args&&>(args)...); + } + + // Allocates memory with the specific size and alignment. + void* AllocateAligned(size_t size, size_t align = 8) { + if (align <= 8) { + return AllocateAlignedNoHook(internal::AlignUpTo8(size)); + } else { + // We are wasting space by over allocating align - 8 bytes. Compared + // to a dedicated function that takes current alignment in consideration. + // Such a scheme would only waste (align - 8)/2 bytes on average, but + // requires a dedicated function in the outline arena allocation + // functions. Possibly re-evaluate tradeoffs later. + return internal::AlignTo(AllocateAlignedNoHook(size + align - 8), align); + } + } + + // Create an array of object type T on the arena *without* invoking the + // constructor of T. If `arena` is null, then the return value should be freed + // with `delete[] x;` (or `::operator delete[](x);`). + // To ensure safe uses, this function checks at compile time + // (when compiled as C++11) that T is trivially default-constructible and + // trivially destructible. + template <typename T> + PROTOBUF_NDEBUG_INLINE static T* CreateArray(Arena* arena, + size_t num_elements) { + static_assert(std::is_trivial<T>::value, + "CreateArray requires a trivially constructible type"); + static_assert(std::is_trivially_destructible<T>::value, + "CreateArray requires a trivially destructible type"); + GOOGLE_CHECK_LE(num_elements, std::numeric_limits<size_t>::max() / sizeof(T)) + << "Requested size is too large to fit into size_t."; + if (arena == NULL) { + return static_cast<T*>(::operator new[](num_elements * sizeof(T))); + } else { + return arena->CreateInternalRawArray<T>(num_elements); + } + } + + // The following are routines are for monitoring. They will approximate the + // total sum allocated and used memory, but the exact value is an + // implementation deal. For instance allocated space depends on growth + // policies. Do not use these in unit tests. + // Returns the total space allocated by the arena, which is the sum of the + // sizes of the underlying blocks. + uint64_t SpaceAllocated() const { return impl_.SpaceAllocated(); } + // Returns the total space used by the arena. Similar to SpaceAllocated but + // does not include free space and block overhead. The total space returned + // may not include space used by other threads executing concurrently with + // the call to this method. + uint64_t SpaceUsed() const { return impl_.SpaceUsed(); } + + // Frees all storage allocated by this arena after calling destructors + // registered with OwnDestructor() and freeing objects registered with Own(). + // Any objects allocated on this arena are unusable after this call. It also + // returns the total space used by the arena which is the sums of the sizes + // of the allocated blocks. This method is not thread-safe. + uint64_t Reset() { return impl_.Reset(); } + + // Adds |object| to a list of heap-allocated objects to be freed with |delete| + // when the arena is destroyed or reset. + template <typename T> + PROTOBUF_ALWAYS_INLINE void Own(T* object) { + OwnInternal(object, std::is_convertible<T*, MessageLite*>()); + } + + // Adds |object| to a list of objects whose destructors will be manually + // called when the arena is destroyed or reset. This differs from Own() in + // that it does not free the underlying memory with |delete|; hence, it is + // normally only used for objects that are placement-newed into + // arena-allocated memory. + template <typename T> + PROTOBUF_ALWAYS_INLINE void OwnDestructor(T* object) { + if (object != NULL) { + impl_.AddCleanup(object, &internal::arena_destruct_object<T>); + } + } + + // Adds a custom member function on an object to the list of destructors that + // will be manually called when the arena is destroyed or reset. This differs + // from OwnDestructor() in that any member function may be specified, not only + // the class destructor. + PROTOBUF_ALWAYS_INLINE void OwnCustomDestructor(void* object, + void (*destruct)(void*)) { + impl_.AddCleanup(object, destruct); + } + + // Retrieves the arena associated with |value| if |value| is an arena-capable + // message, or NULL otherwise. If possible, the call resolves at compile time. + // Note that we can often devirtualize calls to `value->GetArena()` so usually + // calling this method is unnecessary. + template <typename T> + PROTOBUF_ALWAYS_INLINE static Arena* GetArena(const T* value) { + return GetArenaInternal(value); + } + + template <typename T> + class InternalHelper { + private: + // Provides access to protected GetOwningArena to generated messages. + static Arena* GetOwningArena(const T* p) { return p->GetOwningArena(); } + + static void InternalSwap(T* a, T* b) { a->InternalSwap(b); } + + static Arena* GetArenaForAllocationInternal( + const T* p, std::true_type /*is_derived_from<MessageLite>*/) { + return p->GetArenaForAllocation(); + } + + static Arena* GetArenaForAllocationInternal( + const T* p, std::false_type /*is_derived_from<MessageLite>*/) { + return GetArenaForAllocationForNonMessage( + p, typename is_arena_constructable::type()); + } + + static Arena* GetArenaForAllocationForNonMessage( + const T* p, std::true_type /*is_arena_constructible*/) { + return p->GetArena(); + } + + static Arena* GetArenaForAllocationForNonMessage( + const T* p, std::false_type /*is_arena_constructible*/) { + return GetArenaForAllocationForNonMessageNonArenaConstructible( + p, typename has_get_arena::type()); + } + + static Arena* GetArenaForAllocationForNonMessageNonArenaConstructible( + const T* p, std::true_type /*has_get_arena*/) { + return p->GetArena(); + } + + static Arena* GetArenaForAllocationForNonMessageNonArenaConstructible( + const T* /* p */, std::false_type /*has_get_arena*/) { + return nullptr; + } + + template <typename U> + static char DestructorSkippable(const typename U::DestructorSkippable_*); + template <typename U> + static double DestructorSkippable(...); + + typedef std::integral_constant< + bool, sizeof(DestructorSkippable<T>(static_cast<const T*>(0))) == + sizeof(char) || + std::is_trivially_destructible<T>::value> + is_destructor_skippable; + + template <typename U> + static char ArenaConstructable( + const typename U::InternalArenaConstructable_*); + template <typename U> + static double ArenaConstructable(...); + + typedef std::integral_constant<bool, sizeof(ArenaConstructable<T>( + static_cast<const T*>(0))) == + sizeof(char)> + is_arena_constructable; + + template <typename U, + typename std::enable_if< + std::is_same<Arena*, decltype(std::declval<const U>() + .GetArena())>::value, + int>::type = 0> + static char HasGetArena(decltype(&U::GetArena)); + template <typename U> + static double HasGetArena(...); + + typedef std::integral_constant<bool, sizeof(HasGetArena<T>(nullptr)) == + sizeof(char)> + has_get_arena; + + template <typename... Args> + static T* Construct(void* ptr, Args&&... args) { + return new (ptr) T(static_cast<Args&&>(args)...); + } + + static inline PROTOBUF_ALWAYS_INLINE T* New() { + return new T(nullptr); + } + + static Arena* GetArena(const T* p) { return p->GetArena(); } + + friend class Arena; + friend class TestUtil::ReflectionTester; + }; + + // Provides access to protected GetOwningArena to generated messages. For + // internal use only. + template <typename T> + static Arena* InternalGetOwningArena(const T* p) { + return InternalHelper<T>::GetOwningArena(p); + } + + // Provides access to protected GetArenaForAllocation to generated messages. + // For internal use only. + template <typename T> + static Arena* InternalGetArenaForAllocation(const T* p) { + return InternalHelper<T>::GetArenaForAllocationInternal( + p, std::is_convertible<T*, MessageLite*>()); + } + + // Creates message-owned arena. For internal use only. + static Arena* InternalCreateMessageOwnedArena() { + return new Arena(internal::MessageOwned{}); + } + + // Checks whether this arena is message-owned. For internal use only. + bool InternalIsMessageOwnedArena() { return IsMessageOwned(); } + + // Helper typetraits that indicates support for arenas in a type T at compile + // time. This is public only to allow construction of higher-level templated + // utilities. + // + // is_arena_constructable<T>::value is true if the message type T has arena + // support enabled, and false otherwise. + // + // is_destructor_skippable<T>::value is true if the message type T has told + // the arena that it is safe to skip the destructor, and false otherwise. + // + // This is inside Arena because only Arena has the friend relationships + // necessary to see the underlying generated code traits. + template <typename T> + struct is_arena_constructable : InternalHelper<T>::is_arena_constructable {}; + template <typename T> + struct is_destructor_skippable : InternalHelper<T>::is_destructor_skippable { + }; + + private: + internal::ThreadSafeArena impl_; + + template <typename T> + struct has_get_arena : InternalHelper<T>::has_get_arena {}; + + // Constructor solely used by message-owned arena. + inline Arena(internal::MessageOwned) : impl_(internal::MessageOwned{}) {} + + // Checks whether this arena is message-owned. + PROTOBUF_ALWAYS_INLINE bool IsMessageOwned() const { + return impl_.IsMessageOwned(); + } + + void ReturnArrayMemory(void* p, size_t size) { + impl_.ReturnArrayMemory(p, size); + } + + template <typename T, typename... Args> + PROTOBUF_NDEBUG_INLINE static T* CreateMessageInternal(Arena* arena, + Args&&... args) { + static_assert( + InternalHelper<T>::is_arena_constructable::value, + "CreateMessage can only construct types that are ArenaConstructable"); + if (arena == NULL) { + return new T(nullptr, static_cast<Args&&>(args)...); + } else { + return arena->DoCreateMessage<T>(static_cast<Args&&>(args)...); + } + } + + // This specialization for no arguments is necessary, because its behavior is + // slightly different. When the arena pointer is nullptr, it calls T() + // instead of T(nullptr). + template <typename T> + PROTOBUF_NDEBUG_INLINE static T* CreateMessageInternal(Arena* arena) { + static_assert( + InternalHelper<T>::is_arena_constructable::value, + "CreateMessage can only construct types that are ArenaConstructable"); + if (arena == NULL) { + // Generated arena constructor T(Arena*) is protected. Call via + // InternalHelper. + return InternalHelper<T>::New(); + } else { + return arena->DoCreateMessage<T>(); + } + } + + // Allocate and also optionally call collector with the allocated type info + // when allocation recording is enabled. + PROTOBUF_NDEBUG_INLINE void* AllocateInternal(size_t size, size_t align, + void (*destructor)(void*), + const std::type_info* type) { + // Monitor allocation if needed. + if (destructor == nullptr) { + return AllocateAlignedWithHook(size, align, type); + } else { + if (align <= 8) { + auto res = AllocateAlignedWithCleanup(internal::AlignUpTo8(size), type); + res.second->elem = res.first; + res.second->cleanup = destructor; + return res.first; + } else { + auto res = AllocateAlignedWithCleanup(size + align - 8, type); + auto ptr = internal::AlignTo(res.first, align); + res.second->elem = ptr; + res.second->cleanup = destructor; + return ptr; + } + } + } + + // CreateMessage<T> requires that T supports arenas, but this private method + // works whether or not T supports arenas. These are not exposed to user code + // as it can cause confusing API usages, and end up having double free in + // user code. These are used only internally from LazyField and Repeated + // fields, since they are designed to work in all mode combinations. + template <typename Msg, typename... Args> + PROTOBUF_ALWAYS_INLINE static Msg* DoCreateMaybeMessage(Arena* arena, + std::true_type, + Args&&... args) { + return CreateMessageInternal<Msg>(arena, std::forward<Args>(args)...); + } + + template <typename T, typename... Args> + PROTOBUF_ALWAYS_INLINE static T* DoCreateMaybeMessage(Arena* arena, + std::false_type, + Args&&... args) { + return Create<T>(arena, std::forward<Args>(args)...); + } + + template <typename T, typename... Args> + PROTOBUF_ALWAYS_INLINE static T* CreateMaybeMessage(Arena* arena, + Args&&... args) { + return DoCreateMaybeMessage<T>(arena, is_arena_constructable<T>(), + std::forward<Args>(args)...); + } + + // Just allocate the required size for the given type assuming the + // type has a trivial constructor. + template <typename T> + PROTOBUF_NDEBUG_INLINE T* CreateInternalRawArray(size_t num_elements) { + GOOGLE_CHECK_LE(num_elements, std::numeric_limits<size_t>::max() / sizeof(T)) + << "Requested size is too large to fit into size_t."; + // We count on compiler to realize that if sizeof(T) is a multiple of + // 8 AlignUpTo can be elided. + const size_t n = sizeof(T) * num_elements; + return static_cast<T*>( + AllocateAlignedWithHookForArray(n, alignof(T), RTTI_TYPE_ID(T))); + } + + template <typename T, typename... Args> + PROTOBUF_NDEBUG_INLINE T* DoCreateMessage(Args&&... args) { + return InternalHelper<T>::Construct( + AllocateInternal(sizeof(T), alignof(T), + internal::ObjectDestructor< + InternalHelper<T>::is_destructor_skippable::value, + T>::destructor, + RTTI_TYPE_ID(T)), + this, std::forward<Args>(args)...); + } + + // CreateInArenaStorage is used to implement map field. Without it, + // Map need to call generated message's protected arena constructor, + // which needs to declare Map as friend of generated message. + template <typename T, typename... Args> + static void CreateInArenaStorage(T* ptr, Arena* arena, Args&&... args) { + CreateInArenaStorageInternal(ptr, arena, + typename is_arena_constructable<T>::type(), + std::forward<Args>(args)...); + if (arena != nullptr) { + RegisterDestructorInternal( + ptr, arena, + typename InternalHelper<T>::is_destructor_skippable::type()); + } + } + + template <typename T, typename... Args> + static void CreateInArenaStorageInternal(T* ptr, Arena* arena, + std::true_type, Args&&... args) { + InternalHelper<T>::Construct(ptr, arena, std::forward<Args>(args)...); + } + template <typename T, typename... Args> + static void CreateInArenaStorageInternal(T* ptr, Arena* /* arena */, + std::false_type, Args&&... args) { + new (ptr) T(std::forward<Args>(args)...); + } + + template <typename T> + static void RegisterDestructorInternal(T* /* ptr */, Arena* /* arena */, + std::true_type) {} + template <typename T> + static void RegisterDestructorInternal(T* ptr, Arena* arena, + std::false_type) { + arena->OwnDestructor(ptr); + } + + // These implement Create(). The second parameter has type 'true_type' if T is + // a subtype of Message and 'false_type' otherwise. + template <typename T, typename... Args> + PROTOBUF_ALWAYS_INLINE static T* CreateInternal(Arena* arena, std::true_type, + Args&&... args) { + if (arena == nullptr) { + return new T(std::forward<Args>(args)...); + } else { + auto destructor = + internal::ObjectDestructor<std::is_trivially_destructible<T>::value, + T>::destructor; + T* result = + new (arena->AllocateInternal(sizeof(T), alignof(T), destructor, + RTTI_TYPE_ID(T))) + T(std::forward<Args>(args)...); + return result; + } + } + template <typename T, typename... Args> + PROTOBUF_ALWAYS_INLINE static T* CreateInternal(Arena* arena, std::false_type, + Args&&... args) { + if (arena == nullptr) { + return new T(std::forward<Args>(args)...); + } else { + auto destructor = + internal::ObjectDestructor<std::is_trivially_destructible<T>::value, + T>::destructor; + return new (arena->AllocateInternal(sizeof(T), alignof(T), destructor, + RTTI_TYPE_ID(T))) + T(std::forward<Args>(args)...); + } + } + + // These implement Own(), which registers an object for deletion (destructor + // call and operator delete()). The second parameter has type 'true_type' if T + // is a subtype of Message and 'false_type' otherwise. Collapsing + // all template instantiations to one for generic Message reduces code size, + // using the virtual destructor instead. + template <typename T> + PROTOBUF_ALWAYS_INLINE void OwnInternal(T* object, std::true_type) { + if (object != NULL) { + impl_.AddCleanup(object, &internal::arena_delete_object<MessageLite>); + } + } + template <typename T> + PROTOBUF_ALWAYS_INLINE void OwnInternal(T* object, std::false_type) { + if (object != NULL) { + impl_.AddCleanup(object, &internal::arena_delete_object<T>); + } + } + + // Implementation for GetArena(). Only message objects with + // InternalArenaConstructable_ tags can be associated with an arena, and such + // objects must implement a GetArena() method. + template <typename T, typename std::enable_if< + is_arena_constructable<T>::value, int>::type = 0> + PROTOBUF_ALWAYS_INLINE static Arena* GetArenaInternal(const T* value) { + return InternalHelper<T>::GetArena(value); + } + template <typename T, + typename std::enable_if<!is_arena_constructable<T>::value && + has_get_arena<T>::value, + int>::type = 0> + PROTOBUF_ALWAYS_INLINE static Arena* GetArenaInternal(const T* value) { + return value->GetArena(); + } + template <typename T, + typename std::enable_if<!is_arena_constructable<T>::value && + !has_get_arena<T>::value, + int>::type = 0> + PROTOBUF_ALWAYS_INLINE static Arena* GetArenaInternal(const T* value) { + (void)value; + return nullptr; + } + + template <typename T> + PROTOBUF_ALWAYS_INLINE static Arena* GetOwningArena(const T* value) { + return GetOwningArenaInternal( + value, std::is_convertible<T*, MessageLite*>()); + } + + // Implementation for GetOwningArena(). All and only message objects have + // GetOwningArena() method. + template <typename T> + PROTOBUF_ALWAYS_INLINE static Arena* GetOwningArenaInternal( + const T* value, std::true_type) { + return InternalHelper<T>::GetOwningArena(value); + } + template <typename T> + PROTOBUF_ALWAYS_INLINE static Arena* GetOwningArenaInternal( + const T* /* value */, std::false_type) { + return nullptr; + } + + void* AllocateAlignedWithHookForArray(size_t n, size_t align, + const std::type_info* type) { + if (align <= 8) { + return AllocateAlignedWithHookForArray(internal::AlignUpTo8(n), type); + } else { + // We are wasting space by over allocating align - 8 bytes. Compared + // to a dedicated function that takes current alignment in consideration. + // Such a scheme would only waste (align - 8)/2 bytes on average, but + // requires a dedicated function in the outline arena allocation + // functions. Possibly re-evaluate tradeoffs later. + return internal::AlignTo( + AllocateAlignedWithHookForArray(n + align - 8, type), align); + } + } + + void* AllocateAlignedWithHook(size_t n, size_t align, + const std::type_info* type) { + if (align <= 8) { + return AllocateAlignedWithHook(internal::AlignUpTo8(n), type); + } else { + // We are wasting space by over allocating align - 8 bytes. Compared + // to a dedicated function that takes current alignment in consideration. + // Such a scheme would only waste (align - 8)/2 bytes on average, but + // requires a dedicated function in the outline arena allocation + // functions. Possibly re-evaluate tradeoffs later. + return internal::AlignTo(AllocateAlignedWithHook(n + align - 8, type), + align); + } + } + + void* AllocateAlignedNoHook(size_t n); + void* AllocateAlignedWithHook(size_t n, const std::type_info* type); + void* AllocateAlignedWithHookForArray(size_t n, const std::type_info* type); + std::pair<void*, internal::SerialArena::CleanupNode*> + AllocateAlignedWithCleanup(size_t n, const std::type_info* type); + + template <typename Type> + friend class internal::GenericTypeHandler; + friend class internal::InternalMetadata; // For user_arena(). + friend class internal::LazyField; // For CreateMaybeMessage. + friend class internal::EpsCopyInputStream; // For parser performance + friend class MessageLite; + template <typename Key, typename T> + friend class Map; + template <typename> + friend class RepeatedField; // For ReturnArrayMemory + friend class internal::RepeatedPtrFieldBase; // For ReturnArrayMemory + friend struct internal::ArenaTestPeer; +}; + +// Defined above for supporting environments without RTTI. +#undef RTTI_TYPE_ID + +} // namespace protobuf +} // namespace google + +#include <google/protobuf/port_undef.inc> + +#endif // GOOGLE_PROTOBUF_ARENA_H__ diff --git a/toolkit/components/protobuf/src/google/protobuf/arena_impl.h b/toolkit/components/protobuf/src/google/protobuf/arena_impl.h new file mode 100644 index 0000000000..76727688b5 --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/arena_impl.h @@ -0,0 +1,686 @@ +// 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. + +// This file defines an Arena allocator for better allocation performance. + +#ifndef GOOGLE_PROTOBUF_ARENA_IMPL_H__ +#define GOOGLE_PROTOBUF_ARENA_IMPL_H__ + +#include <atomic> +#include <limits> +#include <typeinfo> + +#include <google/protobuf/stubs/common.h> +#include <google/protobuf/stubs/logging.h> +#include <google/protobuf/stubs/port.h> + +#ifdef ADDRESS_SANITIZER +#include <sanitizer/asan_interface.h> +#endif // ADDRESS_SANITIZER + +#include <google/protobuf/arenaz_sampler.h> + +// Must be included last. +#include <google/protobuf/port_def.inc> + + +namespace google { +namespace protobuf { +namespace internal { + +// To prevent sharing cache lines between threads +#ifdef __cpp_aligned_new +enum { kCacheAlignment = 64 }; +#else +enum { kCacheAlignment = alignof(max_align_t) }; // do the best we can +#endif + +inline constexpr size_t AlignUpTo8(size_t n) { + // Align n to next multiple of 8 (from Hacker's Delight, Chapter 3.) + return (n + 7) & static_cast<size_t>(-8); +} + +using LifecycleIdAtomic = uint64_t; + +// MetricsCollector collects stats for a particular arena. +class PROTOBUF_EXPORT ArenaMetricsCollector { + public: + ArenaMetricsCollector(bool record_allocs) : record_allocs_(record_allocs) {} + + // Invoked when the arena is about to be destroyed. This method will + // typically finalize any metric collection and delete the collector. + // space_allocated is the space used by the arena. + virtual void OnDestroy(uint64_t space_allocated) = 0; + + // OnReset() is called when the associated arena is reset. + // space_allocated is the space used by the arena just before the reset. + virtual void OnReset(uint64_t space_allocated) = 0; + + // OnAlloc is called when an allocation happens. + // type_info is promised to be static - its lifetime extends to + // match program's lifetime (It is given by typeid operator). + // Note: typeid(void) will be passed as allocated_type every time we + // intentionally want to avoid monitoring an allocation. (i.e. internal + // allocations for managing the arena) + virtual void OnAlloc(const std::type_info* allocated_type, + uint64_t alloc_size) = 0; + + // Does OnAlloc() need to be called? If false, metric collection overhead + // will be reduced since we will not do extra work per allocation. + bool RecordAllocs() { return record_allocs_; } + + protected: + // This class is destructed by the call to OnDestroy(). + ~ArenaMetricsCollector() = default; + const bool record_allocs_; +}; + +struct AllocationPolicy { + static constexpr size_t kDefaultStartBlockSize = 256; + static constexpr size_t kDefaultMaxBlockSize = 8192; + + size_t start_block_size = kDefaultStartBlockSize; + size_t max_block_size = kDefaultMaxBlockSize; + void* (*block_alloc)(size_t) = nullptr; + void (*block_dealloc)(void*, size_t) = nullptr; + ArenaMetricsCollector* metrics_collector = nullptr; + + bool IsDefault() const { + return start_block_size == kDefaultMaxBlockSize && + max_block_size == kDefaultMaxBlockSize && block_alloc == nullptr && + block_dealloc == nullptr && metrics_collector == nullptr; + } +}; + +// Tagged pointer to an AllocationPolicy. +class TaggedAllocationPolicyPtr { + public: + constexpr TaggedAllocationPolicyPtr() : policy_(0) {} + + explicit TaggedAllocationPolicyPtr(AllocationPolicy* policy) + : policy_(reinterpret_cast<uintptr_t>(policy)) {} + + void set_policy(AllocationPolicy* policy) { + auto bits = policy_ & kTagsMask; + policy_ = reinterpret_cast<uintptr_t>(policy) | bits; + } + + AllocationPolicy* get() { + return reinterpret_cast<AllocationPolicy*>(policy_ & kPtrMask); + } + const AllocationPolicy* get() const { + return reinterpret_cast<const AllocationPolicy*>(policy_ & kPtrMask); + } + + AllocationPolicy& operator*() { return *get(); } + const AllocationPolicy& operator*() const { return *get(); } + + AllocationPolicy* operator->() { return get(); } + const AllocationPolicy* operator->() const { return get(); } + + bool is_user_owned_initial_block() const { + return static_cast<bool>(get_mask<kUserOwnedInitialBlock>()); + } + void set_is_user_owned_initial_block(bool v) { + set_mask<kUserOwnedInitialBlock>(v); + } + + bool should_record_allocs() const { + return static_cast<bool>(get_mask<kRecordAllocs>()); + } + void set_should_record_allocs(bool v) { set_mask<kRecordAllocs>(v); } + + uintptr_t get_raw() const { return policy_; } + + inline void RecordAlloc(const std::type_info* allocated_type, + size_t n) const { + get()->metrics_collector->OnAlloc(allocated_type, n); + } + + private: + enum : uintptr_t { + kUserOwnedInitialBlock = 1, + kRecordAllocs = 2, + }; + + static constexpr uintptr_t kTagsMask = 7; + static constexpr uintptr_t kPtrMask = ~kTagsMask; + + template <uintptr_t kMask> + uintptr_t get_mask() const { + return policy_ & kMask; + } + template <uintptr_t kMask> + void set_mask(bool v) { + if (v) { + policy_ |= kMask; + } else { + policy_ &= ~kMask; + } + } + uintptr_t policy_; +}; + +enum class AllocationClient { kDefault, kArray }; + +// A simple arena allocator. Calls to allocate functions must be properly +// serialized by the caller, hence this class cannot be used as a general +// purpose allocator in a multi-threaded program. It serves as a building block +// for ThreadSafeArena, which provides a thread-safe arena allocator. +// +// This class manages +// 1) Arena bump allocation + owning memory blocks. +// 2) Maintaining a cleanup list. +// It delagetes the actual memory allocation back to ThreadSafeArena, which +// contains the information on block growth policy and backing memory allocation +// used. +class PROTOBUF_EXPORT SerialArena { + public: + struct Memory { + void* ptr; + size_t size; + }; + + // Node contains the ptr of the object to be cleaned up and the associated + // cleanup function ptr. + struct CleanupNode { + void* elem; // Pointer to the object to be cleaned up. + void (*cleanup)(void*); // Function pointer to the destructor or deleter. + }; + + void CleanupList(); + uint64_t SpaceAllocated() const { + return space_allocated_.load(std::memory_order_relaxed); + } + uint64_t SpaceUsed() const; + + bool HasSpace(size_t n) const { + return n <= static_cast<size_t>(limit_ - ptr_); + } + + // See comments on `cached_blocks_` member for details. + PROTOBUF_ALWAYS_INLINE void* TryAllocateFromCachedBlock(size_t size) { + if (PROTOBUF_PREDICT_FALSE(size < 16)) return nullptr; + // We round up to the next larger block in case the memory doesn't match + // the pattern we are looking for. + const size_t index = Bits::Log2FloorNonZero64(size - 1) - 3; + + if (index >= cached_block_length_) return nullptr; + auto& cached_head = cached_blocks_[index]; + if (cached_head == nullptr) return nullptr; + + void* ret = cached_head; +#ifdef ADDRESS_SANITIZER + ASAN_UNPOISON_MEMORY_REGION(ret, size); +#endif // ADDRESS_SANITIZER + cached_head = cached_head->next; + return ret; + } + + // In kArray mode we look through cached blocks. + // We do not do this by default because most non-array allocations will not + // have the right size and will fail to find an appropriate cached block. + // + // TODO(sbenza): Evaluate if we should use cached blocks for message types of + // the right size. We can statically know if the allocation size can benefit + // from it. + template <AllocationClient alloc_client = AllocationClient::kDefault> + void* AllocateAligned(size_t n, const AllocationPolicy* policy) { + GOOGLE_DCHECK_EQ(internal::AlignUpTo8(n), n); // Must be already aligned. + GOOGLE_DCHECK_GE(limit_, ptr_); + + if (alloc_client == AllocationClient::kArray) { + if (void* res = TryAllocateFromCachedBlock(n)) { + return res; + } + } + + if (PROTOBUF_PREDICT_FALSE(!HasSpace(n))) { + return AllocateAlignedFallback(n, policy); + } + return AllocateFromExisting(n); + } + + private: + void* AllocateFromExisting(size_t n) { + void* ret = ptr_; + ptr_ += n; +#ifdef ADDRESS_SANITIZER + ASAN_UNPOISON_MEMORY_REGION(ret, n); +#endif // ADDRESS_SANITIZER + return ret; + } + + // See comments on `cached_blocks_` member for details. + void ReturnArrayMemory(void* p, size_t size) { + // We only need to check for 32-bit platforms. + // In 64-bit platforms the minimum allocation size from Repeated*Field will + // be 16 guaranteed. + if (sizeof(void*) < 8) { + if (PROTOBUF_PREDICT_FALSE(size < 16)) return; + } else { + GOOGLE_DCHECK(size >= 16); + } + + // We round down to the next smaller block in case the memory doesn't match + // the pattern we are looking for. eg, someone might have called Reserve() + // on the repeated field. + const size_t index = Bits::Log2FloorNonZero64(size) - 4; + + if (PROTOBUF_PREDICT_FALSE(index >= cached_block_length_)) { + // We can't put this object on the freelist so make this object the + // freelist. It is guaranteed it is larger than the one we have, and + // large enough to hold another allocation of `size`. + CachedBlock** new_list = static_cast<CachedBlock**>(p); + size_t new_size = size / sizeof(CachedBlock*); + + std::copy(cached_blocks_, cached_blocks_ + cached_block_length_, + new_list); + std::fill(new_list + cached_block_length_, new_list + new_size, nullptr); + cached_blocks_ = new_list; + // Make the size fit in uint8_t. This is the power of two, so we don't + // need anything larger. + cached_block_length_ = + static_cast<uint8_t>(std::min(size_t{64}, new_size)); + + return; + } + + auto& cached_head = cached_blocks_[index]; + auto* new_node = static_cast<CachedBlock*>(p); + new_node->next = cached_head; + cached_head = new_node; +#ifdef ADDRESS_SANITIZER + ASAN_POISON_MEMORY_REGION(p, size); +#endif // ADDRESS_SANITIZER + } + + public: + // Allocate space if the current region provides enough space. + bool MaybeAllocateAligned(size_t n, void** out) { + GOOGLE_DCHECK_EQ(internal::AlignUpTo8(n), n); // Must be already aligned. + GOOGLE_DCHECK_GE(limit_, ptr_); + if (PROTOBUF_PREDICT_FALSE(!HasSpace(n))) return false; + *out = AllocateFromExisting(n); + return true; + } + + std::pair<void*, CleanupNode*> AllocateAlignedWithCleanup( + size_t n, const AllocationPolicy* policy) { + GOOGLE_DCHECK_EQ(internal::AlignUpTo8(n), n); // Must be already aligned. + if (PROTOBUF_PREDICT_FALSE(!HasSpace(n + kCleanupSize))) { + return AllocateAlignedWithCleanupFallback(n, policy); + } + return AllocateFromExistingWithCleanupFallback(n); + } + + private: + std::pair<void*, CleanupNode*> AllocateFromExistingWithCleanupFallback( + size_t n) { + void* ret = ptr_; + ptr_ += n; + limit_ -= kCleanupSize; +#ifdef ADDRESS_SANITIZER + ASAN_UNPOISON_MEMORY_REGION(ret, n); + ASAN_UNPOISON_MEMORY_REGION(limit_, kCleanupSize); +#endif // ADDRESS_SANITIZER + return CreatePair(ret, reinterpret_cast<CleanupNode*>(limit_)); + } + + public: + void AddCleanup(void* elem, void (*cleanup)(void*), + const AllocationPolicy* policy) { + auto res = AllocateAlignedWithCleanup(0, policy); + res.second->elem = elem; + res.second->cleanup = cleanup; + } + + void* owner() const { return owner_; } + SerialArena* next() const { return next_; } + void set_next(SerialArena* next) { next_ = next; } + + private: + friend class ThreadSafeArena; + friend class ArenaBenchmark; + + // Creates a new SerialArena inside mem using the remaining memory as for + // future allocations. + static SerialArena* New(SerialArena::Memory mem, void* owner, + ThreadSafeArenaStats* stats); + // Free SerialArena returning the memory passed in to New + template <typename Deallocator> + Memory Free(Deallocator deallocator); + + // Blocks are variable length malloc-ed objects. The following structure + // describes the common header for all blocks. + struct Block { + Block(Block* next, size_t size) : next(next), size(size), start(nullptr) {} + + char* Pointer(size_t n) { + GOOGLE_DCHECK(n <= size); + return reinterpret_cast<char*>(this) + n; + } + + Block* const next; + const size_t size; + CleanupNode* start; + // data follows + }; + + void* owner_; // &ThreadCache of this thread; + Block* head_; // Head of linked list of blocks. + SerialArena* next_; // Next SerialArena in this linked list. + size_t space_used_ = 0; // Necessary for metrics. + std::atomic<size_t> space_allocated_; + + // Next pointer to allocate from. Always 8-byte aligned. Points inside + // head_ (and head_->pos will always be non-canonical). We keep these + // here to reduce indirection. + char* ptr_; + // Limiting address up to which memory can be allocated from the head block. + char* limit_; + // For holding sampling information. The pointer is owned by the + // ThreadSafeArena that holds this serial arena. + ThreadSafeArenaStats* arena_stats_; + + // Repeated*Field and Arena play together to reduce memory consumption by + // reusing blocks. Currently, natural growth of the repeated field types makes + // them allocate blocks of size `8 + 2^N, N>=3`. + // When the repeated field grows returns the previous block and we put it in + // this free list. + // `cached_blocks_[i]` points to the free list for blocks of size `8+2^(i+3)`. + // The array of freelists is grown when needed in `ReturnArrayMemory()`. + struct CachedBlock { + // Simple linked list. + CachedBlock* next; + }; + uint8_t cached_block_length_ = 0; + CachedBlock** cached_blocks_ = nullptr; + + // Constructor is private as only New() should be used. + inline SerialArena(Block* b, void* owner, ThreadSafeArenaStats* stats); + void* AllocateAlignedFallback(size_t n, const AllocationPolicy* policy); + std::pair<void*, CleanupNode*> AllocateAlignedWithCleanupFallback( + size_t n, const AllocationPolicy* policy); + void AllocateNewBlock(size_t n, const AllocationPolicy* policy); + + std::pair<void*, CleanupNode*> CreatePair(void* ptr, CleanupNode* node) { + return {ptr, node}; + } + + public: + static constexpr size_t kBlockHeaderSize = AlignUpTo8(sizeof(Block)); + static constexpr size_t kCleanupSize = AlignUpTo8(sizeof(CleanupNode)); +}; + +// Tag type used to invoke the constructor of message-owned arena. +// Only message-owned arenas use this constructor for creation. +// Such constructors are internal implementation details of the library. +struct MessageOwned { + explicit MessageOwned() = default; +}; + +// This class provides the core Arena memory allocation library. Different +// implementations only need to implement the public interface below. +// Arena is not a template type as that would only be useful if all protos +// in turn would be templates, which will/cannot happen. However separating +// the memory allocation part from the cruft of the API users expect we can +// use #ifdef the select the best implementation based on hardware / OS. +class PROTOBUF_EXPORT ThreadSafeArena { + public: + ThreadSafeArena() { Init(); } + + // Constructor solely used by message-owned arena. + ThreadSafeArena(internal::MessageOwned) : tag_and_id_(kMessageOwnedArena) { + Init(); + } + + ThreadSafeArena(char* mem, size_t size) { InitializeFrom(mem, size); } + + explicit ThreadSafeArena(void* mem, size_t size, + const AllocationPolicy& policy) { + InitializeWithPolicy(mem, size, policy); + } + + // Destructor deletes all owned heap allocated objects, and destructs objects + // that have non-trivial destructors, except for proto2 message objects whose + // destructors can be skipped. Also, frees all blocks except the initial block + // if it was passed in. + ~ThreadSafeArena(); + + uint64_t Reset(); + + uint64_t SpaceAllocated() const; + uint64_t SpaceUsed() const; + + template <AllocationClient alloc_client = AllocationClient::kDefault> + void* AllocateAligned(size_t n, const std::type_info* type) { + SerialArena* arena; + if (PROTOBUF_PREDICT_TRUE(!alloc_policy_.should_record_allocs() && + GetSerialArenaFast(&arena))) { + return arena->AllocateAligned<alloc_client>(n, AllocPolicy()); + } else { + return AllocateAlignedFallback(n, type); + } + } + + void ReturnArrayMemory(void* p, size_t size) { + SerialArena* arena; + if (PROTOBUF_PREDICT_TRUE(GetSerialArenaFast(&arena))) { + arena->ReturnArrayMemory(p, size); + } + } + + // This function allocates n bytes if the common happy case is true and + // returns true. Otherwise does nothing and returns false. This strange + // semantics is necessary to allow callers to program functions that only + // have fallback function calls in tail position. This substantially improves + // code for the happy path. + PROTOBUF_NDEBUG_INLINE bool MaybeAllocateAligned(size_t n, void** out) { + SerialArena* arena; + if (PROTOBUF_PREDICT_TRUE(!alloc_policy_.should_record_allocs() && + GetSerialArenaFromThreadCache(&arena))) { + return arena->MaybeAllocateAligned(n, out); + } + return false; + } + + std::pair<void*, SerialArena::CleanupNode*> AllocateAlignedWithCleanup( + size_t n, const std::type_info* type); + + // Add object pointer and cleanup function pointer to the list. + void AddCleanup(void* elem, void (*cleanup)(void*)); + + // Checks whether this arena is message-owned. + PROTOBUF_ALWAYS_INLINE bool IsMessageOwned() const { + return tag_and_id_ & kMessageOwnedArena; + } + + private: + // Unique for each arena. Changes on Reset(). + uint64_t tag_and_id_ = 0; + // The LSB of tag_and_id_ indicates if the arena is message-owned. + enum : uint64_t { kMessageOwnedArena = 1 }; + + TaggedAllocationPolicyPtr alloc_policy_; // Tagged pointer to AllocPolicy. + + static_assert(std::is_trivially_destructible<SerialArena>{}, + "SerialArena needs to be trivially destructible."); + // Pointer to a linked list of SerialArena. + std::atomic<SerialArena*> threads_; + std::atomic<SerialArena*> hint_; // Fast thread-local block access + + const AllocationPolicy* AllocPolicy() const { return alloc_policy_.get(); } + void InitializeFrom(void* mem, size_t size); + void InitializeWithPolicy(void* mem, size_t size, AllocationPolicy policy); + void* AllocateAlignedFallback(size_t n, const std::type_info* type); + std::pair<void*, SerialArena::CleanupNode*> + AllocateAlignedWithCleanupFallback(size_t n, const std::type_info* type); + + void Init(); + void SetInitialBlock(void* mem, size_t size); + + // Delete or Destruct all objects owned by the arena. + void CleanupList(); + + inline uint64_t LifeCycleId() const { + return tag_and_id_ & ~kMessageOwnedArena; + } + + inline void CacheSerialArena(SerialArena* serial) { + thread_cache().last_serial_arena = serial; + thread_cache().last_lifecycle_id_seen = tag_and_id_; + // TODO(haberman): evaluate whether we would gain efficiency by getting rid + // of hint_. It's the only write we do to ThreadSafeArena in the allocation + // path, which will dirty the cache line. + + hint_.store(serial, std::memory_order_release); + } + + PROTOBUF_NDEBUG_INLINE bool GetSerialArenaFast(SerialArena** arena) { + if (GetSerialArenaFromThreadCache(arena)) return true; + + // Check whether we own the last accessed SerialArena on this arena. This + // fast path optimizes the case where a single thread uses multiple arenas. + ThreadCache* tc = &thread_cache(); + SerialArena* serial = hint_.load(std::memory_order_acquire); + if (PROTOBUF_PREDICT_TRUE(serial != nullptr && serial->owner() == tc)) { + *arena = serial; + return true; + } + return false; + } + + PROTOBUF_NDEBUG_INLINE bool GetSerialArenaFromThreadCache( + SerialArena** arena) { + // If this thread already owns a block in this arena then try to use that. + // This fast path optimizes the case where multiple threads allocate from + // the same arena. + ThreadCache* tc = &thread_cache(); + if (PROTOBUF_PREDICT_TRUE(tc->last_lifecycle_id_seen == tag_and_id_)) { + *arena = tc->last_serial_arena; + return true; + } + return false; + } + SerialArena* GetSerialArenaFallback(void* me); + + template <typename Functor> + void PerSerialArena(Functor fn) { + // By omitting an Acquire barrier we ensure that any user code that doesn't + // properly synchronize Reset() or the destructor will throw a TSAN warning. + SerialArena* serial = threads_.load(std::memory_order_relaxed); + + for (; serial; serial = serial->next()) fn(serial); + } + + // Releases all memory except the first block which it returns. The first + // block might be owned by the user and thus need some extra checks before + // deleting. + SerialArena::Memory Free(size_t* space_allocated); + +#ifdef _MSC_VER +#pragma warning(disable : 4324) +#endif + struct alignas(kCacheAlignment) ThreadCache { +#if defined(GOOGLE_PROTOBUF_NO_THREADLOCAL) + // If we are using the ThreadLocalStorage class to store the ThreadCache, + // then the ThreadCache's default constructor has to be responsible for + // initializing it. + ThreadCache() + : next_lifecycle_id(0), + last_lifecycle_id_seen(-1), + last_serial_arena(nullptr) {} +#endif + + // Number of per-thread lifecycle IDs to reserve. Must be power of two. + // To reduce contention on a global atomic, each thread reserves a batch of + // IDs. The following number is calculated based on a stress test with + // ~6500 threads all frequently allocating a new arena. + static constexpr size_t kPerThreadIds = 256; + // Next lifecycle ID available to this thread. We need to reserve a new + // batch, if `next_lifecycle_id & (kPerThreadIds - 1) == 0`. + uint64_t next_lifecycle_id; + // The ThreadCache is considered valid as long as this matches the + // lifecycle_id of the arena being used. + uint64_t last_lifecycle_id_seen; + SerialArena* last_serial_arena; + }; + + // Lifecycle_id can be highly contended variable in a situation of lots of + // arena creation. Make sure that other global variables are not sharing the + // cacheline. +#ifdef _MSC_VER +#pragma warning(disable : 4324) +#endif + struct alignas(kCacheAlignment) CacheAlignedLifecycleIdGenerator { + std::atomic<LifecycleIdAtomic> id; + }; + static CacheAlignedLifecycleIdGenerator lifecycle_id_generator_; +#if defined(GOOGLE_PROTOBUF_NO_THREADLOCAL) + // iOS does not support __thread keyword so we use a custom thread local + // storage class we implemented. + static ThreadCache& thread_cache(); +#elif defined(PROTOBUF_USE_DLLS) + // Thread local variables cannot be exposed through DLL interface but we can + // wrap them in static functions. + static ThreadCache& thread_cache(); +#else + static PROTOBUF_THREAD_LOCAL ThreadCache thread_cache_; + static ThreadCache& thread_cache() { return thread_cache_; } +#endif + + ThreadSafeArenaStatsHandle arena_stats_; + + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ThreadSafeArena); + // All protos have pointers back to the arena hence Arena must have + // pointer stability. + ThreadSafeArena(ThreadSafeArena&&) = delete; + ThreadSafeArena& operator=(ThreadSafeArena&&) = delete; + + public: + // kBlockHeaderSize is sizeof(Block), aligned up to the nearest multiple of 8 + // to protect the invariant that pos is always at a multiple of 8. + static constexpr size_t kBlockHeaderSize = SerialArena::kBlockHeaderSize; + static constexpr size_t kSerialArenaSize = + (sizeof(SerialArena) + 7) & static_cast<size_t>(-8); + static_assert(kBlockHeaderSize % 8 == 0, + "kBlockHeaderSize must be a multiple of 8."); + static_assert(kSerialArenaSize % 8 == 0, + "kSerialArenaSize must be a multiple of 8."); +}; + +} // namespace internal +} // namespace protobuf +} // namespace google + +#include <google/protobuf/port_undef.inc> + +#endif // GOOGLE_PROTOBUF_ARENA_IMPL_H__ diff --git a/toolkit/components/protobuf/src/google/protobuf/arenastring.cc b/toolkit/components/protobuf/src/google/protobuf/arenastring.cc new file mode 100644 index 0000000000..af0c9df6bc --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/arenastring.cc @@ -0,0 +1,267 @@ +// 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. + +#include <google/protobuf/arenastring.h> + +#include <cstddef> +#include <google/protobuf/stubs/logging.h> +#include <google/protobuf/stubs/common.h> +#include <google/protobuf/io/coded_stream.h> +#include <google/protobuf/stubs/mutex.h> +#include <google/protobuf/stubs/strutil.h> +#include <google/protobuf/message_lite.h> +#include <google/protobuf/parse_context.h> +#include <google/protobuf/stubs/stl_util.h> + +// clang-format off +#include <google/protobuf/port_def.inc> +// clang-format on + +namespace google { +namespace protobuf { +namespace internal { + +namespace { + +// TaggedStringPtr::Flags uses the lower 2 bits as tags. +// Enforce that allocated data aligns to at least 4 bytes, and that +// the alignment of the global const string value does as well. +// The alignment guaranteed by `new std::string` depends on both: +// - new align = __STDCPP_DEFAULT_NEW_ALIGNMENT__ / max_align_t +// - alignof(std::string) +#ifdef __STDCPP_DEFAULT_NEW_ALIGNMENT__ +constexpr size_t kNewAlign = __STDCPP_DEFAULT_NEW_ALIGNMENT__; +#elif (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) < 40900 +constexpr size_t kNewAlign = alignof(::max_align_t); +#else +constexpr size_t kNewAlign = alignof(std::max_align_t); +#endif +constexpr size_t kStringAlign = alignof(std::string); + +static_assert((kStringAlign > kNewAlign ? kStringAlign : kNewAlign) >= 4, ""); +static_assert(alignof(ExplicitlyConstructedArenaString) >= 4, ""); + +} // namespace + +const std::string& LazyString::Init() const { + static WrappedMutex mu{GOOGLE_PROTOBUF_LINKER_INITIALIZED}; + mu.Lock(); + const std::string* res = inited_.load(std::memory_order_acquire); + if (res == nullptr) { + auto init_value = init_value_; + res = ::new (static_cast<void*>(string_buf_)) + std::string(init_value.ptr, init_value.size); + inited_.store(res, std::memory_order_release); + } + mu.Unlock(); + return *res; +} + +namespace { + + +#if defined(NDEBUG) || !GOOGLE_PROTOBUF_INTERNAL_DONATE_STEAL + +class ScopedCheckPtrInvariants { + public: + explicit ScopedCheckPtrInvariants(const TaggedStringPtr*) {} +}; + +#endif // NDEBUG || !GOOGLE_PROTOBUF_INTERNAL_DONATE_STEAL + +// Creates a heap allocated std::string value. +inline TaggedStringPtr CreateString(ConstStringParam value) { + TaggedStringPtr res; + res.SetAllocated(new std::string(value.data(), value.length())); + return res; +} + +#if !GOOGLE_PROTOBUF_INTERNAL_DONATE_STEAL + +// Creates an arena allocated std::string value. +TaggedStringPtr CreateArenaString(Arena& arena, ConstStringParam s) { + TaggedStringPtr res; + res.SetMutableArena(Arena::Create<std::string>(&arena, s.data(), s.length())); + return res; +} + +#endif // !GOOGLE_PROTOBUF_INTERNAL_DONATE_STEAL + +} // namespace + +void ArenaStringPtr::Set(ConstStringParam value, Arena* arena) { + ScopedCheckPtrInvariants check(&tagged_ptr_); + if (IsDefault()) { + // If we're not on an arena, skip straight to a true string to avoid + // possible copy cost later. + tagged_ptr_ = arena != nullptr ? CreateArenaString(*arena, value) + : CreateString(value); + } else { + UnsafeMutablePointer()->assign(value.data(), value.length()); + } +} + +void ArenaStringPtr::Set(std::string&& value, Arena* arena) { + ScopedCheckPtrInvariants check(&tagged_ptr_); + if (IsDefault()) { + NewString(arena, std::move(value)); + } else if (IsFixedSizeArena()) { + std::string* current = tagged_ptr_.Get(); + auto* s = new (current) std::string(std::move(value)); + arena->OwnDestructor(s); + tagged_ptr_.SetMutableArena(s); + } else /* !IsFixedSizeArena() */ { + *UnsafeMutablePointer() = std::move(value); + } +} + +std::string* ArenaStringPtr::Mutable(Arena* arena) { + ScopedCheckPtrInvariants check(&tagged_ptr_); + if (tagged_ptr_.IsMutable()) { + return tagged_ptr_.Get(); + } else { + return MutableSlow(arena); + } +} + +std::string* ArenaStringPtr::Mutable(const LazyString& default_value, + Arena* arena) { + ScopedCheckPtrInvariants check(&tagged_ptr_); + if (tagged_ptr_.IsMutable()) { + return tagged_ptr_.Get(); + } else { + return MutableSlow(arena, default_value); + } +} + +std::string* ArenaStringPtr::MutableNoCopy(Arena* arena) { + ScopedCheckPtrInvariants check(&tagged_ptr_); + if (tagged_ptr_.IsMutable()) { + return tagged_ptr_.Get(); + } else { + GOOGLE_DCHECK(IsDefault()); + // Allocate empty. The contents are not relevant. + return NewString(arena); + } +} + +template <typename... Lazy> +std::string* ArenaStringPtr::MutableSlow(::google::protobuf::Arena* arena, + const Lazy&... lazy_default) { + GOOGLE_DCHECK(IsDefault()); + + // For empty defaults, this ends up calling the default constructor which is + // more efficient than a copy construction from + // GetEmptyStringAlreadyInited(). + return NewString(arena, lazy_default.get()...); +} + +std::string* ArenaStringPtr::Release() { + ScopedCheckPtrInvariants check(&tagged_ptr_); + if (IsDefault()) return nullptr; + + std::string* released = tagged_ptr_.Get(); + if (tagged_ptr_.IsArena()) { + released = tagged_ptr_.IsMutable() ? new std::string(std::move(*released)) + : new std::string(*released); + } + InitDefault(); + return released; +} + +void ArenaStringPtr::SetAllocated(std::string* value, Arena* arena) { + ScopedCheckPtrInvariants check(&tagged_ptr_); + // Release what we have first. + Destroy(); + + if (value == nullptr) { + InitDefault(); + } else { +#ifndef NDEBUG + // On debug builds, copy the string so the address differs. delete will + // fail if value was a stack-allocated temporary/etc., which would have + // failed when arena ran its cleanup list. + std::string* new_value = new std::string(std::move(*value)); + delete value; + value = new_value; +#endif // !NDEBUG + InitAllocated(value, arena); + } +} + +void ArenaStringPtr::Destroy() { + delete tagged_ptr_.GetIfAllocated(); +} + +void ArenaStringPtr::ClearToEmpty() { + ScopedCheckPtrInvariants check(&tagged_ptr_); + if (IsDefault()) { + // Already set to default -- do nothing. + } else { + // Unconditionally mask away the tag. + // + // UpdateArenaString uses assign when capacity is larger than the new + // value, which is trivially true in the donated string case. + // const_cast<std::string*>(PtrValue<std::string>())->clear(); + tagged_ptr_.Get()->clear(); + } +} + +void ArenaStringPtr::ClearToDefault(const LazyString& default_value, + ::google::protobuf::Arena* arena) { + ScopedCheckPtrInvariants check(&tagged_ptr_); + (void)arena; + if (IsDefault()) { + // Already set to default -- do nothing. + } else { + UnsafeMutablePointer()->assign(default_value.get()); + } +} + +const char* EpsCopyInputStream::ReadArenaString(const char* ptr, + ArenaStringPtr* s, + Arena* arena) { + ScopedCheckPtrInvariants check(&s->tagged_ptr_); + GOOGLE_DCHECK(arena != nullptr); + + int size = ReadSize(&ptr); + if (!ptr) return nullptr; + + auto* str = s->NewString(arena); + ptr = ReadString(ptr, size, str); + GOOGLE_PROTOBUF_PARSER_ASSERT(ptr); + return ptr; +} + +} // namespace internal +} // namespace protobuf +} // namespace google + +#include <google/protobuf/port_undef.inc> diff --git a/toolkit/components/protobuf/src/google/protobuf/arenastring.h b/toolkit/components/protobuf/src/google/protobuf/arenastring.h new file mode 100644 index 0000000000..6bc8395f23 --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/arenastring.h @@ -0,0 +1,480 @@ +// 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. + +#ifndef GOOGLE_PROTOBUF_ARENASTRING_H__ +#define GOOGLE_PROTOBUF_ARENASTRING_H__ + +#include <algorithm> +#include <string> +#include <type_traits> +#include <utility> + +#include <google/protobuf/stubs/logging.h> +#include <google/protobuf/stubs/common.h> +#include <google/protobuf/arena.h> +#include <google/protobuf/port.h> +#include <google/protobuf/explicitly_constructed.h> + +// must be last: +#include <google/protobuf/port_def.inc> + +#ifdef SWIG +#error "You cannot SWIG proto headers" +#endif + + +namespace google { +namespace protobuf { +namespace internal { +class EpsCopyInputStream; + +class SwapFieldHelper; + +// Declared in message_lite.h +PROTOBUF_EXPORT extern ExplicitlyConstructedArenaString + fixed_address_empty_string; + +// Lazy string instance to support string fields with non-empty default. +// These are initialized on the first call to .get(). +class PROTOBUF_EXPORT LazyString { + public: + // We explicitly make LazyString an aggregate so that MSVC can do constant + // initialization on it without marking it `constexpr`. + // We do not want to use `constexpr` because it makes it harder to have extern + // storage for it and causes library bloat. + struct InitValue { + const char* ptr; + size_t size; + }; + // We keep a union of the initialization value and the std::string to save on + // space. We don't need the string array after Init() is done. + union { + mutable InitValue init_value_; + alignas(std::string) mutable char string_buf_[sizeof(std::string)]; + }; + mutable std::atomic<const std::string*> inited_; + + const std::string& get() const { + // This check generates less code than a call-once invocation. + auto* res = inited_.load(std::memory_order_acquire); + if (PROTOBUF_PREDICT_FALSE(res == nullptr)) return Init(); + return *res; + } + + private: + // Initialize the string in `string_buf_`, update `inited_` and return it. + // We return it here to avoid having to read it again in the inlined code. + const std::string& Init() const; +}; + +class TaggedStringPtr { + public: + // Bit flags qualifying string properties. We can use 2 bits as + // ptr_ is guaranteed and enforced to be aligned on 4 byte boundaries. + enum Flags { + kArenaBit = 0x1, // ptr is arena allocated + kMutableBit = 0x2, // ptr contents are fully mutable + kMask = 0x3 // Bit mask + }; + + // Composed logical types + enum Type { + // Default strings are immutable and never owned. + kDefault = 0, + + // Allocated strings are mutable and (as the name implies) owned. + // A heap allocated string must be deleted. + kAllocated = kMutableBit, + + // Mutable arena strings are strings where the string instance is owned + // by the arena, but the string contents itself are owned by the string + // instance. Mutable arena string instances need to be destroyed which is + // typically done through a cleanup action added to the arena owning it. + kMutableArena = kArenaBit | kMutableBit, + + // Fixed size arena strings are strings where both the string instance and + // the string contents are fully owned by the arena. Fixed size arena + // strings are a platform and c++ library specific customization. Fixed + // size arena strings are immutable, with the exception of custom internal + // updates to the content that fit inside the existing capacity. + // Fixed size arena strings must never be deleted or destroyed. + kFixedSizeArena = kArenaBit, + }; + + TaggedStringPtr() = default; + explicit constexpr TaggedStringPtr(ExplicitlyConstructedArenaString* ptr) + : ptr_(ptr) {} + + // Sets the value to `p`, tagging the value as being a 'default' value. + // See documentation for kDefault for more info. + inline const std::string* SetDefault(const std::string* p) { + return TagAs(kDefault, const_cast<std::string*>(p)); + } + + // Sets the value to `p`, tagging the value as a heap allocated value. + // Allocated strings are mutable and (as the name implies) owned. + // `p` must not be null + inline std::string* SetAllocated(std::string* p) { + return TagAs(kAllocated, p); + } + + // Sets the value to `p`, tagging the value as a fixed size arena string. + // See documentation for kFixedSizeArena for more info. + // `p` must not be null + inline std::string* SetFixedSizeArena(std::string* p) { + return TagAs(kFixedSizeArena, p); + } + + // Sets the value to `p`, tagging the value as a mutable arena string. + // See documentation for kMutableArena for more info. + // `p` must not be null + inline std::string* SetMutableArena(std::string* p) { + return TagAs(kMutableArena, p); + } + + // Returns true if the contents of the current string are fully mutable. + inline bool IsMutable() const { return as_int() & kMutableBit; } + + // Returns true if the current string is an immutable default value. + inline bool IsDefault() const { return (as_int() & kMask) == kDefault; } + + // If the current string is a heap-allocated mutable value, returns a pointer + // to it. Returns nullptr otherwise. + inline std::string *GetIfAllocated() const { + auto allocated = as_int() ^ kAllocated; + if (allocated & kMask) return nullptr; + + auto ptr = reinterpret_cast<std::string*>(allocated); + PROTOBUF_ASSUME(ptr != nullptr); + return ptr; + } + + // Returns true if the current string is an arena allocated value. + // This means it's either a mutable or fixed size arena string. + inline bool IsArena() const { return as_int() & kArenaBit; } + + // Returns true if the current string is a fixed size arena allocated value. + inline bool IsFixedSizeArena() const { + return (as_int() & kMask) == kFixedSizeArena; + } + + // Returns the contained string pointer. + inline std::string* Get() const { + return reinterpret_cast<std::string*>(as_int() & ~kMask); + } + + // Returns true if the contained pointer is null, indicating some error. + // The Null value is only used during parsing for temporary values. + // A persisted ArenaStringPtr value is never null. + inline bool IsNull() { return ptr_ == nullptr; } + + private: + static inline void assert_aligned(const void* p) { + GOOGLE_DCHECK_EQ(reinterpret_cast<uintptr_t>(p) & kMask, 0UL); + } + + inline std::string* TagAs(Type type, std::string* p) { + GOOGLE_DCHECK(p != nullptr); + assert_aligned(p); + ptr_ = reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(p) | type); + return p; + } + + uintptr_t as_int() const { return reinterpret_cast<uintptr_t>(ptr_); } + void* ptr_; +}; + +static_assert(std::is_trivial<TaggedStringPtr>::value, + "TaggedStringPtr must be trivial"); + +// This class encapsulates a pointer to a std::string with or without arena +// owned contents, tagged by the bottom bits of the string pointer. It is a +// high-level wrapper that almost directly corresponds to the interface required +// by string fields in generated code. It replaces the old std::string* pointer +// in such cases. +// +// The string pointer is tagged to be either a default, externally owned value, +// a mutable heap allocated value, or an arena allocated value. The object uses +// a single global instance of an empty string that is used as the initial +// default value. Fields that have empty default values directly use this global +// default. Fields that have non empty default values are supported through +// lazily initialized default values managed by the LazyString class. +// +// Generated code and reflection code both ensure that ptr_ is never null. +// Because ArenaStringPtr is used in oneof unions, its constructor is a NOP and +// the field is always manually initialized via method calls. +// +// See TaggedStringPtr for more information about the types of string values +// being held, and the mutable and ownership invariants for each type. +struct PROTOBUF_EXPORT ArenaStringPtr { + ArenaStringPtr() = default; + constexpr ArenaStringPtr(ExplicitlyConstructedArenaString* default_value, + ConstantInitialized) + : tagged_ptr_(default_value) {} + + // Called from generated code / reflection runtime only. Resets value to point + // to a default string pointer, with the semantics that this ArenaStringPtr + // does not own the pointed-to memory. Disregards initial value of ptr_ (so + // this is the *ONLY* safe method to call after construction or when + // reinitializing after becoming the active field in a oneof union). + inline void InitDefault(); + + // Similar to `InitDefault` except that it allows the default value to be + // initialized to an externally owned string. This method is called from + // parsing code. `str` must not be null and outlive this instance. + inline void InitExternal(const std::string* str); + + // Called from generated code / reflection runtime only. Resets the value of + // this instances to the heap allocated value in `str`. `str` must not be + // null. Invokes `arena->Own(str)` to transfer ownership into the arena if + // `arena` is not null, else, `str` will be owned by ArenaStringPtr. This + // function should only be used to initialize a ArenaStringPtr or on an + // instance known to not carry any heap allocated value. + inline void InitAllocated(std::string* str, Arena* arena); + + void Set(ConstStringParam value, Arena* arena); + void Set(std::string&& value, Arena* arena); + void Set(const char* s, Arena* arena); + void Set(const char* s, size_t n, Arena* arena); + + void SetBytes(ConstStringParam value, Arena* arena); + void SetBytes(std::string&& value, Arena* arena); + void SetBytes(const char* s, Arena* arena); + void SetBytes(const void* p, size_t n, Arena* arena); + + template <typename RefWrappedType> + void Set(std::reference_wrapper<RefWrappedType> const_string_ref, + ::google::protobuf::Arena* arena) { + Set(const_string_ref.get(), arena); + } + + // Returns a mutable std::string reference. + // The version accepting a `LazyString` value is used in the generated code to + // initialize mutable copies for fields with a non-empty default where the + // default value is lazily initialized. + std::string* Mutable(Arena* arena); + std::string* Mutable(const LazyString& default_value, Arena* arena); + + // Gets a mutable pointer with unspecified contents. + // This function is identical to Mutable(), except it is optimized for the + // case where the caller is not interested in the current contents. For + // example, if the current field is not mutable, it will re-initialize the + // value with an empty string rather than a (non-empty) default value. + // Likewise, if the current value is a fixed size arena string with contents, + // it will be initialized into an empty mutable arena string. + std::string* MutableNoCopy(Arena* arena); + + // Basic accessors. + PROTOBUF_NDEBUG_INLINE const std::string& Get() const { + // Unconditionally mask away the tag. + return *tagged_ptr_.Get(); + } + + // Returns a pointer to the stored contents for this instance. + // This method is for internal debugging and tracking purposes only. + PROTOBUF_NDEBUG_INLINE const std::string* UnsafeGetPointer() const + PROTOBUF_RETURNS_NONNULL { + return tagged_ptr_.Get(); + } + + // Release returns a std::string* instance that is heap-allocated and is not + // Own()'d by any arena. If the field is not set, this returns nullptr. The + // caller retains ownership. Clears this field back to the default state. + // Used to implement release_<field>() methods on generated classes. + PROTOBUF_NODISCARD std::string* Release(); + + // Takes a std::string that is heap-allocated, and takes ownership. The + // std::string's destructor is registered with the arena. Used to implement + // set_allocated_<field> in generated classes. + void SetAllocated(std::string* value, Arena* arena); + + // Frees storage (if not on an arena). + void Destroy(); + + // Clears content, but keeps allocated std::string, to avoid the overhead of + // heap operations. After this returns, the content (as seen by the user) will + // always be the empty std::string. Assumes that |default_value| is an empty + // std::string. + void ClearToEmpty(); + + // Clears content, assuming that the current value is not the empty + // string default. + void ClearNonDefaultToEmpty(); + + // Clears content, but keeps allocated std::string if arena != nullptr, to + // avoid the overhead of heap operations. After this returns, the content + // (as seen by the user) will always be equal to |default_value|. + void ClearToDefault(const LazyString& default_value, ::google::protobuf::Arena* arena); + + // Swaps internal pointers. Arena-safety semantics: this is guarded by the + // logic in Swap()/UnsafeArenaSwap() at the message level, so this method is + // 'unsafe' if called directly. + inline PROTOBUF_NDEBUG_INLINE static void InternalSwap(ArenaStringPtr* rhs, + Arena* rhs_arena, + ArenaStringPtr* lhs, + Arena* lhs_arena); + + // Internal setter used only at parse time to directly set a donated string + // value. + void UnsafeSetTaggedPointer(TaggedStringPtr value) { tagged_ptr_ = value; } + // Generated code only! An optimization, in certain cases the generated + // code is certain we can obtain a std::string with no default checks and + // tag tests. + std::string* UnsafeMutablePointer() PROTOBUF_RETURNS_NONNULL; + + // Returns true if this instances holds an immutable default value. + inline bool IsDefault() const { return tagged_ptr_.IsDefault(); } + + private: + template <typename... Args> + inline std::string* NewString(Arena* arena, Args&&... args) { + if (arena == nullptr) { + auto* s = new std::string(std::forward<Args>(args)...); + return tagged_ptr_.SetAllocated(s); + } else { + auto* s = Arena::Create<std::string>(arena, std::forward<Args>(args)...); + return tagged_ptr_.SetMutableArena(s); + } + } + + TaggedStringPtr tagged_ptr_; + + bool IsFixedSizeArena() const { return false; } + + // Swaps tagged pointer without debug hardening. This is to allow python + // protobuf to maintain pointer stability even in DEBUG builds. + inline PROTOBUF_NDEBUG_INLINE static void UnsafeShallowSwap( + ArenaStringPtr* rhs, ArenaStringPtr* lhs) { + std::swap(lhs->tagged_ptr_, rhs->tagged_ptr_); + } + + friend class ::google::protobuf::internal::SwapFieldHelper; + friend class TcParser; + + // Slow paths. + + // MutableSlow requires that !IsString() || IsDefault + // Variadic to support 0 args for empty default and 1 arg for LazyString. + template <typename... Lazy> + std::string* MutableSlow(::google::protobuf::Arena* arena, const Lazy&... lazy_default); + + friend class EpsCopyInputStream; +}; + +inline void ArenaStringPtr::InitDefault() { + tagged_ptr_ = TaggedStringPtr(&fixed_address_empty_string); +} + +inline void ArenaStringPtr::InitExternal(const std::string* str) { + tagged_ptr_.SetDefault(str); +} + +inline void ArenaStringPtr::InitAllocated(std::string* str, Arena* arena) { + if (arena != nullptr) { + tagged_ptr_.SetMutableArena(str); + arena->Own(str); + } else { + tagged_ptr_.SetAllocated(str); + } +} + +inline void ArenaStringPtr::Set(const char* s, Arena* arena) { + Set(ConstStringParam{s}, arena); +} + +inline void ArenaStringPtr::Set(const char* s, size_t n, Arena* arena) { + Set(ConstStringParam{s, n}, arena); +} + +inline void ArenaStringPtr::SetBytes(ConstStringParam value, Arena* arena) { + Set(value, arena); +} + +inline void ArenaStringPtr::SetBytes(std::string&& value, Arena* arena) { + Set(std::move(value), arena); +} + +inline void ArenaStringPtr::SetBytes(const char* s, Arena* arena) { + Set(s, arena); +} + +inline void ArenaStringPtr::SetBytes(const void* p, size_t n, Arena* arena) { + Set(ConstStringParam{static_cast<const char*>(p), n}, arena); +} + +// Make sure rhs_arena allocated rhs, and lhs_arena allocated lhs. +inline PROTOBUF_NDEBUG_INLINE void ArenaStringPtr::InternalSwap( // + ArenaStringPtr* rhs, Arena* rhs_arena, // + ArenaStringPtr* lhs, Arena* lhs_arena) { + // Silence unused variable warnings in release buildls. + (void)rhs_arena; + (void)lhs_arena; + std::swap(lhs->tagged_ptr_, rhs->tagged_ptr_); +#ifdef PROTOBUF_FORCE_COPY_IN_SWAP + auto force_realloc = [](ArenaStringPtr* p, Arena* arena) { + if (p->IsDefault()) return; + std::string* old_value = p->tagged_ptr_.Get(); + std::string* new_value = + p->IsFixedSizeArena() + ? Arena::Create<std::string>(arena, *old_value) + : Arena::Create<std::string>(arena, std::move(*old_value)); + if (arena == nullptr) { + delete old_value; + p->tagged_ptr_.SetAllocated(new_value); + } else { + p->tagged_ptr_.SetMutableArena(new_value); + } + }; + // Because, at this point, tagged_ptr_ has been swapped, arena should also be + // swapped. + force_realloc(lhs, rhs_arena); + force_realloc(rhs, lhs_arena); +#endif // PROTOBUF_FORCE_COPY_IN_SWAP +} + +inline void ArenaStringPtr::ClearNonDefaultToEmpty() { + // Unconditionally mask away the tag. + tagged_ptr_.Get()->clear(); +} + +inline std::string* ArenaStringPtr::UnsafeMutablePointer() { + GOOGLE_DCHECK(tagged_ptr_.IsMutable()); + GOOGLE_DCHECK(tagged_ptr_.Get() != nullptr); + return tagged_ptr_.Get(); +} + + +} // namespace internal +} // namespace protobuf +} // namespace google + +#include <google/protobuf/port_undef.inc> + +#endif // GOOGLE_PROTOBUF_ARENASTRING_H__ diff --git a/toolkit/components/protobuf/src/google/protobuf/arenaz_sampler.cc b/toolkit/components/protobuf/src/google/protobuf/arenaz_sampler.cc new file mode 100644 index 0000000000..0eac693d98 --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/arenaz_sampler.cc @@ -0,0 +1,177 @@ +// 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. + +#include <google/protobuf/arenaz_sampler.h> + +#include <atomic> +#include <cstdint> +#include <limits> + + +// Must be included last. +#include <google/protobuf/port_def.inc> + +namespace google { +namespace protobuf { +namespace internal { + +ThreadSafeArenazSampler& GlobalThreadSafeArenazSampler() { + static auto* sampler = new ThreadSafeArenazSampler(); + return *sampler; +} + +void UnsampleSlow(ThreadSafeArenaStats* info) { + GlobalThreadSafeArenazSampler().Unregister(info); +} + +#if defined(PROTOBUF_ARENAZ_SAMPLE) +namespace { + +PROTOBUF_CONSTINIT std::atomic<bool> g_arenaz_enabled{true}; +PROTOBUF_CONSTINIT std::atomic<int32_t> g_arenaz_sample_parameter{1 << 10}; +PROTOBUF_THREAD_LOCAL absl::profiling_internal::ExponentialBiased + g_exponential_biased_generator; + +} // namespace + +PROTOBUF_THREAD_LOCAL int64_t global_next_sample = 1LL << 10; + +ThreadSafeArenaStats::ThreadSafeArenaStats() { PrepareForSampling(); } +ThreadSafeArenaStats::~ThreadSafeArenaStats() = default; + +void ThreadSafeArenaStats::PrepareForSampling() { + num_allocations.store(0, std::memory_order_relaxed); + num_resets.store(0, std::memory_order_relaxed); + bytes_requested.store(0, std::memory_order_relaxed); + bytes_allocated.store(0, std::memory_order_relaxed); + bytes_wasted.store(0, std::memory_order_relaxed); + max_bytes_allocated.store(0, std::memory_order_relaxed); + thread_ids.store(0, std::memory_order_relaxed); + // The inliner makes hardcoded skip_count difficult (especially when combined + // with LTO). We use the ability to exclude stacks by regex when encoding + // instead. + depth = absl::GetStackTrace(stack, kMaxStackDepth, /* skip_count= */ 0); +} + +void RecordResetSlow(ThreadSafeArenaStats* info) { + const size_t max_bytes = + info->max_bytes_allocated.load(std::memory_order_relaxed); + const size_t allocated_bytes = + info->bytes_allocated.load(std::memory_order_relaxed); + if (max_bytes < allocated_bytes) { + info->max_bytes_allocated.store(allocated_bytes); + } + info->bytes_requested.store(0, std::memory_order_relaxed); + info->bytes_allocated.store(0, std::memory_order_relaxed); + info->bytes_wasted.fetch_add(0, std::memory_order_relaxed); + info->num_allocations.fetch_add(0, std::memory_order_relaxed); + info->num_resets.fetch_add(1, std::memory_order_relaxed); +} + +void RecordAllocateSlow(ThreadSafeArenaStats* info, size_t requested, + size_t allocated, size_t wasted) { + info->bytes_requested.fetch_add(requested, std::memory_order_relaxed); + info->bytes_allocated.fetch_add(allocated, std::memory_order_relaxed); + info->bytes_wasted.fetch_add(wasted, std::memory_order_relaxed); + info->num_allocations.fetch_add(1, std::memory_order_relaxed); + const uint64_t tid = (1ULL << (GetCachedTID() % 63)); + const uint64_t thread_ids = info->thread_ids.load(std::memory_order_relaxed); + if (!(thread_ids & tid)) { + info->thread_ids.store(thread_ids | tid, std::memory_order_relaxed); + } +} + +ThreadSafeArenaStats* SampleSlow(int64_t* next_sample) { + bool first = *next_sample < 0; + *next_sample = g_exponential_biased_generator.GetStride( + g_arenaz_sample_parameter.load(std::memory_order_relaxed)); + // Small values of interval are equivalent to just sampling next time. + ABSL_ASSERT(*next_sample >= 1); + + // g_arenaz_enabled can be dynamically flipped, we need to set a threshold low + // enough that we will start sampling in a reasonable time, so we just use the + // default sampling rate. + if (!g_arenaz_enabled.load(std::memory_order_relaxed)) return nullptr; + // We will only be negative on our first count, so we should just retry in + // that case. + if (first) { + if (PROTOBUF_PREDICT_TRUE(--*next_sample > 0)) return nullptr; + return SampleSlow(next_sample); + } + + return GlobalThreadSafeArenazSampler().Register(); +} + +void SetThreadSafeArenazEnabled(bool enabled) { + g_arenaz_enabled.store(enabled, std::memory_order_release); +} + +void SetThreadSafeArenazSampleParameter(int32_t rate) { + if (rate > 0) { + g_arenaz_sample_parameter.store(rate, std::memory_order_release); + } else { + ABSL_RAW_LOG(ERROR, "Invalid thread safe arenaz sample rate: %lld", + static_cast<long long>(rate)); // NOLINT(runtime/int) + } +} + +void SetThreadSafeArenazMaxSamples(int32_t max) { + if (max > 0) { + GlobalThreadSafeArenazSampler().SetMaxSamples(max); + } else { + ABSL_RAW_LOG(ERROR, "Invalid thread safe arenaz max samples: %lld", + static_cast<long long>(max)); // NOLINT(runtime/int) + } +} + +void SetThreadSafeArenazGlobalNextSample(int64_t next_sample) { + if (next_sample >= 0) { + global_next_sample = next_sample; + } else { + ABSL_RAW_LOG(ERROR, "Invalid thread safe arenaz next sample: %lld", + static_cast<long long>(next_sample)); // NOLINT(runtime/int) + } +} + +#else +ThreadSafeArenaStats* SampleSlow(int64_t* next_sample) { + *next_sample = std::numeric_limits<int64_t>::max(); + return nullptr; +} + +void SetThreadSafeArenazEnabled(bool enabled) {} +void SetThreadSafeArenazSampleParameter(int32_t rate) {} +void SetThreadSafeArenazMaxSamples(int32_t max) {} +void SetThreadSafeArenazGlobalNextSample(int64_t next_sample) {} +#endif // defined(PROTOBUF_ARENAZ_SAMPLE) + +} // namespace internal +} // namespace protobuf +} // namespace google diff --git a/toolkit/components/protobuf/src/google/protobuf/arenaz_sampler.h b/toolkit/components/protobuf/src/google/protobuf/arenaz_sampler.h new file mode 100644 index 0000000000..b04b0cc678 --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/arenaz_sampler.h @@ -0,0 +1,207 @@ +// 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. + +#ifndef GOOGLE_PROTOBUF_SRC_GOOGLE_PROTOBUF_ARENAZ_SAMPLER_H__ +#define GOOGLE_PROTOBUF_SRC_GOOGLE_PROTOBUF_ARENAZ_SAMPLER_H__ + +#include <atomic> +#include <cstddef> +#include <cstdint> + + +// Must be included last. +#include <google/protobuf/port_def.inc> + +namespace google { +namespace protobuf { +namespace internal { + +#if defined(PROTOBUF_ARENAZ_SAMPLE) +struct ThreadSafeArenaStats; +void RecordResetSlow(ThreadSafeArenaStats* info); +void RecordAllocateSlow(ThreadSafeArenaStats* info, size_t requested, + size_t allocated, size_t wasted); +// Stores information about a sampled thread safe arena. All mutations to this +// *must* be made through `Record*` functions below. All reads from this *must* +// only occur in the callback to `ThreadSafeArenazSampler::Iterate`. +struct ThreadSafeArenaStats + : public absl::profiling_internal::Sample<ThreadSafeArenaStats> { + // Constructs the object but does not fill in any fields. + ThreadSafeArenaStats(); + ~ThreadSafeArenaStats(); + + // Puts the object into a clean state, fills in the logically `const` members, + // blocking for any readers that are currently sampling the object. + void PrepareForSampling() ABSL_EXCLUSIVE_LOCKS_REQUIRED(init_mu); + + // These fields are mutated by the various Record* APIs and need to be + // thread-safe. + std::atomic<int> num_allocations; + std::atomic<int> num_resets; + std::atomic<size_t> bytes_requested; + std::atomic<size_t> bytes_allocated; + std::atomic<size_t> bytes_wasted; + // Records the largest size an arena ever had. Maintained across resets. + std::atomic<size_t> max_bytes_allocated; + // Bit i when set to 1 indicates that a thread with tid % 63 = i accessed the + // underlying arena. The field is maintained across resets. + std::atomic<uint64_t> thread_ids; + + // All of the fields below are set by `PrepareForSampling`, they must not + // be mutated in `Record*` functions. They are logically `const` in that + // sense. These are guarded by init_mu, but that is not externalized to + // clients, who can only read them during + // `ThreadSafeArenazSampler::Iterate` which will hold the lock. + static constexpr int kMaxStackDepth = 64; + int32_t depth; + void* stack[kMaxStackDepth]; + static void RecordAllocateStats(ThreadSafeArenaStats* info, size_t requested, + size_t allocated, size_t wasted) { + if (PROTOBUF_PREDICT_TRUE(info == nullptr)) return; + RecordAllocateSlow(info, requested, allocated, wasted); + } +}; + +ThreadSafeArenaStats* SampleSlow(int64_t* next_sample); +void UnsampleSlow(ThreadSafeArenaStats* info); + +class ThreadSafeArenaStatsHandle { + public: + explicit ThreadSafeArenaStatsHandle() = default; + explicit ThreadSafeArenaStatsHandle(ThreadSafeArenaStats* info) + : info_(info) {} + + ~ThreadSafeArenaStatsHandle() { + if (PROTOBUF_PREDICT_TRUE(info_ == nullptr)) return; + UnsampleSlow(info_); + } + + ThreadSafeArenaStatsHandle(ThreadSafeArenaStatsHandle&& other) noexcept + : info_(absl::exchange(other.info_, nullptr)) {} + + ThreadSafeArenaStatsHandle& operator=( + ThreadSafeArenaStatsHandle&& other) noexcept { + if (PROTOBUF_PREDICT_FALSE(info_ != nullptr)) { + UnsampleSlow(info_); + } + info_ = absl::exchange(other.info_, nullptr); + return *this; + } + + void RecordReset() { + if (PROTOBUF_PREDICT_TRUE(info_ == nullptr)) return; + RecordResetSlow(info_); + } + + ThreadSafeArenaStats* MutableStats() { return info_; } + + friend void swap(ThreadSafeArenaStatsHandle& lhs, + ThreadSafeArenaStatsHandle& rhs) { + std::swap(lhs.info_, rhs.info_); + } + + friend class ThreadSafeArenaStatsHandlePeer; + + private: + ThreadSafeArenaStats* info_ = nullptr; +}; + +using ThreadSafeArenazSampler = + ::absl::profiling_internal::SampleRecorder<ThreadSafeArenaStats>; + +extern PROTOBUF_THREAD_LOCAL int64_t global_next_sample; + +// Returns an RAII sampling handle that manages registration and unregistation +// with the global sampler. +inline ThreadSafeArenaStatsHandle Sample() { + if (PROTOBUF_PREDICT_TRUE(--global_next_sample > 0)) { + return ThreadSafeArenaStatsHandle(nullptr); + } + return ThreadSafeArenaStatsHandle(SampleSlow(&global_next_sample)); +} + +#else +struct ThreadSafeArenaStats { + static void RecordAllocateStats(ThreadSafeArenaStats*, size_t /*requested*/, + size_t /*allocated*/, size_t /*wasted*/) {} +}; + +ThreadSafeArenaStats* SampleSlow(int64_t* next_sample); +void UnsampleSlow(ThreadSafeArenaStats* info); + +class ThreadSafeArenaStatsHandle { + public: + explicit ThreadSafeArenaStatsHandle() = default; + explicit ThreadSafeArenaStatsHandle(ThreadSafeArenaStats*) {} + + void RecordReset() {} + + ThreadSafeArenaStats* MutableStats() { return nullptr; } + + friend void swap(ThreadSafeArenaStatsHandle&, ThreadSafeArenaStatsHandle&) {} + + private: + friend class ThreadSafeArenaStatsHandlePeer; +}; + +class ThreadSafeArenazSampler { + public: + void Unregister(ThreadSafeArenaStats*) {} + void SetMaxSamples(int32_t) {} +}; + +// Returns an RAII sampling handle that manages registration and unregistation +// with the global sampler. +inline ThreadSafeArenaStatsHandle Sample() { + return ThreadSafeArenaStatsHandle(nullptr); +} +#endif // defined(PROTOBUF_ARENAZ_SAMPLE) + +// Returns a global Sampler. +ThreadSafeArenazSampler& GlobalThreadSafeArenazSampler(); + +// Enables or disables sampling for thread safe arenas. +void SetThreadSafeArenazEnabled(bool enabled); + +// Sets the rate at which thread safe arena will be sampled. +void SetThreadSafeArenazSampleParameter(int32_t rate); + +// Sets a soft max for the number of samples that will be kept. +void SetThreadSafeArenazMaxSamples(int32_t max); + +// Sets the current value for when arenas should be next sampled. +void SetThreadSafeArenazGlobalNextSample(int64_t next_sample); + +} // namespace internal +} // namespace protobuf +} // namespace google + +#include <google/protobuf/port_undef.inc> +#endif // GOOGLE_PROTOBUF_SRC_PROTOBUF_ARENAZ_SAMPLER_H__ diff --git a/toolkit/components/protobuf/src/google/protobuf/descriptor.cc b/toolkit/components/protobuf/src/google/protobuf/descriptor.cc new file mode 100644 index 0000000000..5f3427dc72 --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/descriptor.cc @@ -0,0 +1,8340 @@ +// 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. + +// Author: kenton@google.com (Kenton Varda) +// Based on original Protocol Buffers design by +// Sanjay Ghemawat, Jeff Dean, and others. + +#include <google/protobuf/descriptor.h> + +#include <algorithm> +#include <array> +#include <functional> +#include <limits> +#include <map> +#include <memory> +#include <set> +#include <sstream> +#include <string> +#include <type_traits> +#include <unordered_map> +#include <unordered_set> +#include <vector> + +#include <google/protobuf/stubs/common.h> +#include <google/protobuf/stubs/logging.h> +#include <google/protobuf/stubs/strutil.h> +#include <google/protobuf/stubs/once.h> +#include <google/protobuf/any.h> +#include <google/protobuf/descriptor.pb.h> +#include <google/protobuf/io/coded_stream.h> +#include <google/protobuf/io/tokenizer.h> +#include <google/protobuf/io/zero_copy_stream_impl.h> +#include <google/protobuf/stubs/casts.h> +#include <google/protobuf/stubs/stringprintf.h> +#include <google/protobuf/stubs/substitute.h> +#include <google/protobuf/descriptor_database.h> +#include <google/protobuf/dynamic_message.h> +#include <google/protobuf/generated_message_util.h> +#include <google/protobuf/io/strtod.h> +#include <google/protobuf/port.h> +#include <google/protobuf/text_format.h> +#include <google/protobuf/unknown_field_set.h> +#include <google/protobuf/stubs/map_util.h> +#include <google/protobuf/stubs/stl_util.h> +#include <google/protobuf/stubs/hash.h> + +#undef PACKAGE // autoheader #defines this. :( + + +// Must be included last. +#include <google/protobuf/port_def.inc> + +namespace google { +namespace protobuf { + +namespace { +const int kPackageLimit = 100; + +// Note: I distrust ctype.h due to locales. +char ToUpper(char ch) { + return (ch >= 'a' && ch <= 'z') ? (ch - 'a' + 'A') : ch; +} + +char ToLower(char ch) { + return (ch >= 'A' && ch <= 'Z') ? (ch - 'A' + 'a') : ch; +} + +std::string ToCamelCase(const std::string& input, bool lower_first) { + bool capitalize_next = !lower_first; + std::string result; + result.reserve(input.size()); + + for (char character : input) { + if (character == '_') { + capitalize_next = true; + } else if (capitalize_next) { + result.push_back(ToUpper(character)); + capitalize_next = false; + } else { + result.push_back(character); + } + } + + // Lower-case the first letter. + if (lower_first && !result.empty()) { + result[0] = ToLower(result[0]); + } + + return result; +} + +std::string ToJsonName(const std::string& input) { + bool capitalize_next = false; + std::string result; + result.reserve(input.size()); + + for (char character : input) { + if (character == '_') { + capitalize_next = true; + } else if (capitalize_next) { + result.push_back(ToUpper(character)); + capitalize_next = false; + } else { + result.push_back(character); + } + } + + return result; +} + +// Backport of fold expressions for the comma operator to C++11. +// Usage: Fold({expr...}); +// Guaranteed to evaluate left-to-right +struct ExpressionEater { + template <typename T> + ExpressionEater(T&&) {} // NOLINT +}; +void Fold(std::initializer_list<ExpressionEater>) {} + +template <int R> +constexpr size_t RoundUpTo(size_t n) { + static_assert((R & (R - 1)) == 0, "Must be power of two"); + return (n + (R - 1)) & ~(R - 1); +} + +constexpr size_t Max(size_t a, size_t b) { return a > b ? a : b; } +template <typename T, typename... Ts> +constexpr size_t Max(T a, Ts... b) { + return Max(a, Max(b...)); +} + +template <typename T> +constexpr size_t EffectiveAlignof() { + // `char` is special in that it gets aligned to 8. It is where we drop the + // trivial structs. + return std::is_same<T, char>::value ? 8 : alignof(T); +} + +template <int align, typename U, typename... T> +using AppendIfAlign = + typename std::conditional<EffectiveAlignof<U>() == align, void (*)(T..., U), + void (*)(T...)>::type; + +// Metafunction to sort types in descending order of alignment. +// Useful for the flat allocator to ensure proper alignment of all elements +// without having to add padding. +// Instead of implementing a proper sort metafunction we just do a +// filter+merge, which is much simpler to write as a metafunction. +// We have a fixed set of alignments we can filter on. +// For simplicity we use a function pointer as a type list. +template <typename In, typename T16, typename T8, typename T4, typename T2, + typename T1> +struct TypeListSortImpl; + +template <typename... T16, typename... T8, typename... T4, typename... T2, + typename... T1> +struct TypeListSortImpl<void (*)(), void (*)(T16...), void (*)(T8...), + void (*)(T4...), void (*)(T2...), void (*)(T1...)> { + using type = void (*)(T16..., T8..., T4..., T2..., T1...); +}; + +template <typename First, typename... Rest, typename... T16, typename... T8, + typename... T4, typename... T2, typename... T1> +struct TypeListSortImpl<void (*)(First, Rest...), void (*)(T16...), + void (*)(T8...), void (*)(T4...), void (*)(T2...), + void (*)(T1...)> { + using type = typename TypeListSortImpl< + void (*)(Rest...), AppendIfAlign<16, First, T16...>, + AppendIfAlign<8, First, T8...>, AppendIfAlign<4, First, T4...>, + AppendIfAlign<2, First, T2...>, AppendIfAlign<1, First, T1...>>::type; +}; + +template <typename... T> +using SortByAlignment = + typename TypeListSortImpl<void (*)(T...), void (*)(), void (*)(), + void (*)(), void (*)(), void (*)()>::type; + +template <template <typename...> class C, typename... T> +auto ApplyTypeList(void (*)(T...)) -> C<T...>; + +template <typename T> +constexpr int FindTypeIndex() { + return -1; +} + +template <typename T, typename T1, typename... Ts> +constexpr int FindTypeIndex() { + return std::is_same<T, T1>::value ? 0 : FindTypeIndex<T, Ts...>() + 1; +} + +// A type to value map, where the possible keys as specified in `Keys...`. +// The values for key `K` is `ValueT<K>` +template <template <typename> class ValueT, typename... Keys> +class TypeMap { + public: + template <typename K> + ValueT<K>& Get() { + return static_cast<Base<K>&>(payload_).value; + } + + template <typename K> + const ValueT<K>& Get() const { + return static_cast<const Base<K>&>(payload_).value; + } + + private: + template <typename K> + struct Base { + ValueT<K> value{}; + }; + struct Payload : Base<Keys>... {}; + Payload payload_; +}; + +template <typename T> +using IntT = int; +template <typename T> +using PointerT = T*; + +// Manages an allocation of sequential arrays of type `T...`. +// It is more space efficient than storing N (ptr, size) pairs, by storing only +// the pointer to the head and the boundaries between the arrays. +template <typename... T> +class FlatAllocation { + public: + static constexpr size_t kMaxAlign = Max(alignof(T)...); + + FlatAllocation(const TypeMap<IntT, T...>& ends) : ends_(ends) { + // The arrays start just after FlatAllocation, so adjust the ends. + Fold({(ends_.template Get<T>() += + RoundUpTo<kMaxAlign>(sizeof(FlatAllocation)))...}); + Fold({Init<T>()...}); + } + + void Destroy() { + Fold({Destroy<T>()...}); + internal::SizedDelete(this, total_bytes()); + } + + template <int I> + using type = typename std::tuple_element<I, std::tuple<T...>>::type; + + // Gets a tuple of the head pointers for the arrays + TypeMap<PointerT, T...> Pointers() const { + TypeMap<PointerT, T...> out; + Fold({(out.template Get<T>() = Begin<T>())...}); + return out; + } + + + private: + // Total number of bytes used by all arrays. + int total_bytes() const { + // Get the last end. + return ends_.template Get<typename std::tuple_element< + sizeof...(T) - 1, std::tuple<T...>>::type>(); + } + + + template <typename U> + int BeginOffset() const { + constexpr int type_index = FindTypeIndex<U, T...>(); + // Avoid a negative value here to keep it compiling when type_index == 0 + constexpr int prev_type_index = type_index == 0 ? 0 : type_index - 1; + using PrevType = + typename std::tuple_element<prev_type_index, std::tuple<T...>>::type; + // Ensure the types are properly aligned. + static_assert(EffectiveAlignof<PrevType>() >= EffectiveAlignof<U>(), ""); + return type_index == 0 ? RoundUpTo<kMaxAlign>(sizeof(FlatAllocation)) + : ends_.template Get<PrevType>(); + } + + template <typename U> + int EndOffset() const { + return ends_.template Get<U>(); + } + + // Avoid the reinterpret_cast if the array is empty. + // Clang's Control Flow Integrity does not like the cast pointing to memory + // that is not yet initialized to be of that type. + // (from -fsanitize=cfi-unrelated-cast) + template <typename U> + U* Begin() const { + int begin = BeginOffset<U>(), end = EndOffset<U>(); + if (begin == end) return nullptr; + return reinterpret_cast<U*>(data() + begin); + } + + template <typename U> + U* End() const { + int begin = BeginOffset<U>(), end = EndOffset<U>(); + if (begin == end) return nullptr; + return reinterpret_cast<U*>(data() + end); + } + + template <typename U> + bool Init() { + // Skip for the `char` block. No need to zero initialize it. + if (std::is_same<U, char>::value) return true; + for (char *p = data() + BeginOffset<U>(), *end = data() + EndOffset<U>(); + p != end; p += sizeof(U)) { + ::new (p) U{}; + } + return true; + } + + template <typename U> + bool Destroy() { + if (std::is_trivially_destructible<U>::value) return true; + for (U* it = Begin<U>(), *end = End<U>(); it != end; ++it) { + it->~U(); + } + return true; + } + + char* data() const { + return const_cast<char*>(reinterpret_cast<const char*>(this)); + } + + TypeMap<IntT, T...> ends_; +}; + +template <typename... T> +TypeMap<IntT, T...> CalculateEnds(const TypeMap<IntT, T...>& sizes) { + int total = 0; + TypeMap<IntT, T...> out; + Fold({(out.template Get<T>() = total += + sizeof(T) * sizes.template Get<T>())...}); + return out; +} + +// The implementation for FlatAllocator below. +// This separate class template makes it easier to have methods that fold on +// `T...`. +template <typename... T> +class FlatAllocatorImpl { + public: + using Allocation = FlatAllocation<T...>; + + template <typename U> + void PlanArray(int array_size) { + // We can't call PlanArray after FinalizePlanning has been called. + GOOGLE_CHECK(!has_allocated()); + if (std::is_trivially_destructible<U>::value) { + // Trivial types are aligned to 8 bytes. + static_assert(alignof(U) <= 8, ""); + total_.template Get<char>() += RoundUpTo<8>(array_size * sizeof(U)); + } else { + // Since we can't use `if constexpr`, just make the expression compile + // when this path is not taken. + using TypeToUse = + typename std::conditional<std::is_trivially_destructible<U>::value, + char, U>::type; + total_.template Get<TypeToUse>() += array_size; + } + } + + template <typename U> + U* AllocateArray(int array_size) { + constexpr bool trivial = std::is_trivially_destructible<U>::value; + using TypeToUse = typename std::conditional<trivial, char, U>::type; + + // We can only allocate after FinalizePlanning has been called. + GOOGLE_CHECK(has_allocated()); + + TypeToUse*& data = pointers_.template Get<TypeToUse>(); + int& used = used_.template Get<TypeToUse>(); + U* res = reinterpret_cast<U*>(data + used); + used += trivial ? RoundUpTo<8>(array_size * sizeof(U)) : array_size; + GOOGLE_CHECK_LE(used, total_.template Get<TypeToUse>()); + return res; + } + + template <typename... In> + const std::string* AllocateStrings(In&&... in) { + std::string* strings = AllocateArray<std::string>(sizeof...(in)); + std::string* res = strings; + Fold({(*strings++ = std::string(std::forward<In>(in)))...}); + return res; + } + + // Allocate all 5 names of the field: + // name, full name, lowercase, camelcase and json. + // It will dedup the strings when possible. + // The resulting array contains `name` at index 0, `full_name` at index 1 + // and the other 3 indices are specified in the result. + void PlanFieldNames(const std::string& name, + const std::string* opt_json_name) { + GOOGLE_CHECK(!has_allocated()); + + // Fast path for snake_case names, which follow the style guide. + if (opt_json_name == nullptr) { + switch (GetFieldNameCase(name)) { + case FieldNameCase::kAllLower: + // Case 1: they are all the same. + return PlanArray<std::string>(2); + case FieldNameCase::kSnakeCase: + // Case 2: name==lower, camel==json + return PlanArray<std::string>(3); + default: + break; + } + } + + std::string lowercase_name = name; + LowerString(&lowercase_name); + + std::string camelcase_name = ToCamelCase(name, /* lower_first = */ true); + std::string json_name = + opt_json_name != nullptr ? *opt_json_name : ToJsonName(name); + + StringPiece all_names[] = {name, lowercase_name, camelcase_name, + json_name}; + std::sort(all_names, all_names + 4); + int unique = + static_cast<int>(std::unique(all_names, all_names + 4) - all_names); + + PlanArray<std::string>(unique + 1); + } + + struct FieldNamesResult { + const std::string* array; + int lowercase_index; + int camelcase_index; + int json_index; + }; + FieldNamesResult AllocateFieldNames(const std::string& name, + const std::string& scope, + const std::string* opt_json_name) { + GOOGLE_CHECK(has_allocated()); + + std::string full_name = + scope.empty() ? name : StrCat(scope, ".", name); + + // Fast path for snake_case names, which follow the style guide. + if (opt_json_name == nullptr) { + switch (GetFieldNameCase(name)) { + case FieldNameCase::kAllLower: + // Case 1: they are all the same. + return {AllocateStrings(name, std::move(full_name)), 0, 0, 0}; + case FieldNameCase::kSnakeCase: + // Case 2: name==lower, camel==json + return {AllocateStrings(name, std::move(full_name), + ToCamelCase(name, /* lower_first = */ true)), + 0, 2, 2}; + default: + break; + } + } + + std::vector<std::string> names; + names.push_back(name); + names.push_back(std::move(full_name)); + + const auto push_name = [&](std::string new_name) { + for (size_t i = 0; i < names.size(); ++i) { + // Do not compare the full_name. It is unlikely to match, except in + // custom json_name. We are not taking this into account in + // PlanFieldNames so better to not try it. + if (i == 1) continue; + if (names[i] == new_name) return i; + } + names.push_back(std::move(new_name)); + return names.size() - 1; + }; + + FieldNamesResult result{nullptr, 0, 0, 0}; + + std::string lowercase_name = name; + LowerString(&lowercase_name); + result.lowercase_index = push_name(std::move(lowercase_name)); + result.camelcase_index = + push_name(ToCamelCase(name, /* lower_first = */ true)); + result.json_index = + push_name(opt_json_name != nullptr ? *opt_json_name : ToJsonName(name)); + + std::string* all_names = AllocateArray<std::string>(names.size()); + result.array = all_names; + std::move(names.begin(), names.end(), all_names); + + return result; + } + + template <typename Alloc> + void FinalizePlanning(Alloc& alloc) { + GOOGLE_CHECK(!has_allocated()); + + pointers_ = alloc->CreateFlatAlloc(total_)->Pointers(); + + GOOGLE_CHECK(has_allocated()); + } + + void ExpectConsumed() const { + // We verify that we consumed all the memory requested if there was no + // error in processing. + Fold({ExpectConsumed<T>()...}); + } + + private: + bool has_allocated() const { + return pointers_.template Get<char>() != nullptr; + } + + static bool IsLower(char c) { return 'a' <= c && c <= 'z'; } + static bool IsDigit(char c) { return '0' <= c && c <= '9'; } + static bool IsLowerOrDigit(char c) { return IsLower(c) || IsDigit(c); } + + enum class FieldNameCase { kAllLower, kSnakeCase, kOther }; + FieldNameCase GetFieldNameCase(const std::string& name) { + if (!IsLower(name[0])) return FieldNameCase::kOther; + FieldNameCase best = FieldNameCase::kAllLower; + for (char c : name) { + if (IsLowerOrDigit(c)) { + // nothing to do + } else if (c == '_') { + best = FieldNameCase::kSnakeCase; + } else { + return FieldNameCase::kOther; + } + } + return best; + } + + template <typename U> + bool ExpectConsumed() const { + GOOGLE_CHECK_EQ(total_.template Get<U>(), used_.template Get<U>()); + return true; + } + + TypeMap<PointerT, T...> pointers_; + TypeMap<IntT, T...> total_; + TypeMap<IntT, T...> used_; +}; + +} // namespace + +class Symbol { + public: + enum Type { + NULL_SYMBOL, + MESSAGE, + FIELD, + ONEOF, + ENUM, + ENUM_VALUE, + ENUM_VALUE_OTHER_PARENT, + SERVICE, + METHOD, + FULL_PACKAGE, + SUB_PACKAGE, + QUERY_KEY + }; + + Symbol() { + static constexpr internal::SymbolBase null_symbol{}; + static_assert(null_symbol.symbol_type_ == NULL_SYMBOL, ""); + // Initialize with a sentinel to make sure `ptr_` is never null. + ptr_ = &null_symbol; + } + + // Every object we store derives from internal::SymbolBase, where we store the + // symbol type enum. + // Storing in the object can be done without using more space in most cases, + // while storing it in the Symbol type would require 8 bytes. +#define DEFINE_MEMBERS(TYPE, TYPE_CONSTANT, FIELD) \ + explicit Symbol(TYPE* value) : ptr_(value) { \ + value->symbol_type_ = TYPE_CONSTANT; \ + } \ + const TYPE* FIELD() const { \ + return type() == TYPE_CONSTANT ? static_cast<const TYPE*>(ptr_) : nullptr; \ + } + + DEFINE_MEMBERS(Descriptor, MESSAGE, descriptor) + DEFINE_MEMBERS(FieldDescriptor, FIELD, field_descriptor) + DEFINE_MEMBERS(OneofDescriptor, ONEOF, oneof_descriptor) + DEFINE_MEMBERS(EnumDescriptor, ENUM, enum_descriptor) + DEFINE_MEMBERS(ServiceDescriptor, SERVICE, service_descriptor) + DEFINE_MEMBERS(MethodDescriptor, METHOD, method_descriptor) + DEFINE_MEMBERS(FileDescriptor, FULL_PACKAGE, file_descriptor) + + // We use a special node for subpackage FileDescriptor. + // It is potentially added to the table with multiple different names, so we + // need a separate place to put the name. + struct Subpackage : internal::SymbolBase { + int name_size; + const FileDescriptor* file; + }; + DEFINE_MEMBERS(Subpackage, SUB_PACKAGE, sub_package_file_descriptor) + + // Enum values have two different parents. + // We use two different identitied for the same object to determine the two + // different insertions in the map. + static Symbol EnumValue(EnumValueDescriptor* value, int n) { + Symbol s; + internal::SymbolBase* ptr; + if (n == 0) { + ptr = static_cast<internal::SymbolBaseN<0>*>(value); + ptr->symbol_type_ = ENUM_VALUE; + } else { + ptr = static_cast<internal::SymbolBaseN<1>*>(value); + ptr->symbol_type_ = ENUM_VALUE_OTHER_PARENT; + } + s.ptr_ = ptr; + return s; + } + + const EnumValueDescriptor* enum_value_descriptor() const { + return type() == ENUM_VALUE + ? static_cast<const EnumValueDescriptor*>( + static_cast<const internal::SymbolBaseN<0>*>(ptr_)) + : type() == ENUM_VALUE_OTHER_PARENT + ? static_cast<const EnumValueDescriptor*>( + static_cast<const internal::SymbolBaseN<1>*>(ptr_)) + : nullptr; + } + + // Not a real symbol. + // Only used for heterogeneous lookups and never actually inserted in the + // tables. + // TODO(b/215557658): If we templetize QueryKey on the expected object type we + // can skip the switches for the eq function altogether. + struct QueryKey : internal::SymbolBase { + StringPiece name; + const void* parent; + int field_number; + + // Adaptor functions to look like a Symbol to the comparators. + StringPiece full_name() const { return name; } + std::pair<const void*, int> parent_number_key() const { + return {parent, field_number}; + } + std::pair<const void*, StringPiece> parent_name_key() const { + return {parent, name}; + } + }; + // This constructor is implicit to allow for non-transparent lookups when + // necessary. + // For transparent lookup cases we query directly with the object without the + // type erasure layer. + Symbol(QueryKey& value) : ptr_(&value) { // NOLINT + value.symbol_type_ = QUERY_KEY; + } + const QueryKey* query_key() const { + return type() == QUERY_KEY ? static_cast<const QueryKey*>(ptr_) : nullptr; + } +#undef DEFINE_MEMBERS + + Type type() const { return static_cast<Type>(ptr_->symbol_type_); } + bool IsNull() const { return type() == NULL_SYMBOL; } + bool IsType() const { return type() == MESSAGE || type() == ENUM; } + bool IsAggregate() const { + return IsType() || IsPackage() || type() == SERVICE; + } + bool IsPackage() const { + return type() == FULL_PACKAGE || type() == SUB_PACKAGE; + } + + const FileDescriptor* GetFile() const { + switch (type()) { + case MESSAGE: + return descriptor()->file(); + case FIELD: + return field_descriptor()->file(); + case ONEOF: + return oneof_descriptor()->containing_type()->file(); + case ENUM: + return enum_descriptor()->file(); + case ENUM_VALUE: + return enum_value_descriptor()->type()->file(); + case SERVICE: + return service_descriptor()->file(); + case METHOD: + return method_descriptor()->service()->file(); + case FULL_PACKAGE: + return file_descriptor(); + case SUB_PACKAGE: + return sub_package_file_descriptor()->file; + default: + return nullptr; + } + } + + StringPiece full_name() const { + switch (type()) { + case MESSAGE: + return descriptor()->full_name(); + case FIELD: + return field_descriptor()->full_name(); + case ONEOF: + return oneof_descriptor()->full_name(); + case ENUM: + return enum_descriptor()->full_name(); + case ENUM_VALUE: + return enum_value_descriptor()->full_name(); + case SERVICE: + return service_descriptor()->full_name(); + case METHOD: + return method_descriptor()->full_name(); + case FULL_PACKAGE: + return file_descriptor()->package(); + case SUB_PACKAGE: + return StringPiece(sub_package_file_descriptor()->file->package()) + .substr(0, sub_package_file_descriptor()->name_size); + case QUERY_KEY: + return query_key()->full_name(); + default: + GOOGLE_CHECK(false); + } + return ""; + } + + std::pair<const void*, StringPiece> parent_name_key() const { + const auto or_file = [&](const void* p) { return p ? p : GetFile(); }; + switch (type()) { + case MESSAGE: + return {or_file(descriptor()->containing_type()), descriptor()->name()}; + case FIELD: { + auto* field = field_descriptor(); + return {or_file(field->is_extension() ? field->extension_scope() + : field->containing_type()), + field->name()}; + } + case ONEOF: + return {oneof_descriptor()->containing_type(), + oneof_descriptor()->name()}; + case ENUM: + return {or_file(enum_descriptor()->containing_type()), + enum_descriptor()->name()}; + case ENUM_VALUE: + return {or_file(enum_value_descriptor()->type()->containing_type()), + enum_value_descriptor()->name()}; + case ENUM_VALUE_OTHER_PARENT: + return {enum_value_descriptor()->type(), + enum_value_descriptor()->name()}; + case SERVICE: + return {GetFile(), service_descriptor()->name()}; + case METHOD: + return {method_descriptor()->service(), method_descriptor()->name()}; + case QUERY_KEY: + return query_key()->parent_name_key(); + default: + GOOGLE_CHECK(false); + } + return {}; + } + + std::pair<const void*, int> parent_number_key() const { + switch (type()) { + case FIELD: + return {field_descriptor()->containing_type(), + field_descriptor()->number()}; + case ENUM_VALUE: + return {enum_value_descriptor()->type(), + enum_value_descriptor()->number()}; + case QUERY_KEY: + return query_key()->parent_number_key(); + default: + GOOGLE_CHECK(false); + } + return {}; + } + + private: + const internal::SymbolBase* ptr_; +}; + +const FieldDescriptor::CppType + FieldDescriptor::kTypeToCppTypeMap[MAX_TYPE + 1] = { + static_cast<CppType>(0), // 0 is reserved for errors + + CPPTYPE_DOUBLE, // TYPE_DOUBLE + CPPTYPE_FLOAT, // TYPE_FLOAT + CPPTYPE_INT64, // TYPE_INT64 + CPPTYPE_UINT64, // TYPE_UINT64 + CPPTYPE_INT32, // TYPE_INT32 + CPPTYPE_UINT64, // TYPE_FIXED64 + CPPTYPE_UINT32, // TYPE_FIXED32 + CPPTYPE_BOOL, // TYPE_BOOL + CPPTYPE_STRING, // TYPE_STRING + CPPTYPE_MESSAGE, // TYPE_GROUP + CPPTYPE_MESSAGE, // TYPE_MESSAGE + CPPTYPE_STRING, // TYPE_BYTES + CPPTYPE_UINT32, // TYPE_UINT32 + CPPTYPE_ENUM, // TYPE_ENUM + CPPTYPE_INT32, // TYPE_SFIXED32 + CPPTYPE_INT64, // TYPE_SFIXED64 + CPPTYPE_INT32, // TYPE_SINT32 + CPPTYPE_INT64, // TYPE_SINT64 +}; + +const char* const FieldDescriptor::kTypeToName[MAX_TYPE + 1] = { + "ERROR", // 0 is reserved for errors + + "double", // TYPE_DOUBLE + "float", // TYPE_FLOAT + "int64", // TYPE_INT64 + "uint64", // TYPE_UINT64 + "int32", // TYPE_INT32 + "fixed64", // TYPE_FIXED64 + "fixed32", // TYPE_FIXED32 + "bool", // TYPE_BOOL + "string", // TYPE_STRING + "group", // TYPE_GROUP + "message", // TYPE_MESSAGE + "bytes", // TYPE_BYTES + "uint32", // TYPE_UINT32 + "enum", // TYPE_ENUM + "sfixed32", // TYPE_SFIXED32 + "sfixed64", // TYPE_SFIXED64 + "sint32", // TYPE_SINT32 + "sint64", // TYPE_SINT64 +}; + +const char* const FieldDescriptor::kCppTypeToName[MAX_CPPTYPE + 1] = { + "ERROR", // 0 is reserved for errors + + "int32", // CPPTYPE_INT32 + "int64", // CPPTYPE_INT64 + "uint32", // CPPTYPE_UINT32 + "uint64", // CPPTYPE_UINT64 + "double", // CPPTYPE_DOUBLE + "float", // CPPTYPE_FLOAT + "bool", // CPPTYPE_BOOL + "enum", // CPPTYPE_ENUM + "string", // CPPTYPE_STRING + "message", // CPPTYPE_MESSAGE +}; + +const char* const FieldDescriptor::kLabelToName[MAX_LABEL + 1] = { + "ERROR", // 0 is reserved for errors + + "optional", // LABEL_OPTIONAL + "required", // LABEL_REQUIRED + "repeated", // LABEL_REPEATED +}; + +const char* FileDescriptor::SyntaxName(FileDescriptor::Syntax syntax) { + switch (syntax) { + case SYNTAX_PROTO2: + return "proto2"; + case SYNTAX_PROTO3: + return "proto3"; + case SYNTAX_UNKNOWN: + return "unknown"; + } + GOOGLE_LOG(FATAL) << "can't reach here."; + return nullptr; +} + +static const char* const kNonLinkedWeakMessageReplacementName = "google.protobuf.Empty"; + +#if !defined(_MSC_VER) || (_MSC_VER >= 1900 && _MSC_VER < 1912) +const int FieldDescriptor::kMaxNumber; +const int FieldDescriptor::kFirstReservedNumber; +const int FieldDescriptor::kLastReservedNumber; +#endif + +namespace { + +std::string EnumValueToPascalCase(const std::string& input) { + bool next_upper = true; + std::string result; + result.reserve(input.size()); + + for (char character : input) { + if (character == '_') { + next_upper = true; + } else { + if (next_upper) { + result.push_back(ToUpper(character)); + } else { + result.push_back(ToLower(character)); + } + next_upper = false; + } + } + + return result; +} + +// Class to remove an enum prefix from enum values. +class PrefixRemover { + public: + PrefixRemover(StringPiece prefix) { + // Strip underscores and lower-case the prefix. + for (char character : prefix) { + if (character != '_') { + prefix_ += ascii_tolower(character); + } + } + } + + // Tries to remove the enum prefix from this enum value. + // If this is not possible, returns the input verbatim. + std::string MaybeRemove(StringPiece str) { + // We can't just lowercase and strip str and look for a prefix. + // We need to properly recognize the difference between: + // + // enum Foo { + // FOO_BAR_BAZ = 0; + // FOO_BARBAZ = 1; + // } + // + // This is acceptable (though perhaps not advisable) because even when + // we PascalCase, these two will still be distinct (BarBaz vs. Barbaz). + size_t i, j; + + // Skip past prefix_ in str if we can. + for (i = 0, j = 0; i < str.size() && j < prefix_.size(); i++) { + if (str[i] == '_') { + continue; + } + + if (ascii_tolower(str[i]) != prefix_[j++]) { + return std::string(str); + } + } + + // If we didn't make it through the prefix, we've failed to strip the + // prefix. + if (j < prefix_.size()) { + return std::string(str); + } + + // Skip underscores between prefix and further characters. + while (i < str.size() && str[i] == '_') { + i++; + } + + // Enum label can't be the empty string. + if (i == str.size()) { + return std::string(str); + } + + // We successfully stripped the prefix. + str.remove_prefix(i); + return std::string(str); + } + + private: + std::string prefix_; +}; + +// A DescriptorPool contains a bunch of hash-maps to implement the +// various Find*By*() methods. Since hashtable lookups are O(1), it's +// most efficient to construct a fixed set of large hash-maps used by +// all objects in the pool rather than construct one or more small +// hash-maps for each object. +// +// The keys to these hash-maps are (parent, name) or (parent, number) pairs. + +typedef std::pair<const void*, StringPiece> PointerStringPair; + +typedef std::pair<const Descriptor*, int> DescriptorIntPair; + +#define HASH_MAP std::unordered_map +#define HASH_SET std::unordered_set +#define HASH_FXN hash + +template <typename PairType> +struct PointerIntegerPairHash { + size_t operator()(const PairType& p) const { + static const size_t prime1 = 16777499; + static const size_t prime2 = 16777619; + return reinterpret_cast<size_t>(p.first) * prime1 ^ + static_cast<size_t>(p.second) * prime2; + } + +#ifdef _MSC_VER + // Used only by MSVC and platforms where hash_map is not available. + static const size_t bucket_size = 4; + static const size_t min_buckets = 8; +#endif + inline bool operator()(const PairType& a, const PairType& b) const { + return a < b; + } +}; + +struct PointerStringPairHash { + size_t operator()(const PointerStringPair& p) const { + static const size_t prime = 16777619; + hash<StringPiece> string_hash; + return reinterpret_cast<size_t>(p.first) * prime ^ + static_cast<size_t>(string_hash(p.second)); + } + +#ifdef _MSC_VER + // Used only by MSVC and platforms where hash_map is not available. + static const size_t bucket_size = 4; + static const size_t min_buckets = 8; +#endif + inline bool operator()(const PointerStringPair& a, + const PointerStringPair& b) const { + return a < b; + } +}; + + +struct SymbolByFullNameHash { + using is_transparent = void; + + template <typename T> + size_t operator()(const T& s) const { + return HASH_FXN<StringPiece>{}(s.full_name()); + } +}; +struct SymbolByFullNameEq { + using is_transparent = void; + + template <typename T, typename U> + bool operator()(const T& a, const U& b) const { + return a.full_name() == b.full_name(); + } +}; +using SymbolsByNameSet = + HASH_SET<Symbol, SymbolByFullNameHash, SymbolByFullNameEq>; + +struct SymbolByParentHash { + using is_transparent = void; + + template <typename T> + size_t operator()(const T& s) const { + return PointerStringPairHash{}(s.parent_name_key()); + } +}; +struct SymbolByParentEq { + using is_transparent = void; + + template <typename T, typename U> + bool operator()(const T& a, const U& b) const { + return a.parent_name_key() == b.parent_name_key(); + } +}; +using SymbolsByParentSet = + HASH_SET<Symbol, SymbolByParentHash, SymbolByParentEq>; + +typedef HASH_MAP<StringPiece, const FileDescriptor*, + HASH_FXN<StringPiece>> + FilesByNameMap; + +typedef HASH_MAP<PointerStringPair, const FieldDescriptor*, + PointerStringPairHash> + FieldsByNameMap; + +struct FieldsByNumberHash { + using is_transparent = void; + + template <typename T> + size_t operator()(const T& s) const { + return PointerIntegerPairHash<std::pair<const void*, int>>{}( + s.parent_number_key()); + } +}; +struct FieldsByNumberEq { + using is_transparent = void; + + template <typename T, typename U> + bool operator()(const T& a, const U& b) const { + return a.parent_number_key() == b.parent_number_key(); + } +}; +using FieldsByNumberSet = + HASH_SET<Symbol, FieldsByNumberHash, FieldsByNumberEq>; +using EnumValuesByNumberSet = FieldsByNumberSet; + +// This is a map rather than a hash-map, since we use it to iterate +// through all the extensions that extend a given Descriptor, and an +// ordered data structure that implements lower_bound is convenient +// for that. +typedef std::map<DescriptorIntPair, const FieldDescriptor*> + ExtensionsGroupedByDescriptorMap; +typedef HASH_MAP<std::string, const SourceCodeInfo_Location*> + LocationsByPathMap; + +std::set<std::string>* NewAllowedProto3Extendee() { + auto allowed_proto3_extendees = new std::set<std::string>; + const char* kOptionNames[] = { + "FileOptions", "MessageOptions", "FieldOptions", + "EnumOptions", "EnumValueOptions", "ServiceOptions", + "MethodOptions", "OneofOptions", "ExtensionRangeOptions"}; + for (const char* option_name : kOptionNames) { + // descriptor.proto has a different package name in opensource. We allow + // both so the opensource protocol compiler can also compile internal + // proto3 files with custom options. See: b/27567912 + allowed_proto3_extendees->insert(std::string("google.protobuf.") + + option_name); + // Split the word to trick the opensource processing scripts so they + // will keep the original package name. + allowed_proto3_extendees->insert(std::string("proto") + "2." + option_name); + } + return allowed_proto3_extendees; +} + +// Checks whether the extendee type is allowed in proto3. +// Only extensions to descriptor options are allowed. We use name comparison +// instead of comparing the descriptor directly because the extensions may be +// defined in a different pool. +bool AllowedExtendeeInProto3(const std::string& name) { + static auto allowed_proto3_extendees = + internal::OnShutdownDelete(NewAllowedProto3Extendee()); + return allowed_proto3_extendees->find(name) != + allowed_proto3_extendees->end(); +} +} // anonymous namespace + +// Contains tables specific to a particular file. These tables are not +// modified once the file has been constructed, so they need not be +// protected by a mutex. This makes operations that depend only on the +// contents of a single file -- e.g. Descriptor::FindFieldByName() -- +// lock-free. +// +// For historical reasons, the definitions of the methods of +// FileDescriptorTables and DescriptorPool::Tables are interleaved below. +// These used to be a single class. +class FileDescriptorTables { + public: + FileDescriptorTables(); + ~FileDescriptorTables(); + + // Empty table, used with placeholder files. + inline static const FileDescriptorTables& GetEmptyInstance(); + + // ----------------------------------------------------------------- + // Finding items. + + // Returns a null Symbol (symbol.IsNull() is true) if not found. + inline Symbol FindNestedSymbol(const void* parent, + StringPiece name) const; + + // These return nullptr if not found. + inline const FieldDescriptor* FindFieldByNumber(const Descriptor* parent, + int number) const; + inline const FieldDescriptor* FindFieldByLowercaseName( + const void* parent, StringPiece lowercase_name) const; + inline const FieldDescriptor* FindFieldByCamelcaseName( + const void* parent, StringPiece camelcase_name) const; + inline const EnumValueDescriptor* FindEnumValueByNumber( + const EnumDescriptor* parent, int number) const; + // This creates a new EnumValueDescriptor if not found, in a thread-safe way. + inline const EnumValueDescriptor* FindEnumValueByNumberCreatingIfUnknown( + const EnumDescriptor* parent, int number) const; + + // ----------------------------------------------------------------- + // Adding items. + + // These add items to the corresponding tables. They return false if + // the key already exists in the table. + bool AddAliasUnderParent(const void* parent, const std::string& name, + Symbol symbol); + bool AddFieldByNumber(FieldDescriptor* field); + bool AddEnumValueByNumber(EnumValueDescriptor* value); + + // Populates p->first->locations_by_path_ from p->second. + // Unusual signature dictated by internal::call_once. + static void BuildLocationsByPath( + std::pair<const FileDescriptorTables*, const SourceCodeInfo*>* p); + + // Returns the location denoted by the specified path through info, + // or nullptr if not found. + // The value of info must be that of the corresponding FileDescriptor. + // (Conceptually a pure function, but stateful as an optimisation.) + const SourceCodeInfo_Location* GetSourceLocation( + const std::vector<int>& path, const SourceCodeInfo* info) const; + + // Must be called after BuildFileImpl(), even if the build failed and + // we are going to roll back to the last checkpoint. + void FinalizeTables(); + + private: + const void* FindParentForFieldsByMap(const FieldDescriptor* field) const; + static void FieldsByLowercaseNamesLazyInitStatic( + const FileDescriptorTables* tables); + void FieldsByLowercaseNamesLazyInitInternal() const; + static void FieldsByCamelcaseNamesLazyInitStatic( + const FileDescriptorTables* tables); + void FieldsByCamelcaseNamesLazyInitInternal() const; + + SymbolsByParentSet symbols_by_parent_; + mutable internal::once_flag fields_by_lowercase_name_once_; + mutable internal::once_flag fields_by_camelcase_name_once_; + // Make these fields atomic to avoid race conditions with + // GetEstimatedOwnedMemoryBytesSize. Once the pointer is set the map won't + // change anymore. + mutable std::atomic<const FieldsByNameMap*> fields_by_lowercase_name_{}; + mutable std::atomic<const FieldsByNameMap*> fields_by_camelcase_name_{}; + FieldsByNumberSet fields_by_number_; // Not including extensions. + EnumValuesByNumberSet enum_values_by_number_; + mutable EnumValuesByNumberSet unknown_enum_values_by_number_ + PROTOBUF_GUARDED_BY(unknown_enum_values_mu_); + + // Populated on first request to save space, hence constness games. + mutable internal::once_flag locations_by_path_once_; + mutable LocationsByPathMap locations_by_path_; + + // Mutex to protect the unknown-enum-value map due to dynamic + // EnumValueDescriptor creation on unknown values. + mutable internal::WrappedMutex unknown_enum_values_mu_; +}; + +namespace internal { + +// Small sequential allocator to be used within a single file. +// Most of the memory for a single FileDescriptor and everything under it is +// allocated in a single block of memory, with the FlatAllocator giving it out +// in parts later. +// The code first plans the total number of bytes needed by calling PlanArray +// with all the allocations that will happen afterwards, then calls +// FinalizePlanning passing the underlying allocator (the DescriptorPool::Tables +// instance), and then proceeds to get the memory via +// `AllocateArray`/`AllocateString` calls. The calls to PlanArray and +// The calls have to match between planning and allocating, though not +// necessarily in the same order. +class FlatAllocator + : public decltype(ApplyTypeList<FlatAllocatorImpl>( + SortByAlignment<char, std::string, SourceCodeInfo, + FileDescriptorTables, + // Option types + MessageOptions, FieldOptions, EnumOptions, + EnumValueOptions, ExtensionRangeOptions, OneofOptions, + ServiceOptions, MethodOptions, FileOptions>())) {}; + +} // namespace internal + +// =================================================================== +// DescriptorPool::Tables + +class DescriptorPool::Tables { + public: + Tables(); + ~Tables(); + + // Record the current state of the tables to the stack of checkpoints. + // Each call to AddCheckpoint() must be paired with exactly one call to either + // ClearLastCheckpoint() or RollbackToLastCheckpoint(). + // + // This is used when building files, since some kinds of validation errors + // cannot be detected until the file's descriptors have already been added to + // the tables. + // + // This supports recursive checkpoints, since building a file may trigger + // recursive building of other files. Note that recursive checkpoints are not + // normally necessary; explicit dependencies are built prior to checkpointing. + // So although we recursively build transitive imports, there is at most one + // checkpoint in the stack during dependency building. + // + // Recursive checkpoints only arise during cross-linking of the descriptors. + // Symbol references must be resolved, via DescriptorBuilder::FindSymbol and + // friends. If the pending file references an unknown symbol + // (e.g., it is not defined in the pending file's explicit dependencies), and + // the pool is using a fallback database, and that database contains a file + // defining that symbol, and that file has not yet been built by the pool, + // the pool builds the file during cross-linking, leading to another + // checkpoint. + void AddCheckpoint(); + + // Mark the last checkpoint as having cleared successfully, removing it from + // the stack. If the stack is empty, all pending symbols will be committed. + // + // Note that this does not guarantee that the symbols added since the last + // checkpoint won't be rolled back: if a checkpoint gets rolled back, + // everything past that point gets rolled back, including symbols added after + // checkpoints that were pushed onto the stack after it and marked as cleared. + void ClearLastCheckpoint(); + + // Roll back the Tables to the state of the checkpoint at the top of the + // stack, removing everything that was added after that point. + void RollbackToLastCheckpoint(); + + // The stack of files which are currently being built. Used to detect + // cyclic dependencies when loading files from a DescriptorDatabase. Not + // used when fallback_database_ == nullptr. + std::vector<std::string> pending_files_; + + // A set of files which we have tried to load from the fallback database + // and encountered errors. We will not attempt to load them again during + // execution of the current public API call, but for compatibility with + // legacy clients, this is cleared at the beginning of each public API call. + // Not used when fallback_database_ == nullptr. + HASH_SET<std::string> known_bad_files_; + + // A set of symbols which we have tried to load from the fallback database + // and encountered errors. We will not attempt to load them again during + // execution of the current public API call, but for compatibility with + // legacy clients, this is cleared at the beginning of each public API call. + HASH_SET<std::string> known_bad_symbols_; + + // The set of descriptors for which we've already loaded the full + // set of extensions numbers from fallback_database_. + HASH_SET<const Descriptor*> extensions_loaded_from_db_; + + // Maps type name to Descriptor::WellKnownType. This is logically global + // and const, but we make it a member here to simplify its construction and + // destruction. This only has 20-ish entries and is one per DescriptorPool, + // so the overhead is small. + HASH_MAP<std::string, Descriptor::WellKnownType> well_known_types_; + + // ----------------------------------------------------------------- + // Finding items. + + // Find symbols. This returns a null Symbol (symbol.IsNull() is true) + // if not found. + inline Symbol FindSymbol(StringPiece key) const; + + // This implements the body of DescriptorPool::Find*ByName(). It should + // really be a private method of DescriptorPool, but that would require + // declaring Symbol in descriptor.h, which would drag all kinds of other + // stuff into the header. Yay C++. + Symbol FindByNameHelper(const DescriptorPool* pool, StringPiece name); + + // These return nullptr if not found. + inline const FileDescriptor* FindFile(StringPiece key) const; + inline const FieldDescriptor* FindExtension(const Descriptor* extendee, + int number) const; + inline void FindAllExtensions(const Descriptor* extendee, + std::vector<const FieldDescriptor*>* out) const; + + // ----------------------------------------------------------------- + // Adding items. + + // These add items to the corresponding tables. They return false if + // the key already exists in the table. For AddSymbol(), the string passed + // in must be one that was constructed using AllocateString(), as it will + // be used as a key in the symbols_by_name_ map without copying. + bool AddSymbol(const std::string& full_name, Symbol symbol); + bool AddFile(const FileDescriptor* file); + bool AddExtension(const FieldDescriptor* field); + + // ----------------------------------------------------------------- + // Allocating memory. + + // Allocate an object which will be reclaimed when the pool is + // destroyed. Note that the object's destructor will never be called, + // so its fields must be plain old data (primitive data types and + // pointers). All of the descriptor types are such objects. + template <typename Type> + Type* Allocate(); + + // Allocate some bytes which will be reclaimed when the pool is + // destroyed. Memory is aligned to 8 bytes. + void* AllocateBytes(int size); + + // Create a FlatAllocation for the corresponding sizes. + // All objects within it will be default constructed. + // The whole allocation, including the non-trivial objects within, will be + // destroyed with the pool. + template <typename... T> + internal::FlatAllocator::Allocation* CreateFlatAlloc( + const TypeMap<IntT, T...>& sizes); + + + private: + // All memory allocated in the pool. Must be first as other objects can + // point into these. + struct MiscDeleter { + void operator()(int* p) const { internal::SizedDelete(p, *p + 8); } + }; + // Miscellaneous allocations are length prefixed. The paylaod is 8 bytes after + // the `int` that contains the size. This keeps the payload aligned. + std::vector<std::unique_ptr<int, MiscDeleter>> misc_allocs_; + struct FlatAllocDeleter { + void operator()(internal::FlatAllocator::Allocation* p) const { + p->Destroy(); + } + }; + std::vector< + std::unique_ptr<internal::FlatAllocator::Allocation, FlatAllocDeleter>> + flat_allocs_; + + SymbolsByNameSet symbols_by_name_; + FilesByNameMap files_by_name_; + ExtensionsGroupedByDescriptorMap extensions_; + + struct CheckPoint { + explicit CheckPoint(const Tables* tables) + : flat_allocations_before_checkpoint( + static_cast<int>(tables->flat_allocs_.size())), + misc_allocations_before_checkpoint( + static_cast<int>(tables->misc_allocs_.size())), + pending_symbols_before_checkpoint( + tables->symbols_after_checkpoint_.size()), + pending_files_before_checkpoint( + tables->files_after_checkpoint_.size()), + pending_extensions_before_checkpoint( + tables->extensions_after_checkpoint_.size()) {} + int flat_allocations_before_checkpoint; + int misc_allocations_before_checkpoint; + int pending_symbols_before_checkpoint; + int pending_files_before_checkpoint; + int pending_extensions_before_checkpoint; + }; + std::vector<CheckPoint> checkpoints_; + std::vector<Symbol> symbols_after_checkpoint_; + std::vector<const FileDescriptor*> files_after_checkpoint_; + std::vector<DescriptorIntPair> extensions_after_checkpoint_; +}; + +DescriptorPool::Tables::Tables() { + well_known_types_.insert({ + {"google.protobuf.DoubleValue", Descriptor::WELLKNOWNTYPE_DOUBLEVALUE}, + {"google.protobuf.FloatValue", Descriptor::WELLKNOWNTYPE_FLOATVALUE}, + {"google.protobuf.Int64Value", Descriptor::WELLKNOWNTYPE_INT64VALUE}, + {"google.protobuf.UInt64Value", Descriptor::WELLKNOWNTYPE_UINT64VALUE}, + {"google.protobuf.Int32Value", Descriptor::WELLKNOWNTYPE_INT32VALUE}, + {"google.protobuf.UInt32Value", Descriptor::WELLKNOWNTYPE_UINT32VALUE}, + {"google.protobuf.StringValue", Descriptor::WELLKNOWNTYPE_STRINGVALUE}, + {"google.protobuf.BytesValue", Descriptor::WELLKNOWNTYPE_BYTESVALUE}, + {"google.protobuf.BoolValue", Descriptor::WELLKNOWNTYPE_BOOLVALUE}, + {"google.protobuf.Any", Descriptor::WELLKNOWNTYPE_ANY}, + {"google.protobuf.FieldMask", Descriptor::WELLKNOWNTYPE_FIELDMASK}, + {"google.protobuf.Duration", Descriptor::WELLKNOWNTYPE_DURATION}, + {"google.protobuf.Timestamp", Descriptor::WELLKNOWNTYPE_TIMESTAMP}, + {"google.protobuf.Value", Descriptor::WELLKNOWNTYPE_VALUE}, + {"google.protobuf.ListValue", Descriptor::WELLKNOWNTYPE_LISTVALUE}, + {"google.protobuf.Struct", Descriptor::WELLKNOWNTYPE_STRUCT}, + }); +} + +DescriptorPool::Tables::~Tables() { GOOGLE_DCHECK(checkpoints_.empty()); } + +FileDescriptorTables::FileDescriptorTables() {} + +FileDescriptorTables::~FileDescriptorTables() { + delete fields_by_lowercase_name_.load(std::memory_order_acquire); + delete fields_by_camelcase_name_.load(std::memory_order_acquire); +} + +inline const FileDescriptorTables& FileDescriptorTables::GetEmptyInstance() { + static auto file_descriptor_tables = + internal::OnShutdownDelete(new FileDescriptorTables()); + return *file_descriptor_tables; +} + +void DescriptorPool::Tables::AddCheckpoint() { + checkpoints_.push_back(CheckPoint(this)); +} + +void DescriptorPool::Tables::ClearLastCheckpoint() { + GOOGLE_DCHECK(!checkpoints_.empty()); + checkpoints_.pop_back(); + if (checkpoints_.empty()) { + // All checkpoints have been cleared: we can now commit all of the pending + // data. + symbols_after_checkpoint_.clear(); + files_after_checkpoint_.clear(); + extensions_after_checkpoint_.clear(); + } +} + +void DescriptorPool::Tables::RollbackToLastCheckpoint() { + GOOGLE_DCHECK(!checkpoints_.empty()); + const CheckPoint& checkpoint = checkpoints_.back(); + + for (size_t i = checkpoint.pending_symbols_before_checkpoint; + i < symbols_after_checkpoint_.size(); i++) { + symbols_by_name_.erase(symbols_after_checkpoint_[i]); + } + for (size_t i = checkpoint.pending_files_before_checkpoint; + i < files_after_checkpoint_.size(); i++) { + files_by_name_.erase(files_after_checkpoint_[i]->name()); + } + for (size_t i = checkpoint.pending_extensions_before_checkpoint; + i < extensions_after_checkpoint_.size(); i++) { + extensions_.erase(extensions_after_checkpoint_[i]); + } + + symbols_after_checkpoint_.resize( + checkpoint.pending_symbols_before_checkpoint); + files_after_checkpoint_.resize(checkpoint.pending_files_before_checkpoint); + extensions_after_checkpoint_.resize( + checkpoint.pending_extensions_before_checkpoint); + + flat_allocs_.resize(checkpoint.flat_allocations_before_checkpoint); + misc_allocs_.resize(checkpoint.misc_allocations_before_checkpoint); + checkpoints_.pop_back(); +} + +// ------------------------------------------------------------------- + +inline Symbol DescriptorPool::Tables::FindSymbol(StringPiece key) const { + Symbol::QueryKey name; + name.name = key; + auto it = symbols_by_name_.find(name); + return it == symbols_by_name_.end() ? Symbol() : *it; +} + +inline Symbol FileDescriptorTables::FindNestedSymbol( + const void* parent, StringPiece name) const { + Symbol::QueryKey query; + query.name = name; + query.parent = parent; + auto it = symbols_by_parent_.find(query); + return it == symbols_by_parent_.end() ? Symbol() : *it; +} + +Symbol DescriptorPool::Tables::FindByNameHelper(const DescriptorPool* pool, + StringPiece name) { + if (pool->mutex_ != nullptr) { + // Fast path: the Symbol is already cached. This is just a hash lookup. + ReaderMutexLock lock(pool->mutex_); + if (known_bad_symbols_.empty() && known_bad_files_.empty()) { + Symbol result = FindSymbol(name); + if (!result.IsNull()) return result; + } + } + MutexLockMaybe lock(pool->mutex_); + if (pool->fallback_database_ != nullptr) { + known_bad_symbols_.clear(); + known_bad_files_.clear(); + } + Symbol result = FindSymbol(name); + + if (result.IsNull() && pool->underlay_ != nullptr) { + // Symbol not found; check the underlay. + result = pool->underlay_->tables_->FindByNameHelper(pool->underlay_, name); + } + + if (result.IsNull()) { + // Symbol still not found, so check fallback database. + if (pool->TryFindSymbolInFallbackDatabase(name)) { + result = FindSymbol(name); + } + } + + return result; +} + +inline const FileDescriptor* DescriptorPool::Tables::FindFile( + StringPiece key) const { + return FindPtrOrNull(files_by_name_, key); +} + +inline const FieldDescriptor* FileDescriptorTables::FindFieldByNumber( + const Descriptor* parent, int number) const { + // If `number` is within the sequential range, just index into the parent + // without doing a table lookup. + if (parent != nullptr && // + 1 <= number && number <= parent->sequential_field_limit_) { + return parent->field(number - 1); + } + + Symbol::QueryKey query; + query.parent = parent; + query.field_number = number; + + auto it = fields_by_number_.find(query); + return it == fields_by_number_.end() ? nullptr : it->field_descriptor(); +} + +const void* FileDescriptorTables::FindParentForFieldsByMap( + const FieldDescriptor* field) const { + if (field->is_extension()) { + if (field->extension_scope() == nullptr) { + return field->file(); + } else { + return field->extension_scope(); + } + } else { + return field->containing_type(); + } +} + +void FileDescriptorTables::FieldsByLowercaseNamesLazyInitStatic( + const FileDescriptorTables* tables) { + tables->FieldsByLowercaseNamesLazyInitInternal(); +} + +void FileDescriptorTables::FieldsByLowercaseNamesLazyInitInternal() const { + auto* map = new FieldsByNameMap; + for (Symbol symbol : symbols_by_parent_) { + const FieldDescriptor* field = symbol.field_descriptor(); + if (!field) continue; + (*map)[{FindParentForFieldsByMap(field), field->lowercase_name().c_str()}] = + field; + } + fields_by_lowercase_name_.store(map, std::memory_order_release); +} + +inline const FieldDescriptor* FileDescriptorTables::FindFieldByLowercaseName( + const void* parent, StringPiece lowercase_name) const { + internal::call_once( + fields_by_lowercase_name_once_, + &FileDescriptorTables::FieldsByLowercaseNamesLazyInitStatic, this); + return FindPtrOrNull( + *fields_by_lowercase_name_.load(std::memory_order_acquire), + PointerStringPair(parent, lowercase_name)); +} + +void FileDescriptorTables::FieldsByCamelcaseNamesLazyInitStatic( + const FileDescriptorTables* tables) { + tables->FieldsByCamelcaseNamesLazyInitInternal(); +} + +void FileDescriptorTables::FieldsByCamelcaseNamesLazyInitInternal() const { + auto* map = new FieldsByNameMap; + for (Symbol symbol : symbols_by_parent_) { + const FieldDescriptor* field = symbol.field_descriptor(); + if (!field) continue; + (*map)[{FindParentForFieldsByMap(field), field->camelcase_name().c_str()}] = + field; + } + fields_by_camelcase_name_.store(map, std::memory_order_release); +} + +inline const FieldDescriptor* FileDescriptorTables::FindFieldByCamelcaseName( + const void* parent, StringPiece camelcase_name) const { + internal::call_once( + fields_by_camelcase_name_once_, + FileDescriptorTables::FieldsByCamelcaseNamesLazyInitStatic, this); + return FindPtrOrNull( + *fields_by_camelcase_name_.load(std::memory_order_acquire), + PointerStringPair(parent, camelcase_name)); +} + +inline const EnumValueDescriptor* FileDescriptorTables::FindEnumValueByNumber( + const EnumDescriptor* parent, int number) const { + // If `number` is within the sequential range, just index into the parent + // without doing a table lookup. + const int base = parent->value(0)->number(); + if (base <= number && + number <= static_cast<int64_t>(base) + parent->sequential_value_limit_) { + return parent->value(number - base); + } + + Symbol::QueryKey query; + query.parent = parent; + query.field_number = number; + + auto it = enum_values_by_number_.find(query); + return it == enum_values_by_number_.end() ? nullptr + : it->enum_value_descriptor(); +} + +inline const EnumValueDescriptor* +FileDescriptorTables::FindEnumValueByNumberCreatingIfUnknown( + const EnumDescriptor* parent, int number) const { + // First try, with map of compiled-in values. + { + const auto* value = FindEnumValueByNumber(parent, number); + if (value != nullptr) { + return value; + } + } + + Symbol::QueryKey query; + query.parent = parent; + query.field_number = number; + + // Second try, with reader lock held on unknown enum values: common case. + { + ReaderMutexLock l(&unknown_enum_values_mu_); + auto it = unknown_enum_values_by_number_.find(query); + if (it != unknown_enum_values_by_number_.end() && + it->enum_value_descriptor() != nullptr) { + return it->enum_value_descriptor(); + } + } + // If not found, try again with writer lock held, and create new descriptor if + // necessary. + { + WriterMutexLock l(&unknown_enum_values_mu_); + auto it = unknown_enum_values_by_number_.find(query); + if (it != unknown_enum_values_by_number_.end() && + it->enum_value_descriptor() != nullptr) { + return it->enum_value_descriptor(); + } + + // Create an EnumValueDescriptor dynamically. We don't insert it into the + // EnumDescriptor (it's not a part of the enum as originally defined), but + // we do insert it into the table so that we can return the same pointer + // later. + std::string enum_value_name = StringPrintf( + "UNKNOWN_ENUM_VALUE_%s_%d", parent->name().c_str(), number); + auto* pool = DescriptorPool::generated_pool(); + auto* tables = const_cast<DescriptorPool::Tables*>(pool->tables_.get()); + internal::FlatAllocator alloc; + alloc.PlanArray<EnumValueDescriptor>(1); + alloc.PlanArray<std::string>(2); + + { + // Must lock the pool because we will do allocations in the shared arena. + MutexLockMaybe l2(pool->mutex_); + alloc.FinalizePlanning(tables); + } + EnumValueDescriptor* result = alloc.AllocateArray<EnumValueDescriptor>(1); + result->all_names_ = alloc.AllocateStrings( + enum_value_name, + StrCat(parent->full_name(), ".", enum_value_name)); + result->number_ = number; + result->type_ = parent; + result->options_ = &EnumValueOptions::default_instance(); + unknown_enum_values_by_number_.insert(Symbol::EnumValue(result, 0)); + return result; + } +} + +inline const FieldDescriptor* DescriptorPool::Tables::FindExtension( + const Descriptor* extendee, int number) const { + return FindPtrOrNull(extensions_, std::make_pair(extendee, number)); +} + +inline void DescriptorPool::Tables::FindAllExtensions( + const Descriptor* extendee, + std::vector<const FieldDescriptor*>* out) const { + ExtensionsGroupedByDescriptorMap::const_iterator it = + extensions_.lower_bound(std::make_pair(extendee, 0)); + for (; it != extensions_.end() && it->first.first == extendee; ++it) { + out->push_back(it->second); + } +} + +// ------------------------------------------------------------------- + +bool DescriptorPool::Tables::AddSymbol(const std::string& full_name, + Symbol symbol) { + GOOGLE_DCHECK_EQ(full_name, symbol.full_name()); + if (symbols_by_name_.insert(symbol).second) { + symbols_after_checkpoint_.push_back(symbol); + return true; + } else { + return false; + } +} + +bool FileDescriptorTables::AddAliasUnderParent(const void* parent, + const std::string& name, + Symbol symbol) { + GOOGLE_DCHECK_EQ(name, symbol.parent_name_key().second); + GOOGLE_DCHECK_EQ(parent, symbol.parent_name_key().first); + return symbols_by_parent_.insert(symbol).second; +} + +bool DescriptorPool::Tables::AddFile(const FileDescriptor* file) { + if (InsertIfNotPresent(&files_by_name_, file->name(), file)) { + files_after_checkpoint_.push_back(file); + return true; + } else { + return false; + } +} + +void FileDescriptorTables::FinalizeTables() {} + +bool FileDescriptorTables::AddFieldByNumber(FieldDescriptor* field) { + // Skip fields that are at the start of the sequence. + if (field->containing_type() != nullptr && field->number() >= 1 && + field->number() <= field->containing_type()->sequential_field_limit_) { + if (field->is_extension()) { + // Conflicts with the field that already exists in the sequential range. + return false; + } + // Only return true if the field at that index matches. Otherwise it + // conflicts with the existing field in the sequential range. + return field->containing_type()->field(field->number() - 1) == field; + } + + return fields_by_number_.insert(Symbol(field)).second; +} + +bool FileDescriptorTables::AddEnumValueByNumber(EnumValueDescriptor* value) { + // Skip values that are at the start of the sequence. + const int base = value->type()->value(0)->number(); + if (base <= value->number() && + value->number() <= + static_cast<int64_t>(base) + value->type()->sequential_value_limit_) + return true; + return enum_values_by_number_.insert(Symbol::EnumValue(value, 0)).second; +} + +bool DescriptorPool::Tables::AddExtension(const FieldDescriptor* field) { + DescriptorIntPair key(field->containing_type(), field->number()); + if (InsertIfNotPresent(&extensions_, key, field)) { + extensions_after_checkpoint_.push_back(key); + return true; + } else { + return false; + } +} + +// ------------------------------------------------------------------- + +template <typename Type> +Type* DescriptorPool::Tables::Allocate() { + static_assert(std::is_trivially_destructible<Type>::value, ""); + static_assert(alignof(Type) <= 8, ""); + return ::new (AllocateBytes(sizeof(Type))) Type{}; +} + +void* DescriptorPool::Tables::AllocateBytes(int size) { + if (size == 0) return nullptr; + void* p = ::operator new(size + RoundUpTo<8>(sizeof(int))); + int* sizep = static_cast<int*>(p); + misc_allocs_.emplace_back(sizep); + *sizep = size; + return static_cast<char*>(p) + RoundUpTo<8>(sizeof(int)); +} + +template <typename... T> +internal::FlatAllocator::Allocation* DescriptorPool::Tables::CreateFlatAlloc( + const TypeMap<IntT, T...>& sizes) { + auto ends = CalculateEnds(sizes); + using FlatAlloc = internal::FlatAllocator::Allocation; + + int last_end = ends.template Get< + typename std::tuple_element<sizeof...(T) - 1, std::tuple<T...>>::type>(); + size_t total_size = + last_end + RoundUpTo<FlatAlloc::kMaxAlign>(sizeof(FlatAlloc)); + char* data = static_cast<char*>(::operator new(total_size)); + auto* res = ::new (data) FlatAlloc(ends); + flat_allocs_.emplace_back(res); + + return res; +} + +void FileDescriptorTables::BuildLocationsByPath( + std::pair<const FileDescriptorTables*, const SourceCodeInfo*>* p) { + for (int i = 0, len = p->second->location_size(); i < len; ++i) { + const SourceCodeInfo_Location* loc = &p->second->location().Get(i); + p->first->locations_by_path_[Join(loc->path(), ",")] = loc; + } +} + +const SourceCodeInfo_Location* FileDescriptorTables::GetSourceLocation( + const std::vector<int>& path, const SourceCodeInfo* info) const { + std::pair<const FileDescriptorTables*, const SourceCodeInfo*> p( + std::make_pair(this, info)); + internal::call_once(locations_by_path_once_, + FileDescriptorTables::BuildLocationsByPath, &p); + return FindPtrOrNull(locations_by_path_, Join(path, ",")); +} + +// =================================================================== +// DescriptorPool + +DescriptorPool::ErrorCollector::~ErrorCollector() {} + +DescriptorPool::DescriptorPool() + : mutex_(nullptr), + fallback_database_(nullptr), + default_error_collector_(nullptr), + underlay_(nullptr), + tables_(new Tables), + enforce_dependencies_(true), + lazily_build_dependencies_(false), + allow_unknown_(false), + enforce_weak_(false), + disallow_enforce_utf8_(false) {} + +DescriptorPool::DescriptorPool(DescriptorDatabase* fallback_database, + ErrorCollector* error_collector) + : mutex_(new internal::WrappedMutex), + fallback_database_(fallback_database), + default_error_collector_(error_collector), + underlay_(nullptr), + tables_(new Tables), + enforce_dependencies_(true), + lazily_build_dependencies_(false), + allow_unknown_(false), + enforce_weak_(false), + disallow_enforce_utf8_(false) {} + +DescriptorPool::DescriptorPool(const DescriptorPool* underlay) + : mutex_(nullptr), + fallback_database_(nullptr), + default_error_collector_(nullptr), + underlay_(underlay), + tables_(new Tables), + enforce_dependencies_(true), + lazily_build_dependencies_(false), + allow_unknown_(false), + enforce_weak_(false), + disallow_enforce_utf8_(false) {} + +DescriptorPool::~DescriptorPool() { + if (mutex_ != nullptr) delete mutex_; +} + +// DescriptorPool::BuildFile() defined later. +// DescriptorPool::BuildFileCollectingErrors() defined later. + +void DescriptorPool::InternalDontEnforceDependencies() { + enforce_dependencies_ = false; +} + +void DescriptorPool::AddUnusedImportTrackFile(ConstStringParam file_name, + bool is_error) { + unused_import_track_files_[std::string(file_name)] = is_error; +} + +void DescriptorPool::ClearUnusedImportTrackFiles() { + unused_import_track_files_.clear(); +} + +bool DescriptorPool::InternalIsFileLoaded(ConstStringParam filename) const { + MutexLockMaybe lock(mutex_); + return tables_->FindFile(filename) != nullptr; +} + +// generated_pool ==================================================== + +namespace { + + +EncodedDescriptorDatabase* GeneratedDatabase() { + static auto generated_database = + internal::OnShutdownDelete(new EncodedDescriptorDatabase()); + return generated_database; +} + +DescriptorPool* NewGeneratedPool() { + auto generated_pool = new DescriptorPool(GeneratedDatabase()); + generated_pool->InternalSetLazilyBuildDependencies(); + return generated_pool; +} + +} // anonymous namespace + +DescriptorDatabase* DescriptorPool::internal_generated_database() { + return GeneratedDatabase(); +} + +DescriptorPool* DescriptorPool::internal_generated_pool() { + static DescriptorPool* generated_pool = + internal::OnShutdownDelete(NewGeneratedPool()); + return generated_pool; +} + +const DescriptorPool* DescriptorPool::generated_pool() { + const DescriptorPool* pool = internal_generated_pool(); + // Ensure that descriptor.proto has been registered in the generated pool. + DescriptorProto::descriptor(); + return pool; +} + + +void DescriptorPool::InternalAddGeneratedFile( + const void* encoded_file_descriptor, int size) { + // So, this function is called in the process of initializing the + // descriptors for generated proto classes. Each generated .pb.cc file + // has an internal procedure called AddDescriptors() which is called at + // process startup, and that function calls this one in order to register + // the raw bytes of the FileDescriptorProto representing the file. + // + // We do not actually construct the descriptor objects right away. We just + // hang on to the bytes until they are actually needed. We actually construct + // the descriptor the first time one of the following things happens: + // * Someone calls a method like descriptor(), GetDescriptor(), or + // GetReflection() on the generated types, which requires returning the + // descriptor or an object based on it. + // * Someone looks up the descriptor in DescriptorPool::generated_pool(). + // + // Once one of these happens, the DescriptorPool actually parses the + // FileDescriptorProto and generates a FileDescriptor (and all its children) + // based on it. + // + // Note that FileDescriptorProto is itself a generated protocol message. + // Therefore, when we parse one, we have to be very careful to avoid using + // any descriptor-based operations, since this might cause infinite recursion + // or deadlock. + GOOGLE_CHECK(GeneratedDatabase()->Add(encoded_file_descriptor, size)); +} + + +// Find*By* methods ================================================== + +// TODO(kenton): There's a lot of repeated code here, but I'm not sure if +// there's any good way to factor it out. Think about this some time when +// there's nothing more important to do (read: never). + +const FileDescriptor* DescriptorPool::FindFileByName( + ConstStringParam name) const { + MutexLockMaybe lock(mutex_); + if (fallback_database_ != nullptr) { + tables_->known_bad_symbols_.clear(); + tables_->known_bad_files_.clear(); + } + const FileDescriptor* result = tables_->FindFile(name); + if (result != nullptr) return result; + if (underlay_ != nullptr) { + result = underlay_->FindFileByName(name); + if (result != nullptr) return result; + } + if (TryFindFileInFallbackDatabase(name)) { + result = tables_->FindFile(name); + if (result != nullptr) return result; + } + return nullptr; +} + +const FileDescriptor* DescriptorPool::FindFileContainingSymbol( + ConstStringParam symbol_name) const { + MutexLockMaybe lock(mutex_); + if (fallback_database_ != nullptr) { + tables_->known_bad_symbols_.clear(); + tables_->known_bad_files_.clear(); + } + Symbol result = tables_->FindSymbol(symbol_name); + if (!result.IsNull()) return result.GetFile(); + if (underlay_ != nullptr) { + const FileDescriptor* file_result = + underlay_->FindFileContainingSymbol(symbol_name); + if (file_result != nullptr) return file_result; + } + if (TryFindSymbolInFallbackDatabase(symbol_name)) { + result = tables_->FindSymbol(symbol_name); + if (!result.IsNull()) return result.GetFile(); + } + return nullptr; +} + +const Descriptor* DescriptorPool::FindMessageTypeByName( + ConstStringParam name) const { + return tables_->FindByNameHelper(this, name).descriptor(); +} + +const FieldDescriptor* DescriptorPool::FindFieldByName( + ConstStringParam name) const { + if (const FieldDescriptor* field = + tables_->FindByNameHelper(this, name).field_descriptor()) { + if (!field->is_extension()) { + return field; + } + } + return nullptr; +} + +const FieldDescriptor* DescriptorPool::FindExtensionByName( + ConstStringParam name) const { + if (const FieldDescriptor* field = + tables_->FindByNameHelper(this, name).field_descriptor()) { + if (field->is_extension()) { + return field; + } + } + return nullptr; +} + +const OneofDescriptor* DescriptorPool::FindOneofByName( + ConstStringParam name) const { + return tables_->FindByNameHelper(this, name).oneof_descriptor(); +} + +const EnumDescriptor* DescriptorPool::FindEnumTypeByName( + ConstStringParam name) const { + return tables_->FindByNameHelper(this, name).enum_descriptor(); +} + +const EnumValueDescriptor* DescriptorPool::FindEnumValueByName( + ConstStringParam name) const { + return tables_->FindByNameHelper(this, name).enum_value_descriptor(); +} + +const ServiceDescriptor* DescriptorPool::FindServiceByName( + ConstStringParam name) const { + return tables_->FindByNameHelper(this, name).service_descriptor(); +} + +const MethodDescriptor* DescriptorPool::FindMethodByName( + ConstStringParam name) const { + return tables_->FindByNameHelper(this, name).method_descriptor(); +} + +const FieldDescriptor* DescriptorPool::FindExtensionByNumber( + const Descriptor* extendee, int number) const { + if (extendee->extension_range_count() == 0) return nullptr; + // A faster path to reduce lock contention in finding extensions, assuming + // most extensions will be cache hit. + if (mutex_ != nullptr) { + ReaderMutexLock lock(mutex_); + const FieldDescriptor* result = tables_->FindExtension(extendee, number); + if (result != nullptr) { + return result; + } + } + MutexLockMaybe lock(mutex_); + if (fallback_database_ != nullptr) { + tables_->known_bad_symbols_.clear(); + tables_->known_bad_files_.clear(); + } + const FieldDescriptor* result = tables_->FindExtension(extendee, number); + if (result != nullptr) { + return result; + } + if (underlay_ != nullptr) { + result = underlay_->FindExtensionByNumber(extendee, number); + if (result != nullptr) return result; + } + if (TryFindExtensionInFallbackDatabase(extendee, number)) { + result = tables_->FindExtension(extendee, number); + if (result != nullptr) { + return result; + } + } + return nullptr; +} + +const FieldDescriptor* DescriptorPool::InternalFindExtensionByNumberNoLock( + const Descriptor* extendee, int number) const { + if (extendee->extension_range_count() == 0) return nullptr; + + const FieldDescriptor* result = tables_->FindExtension(extendee, number); + if (result != nullptr) { + return result; + } + + if (underlay_ != nullptr) { + result = underlay_->InternalFindExtensionByNumberNoLock(extendee, number); + if (result != nullptr) return result; + } + + return nullptr; +} + +const FieldDescriptor* DescriptorPool::FindExtensionByPrintableName( + const Descriptor* extendee, ConstStringParam printable_name) const { + if (extendee->extension_range_count() == 0) return nullptr; + const FieldDescriptor* result = FindExtensionByName(printable_name); + if (result != nullptr && result->containing_type() == extendee) { + return result; + } + if (extendee->options().message_set_wire_format()) { + // MessageSet extensions may be identified by type name. + const Descriptor* type = FindMessageTypeByName(printable_name); + if (type != nullptr) { + // Look for a matching extension in the foreign type's scope. + const int type_extension_count = type->extension_count(); + for (int i = 0; i < type_extension_count; i++) { + const FieldDescriptor* extension = type->extension(i); + if (extension->containing_type() == extendee && + extension->type() == FieldDescriptor::TYPE_MESSAGE && + extension->is_optional() && extension->message_type() == type) { + // Found it. + return extension; + } + } + } + } + return nullptr; +} + +void DescriptorPool::FindAllExtensions( + const Descriptor* extendee, + std::vector<const FieldDescriptor*>* out) const { + MutexLockMaybe lock(mutex_); + if (fallback_database_ != nullptr) { + tables_->known_bad_symbols_.clear(); + tables_->known_bad_files_.clear(); + } + + // Initialize tables_->extensions_ from the fallback database first + // (but do this only once per descriptor). + if (fallback_database_ != nullptr && + tables_->extensions_loaded_from_db_.count(extendee) == 0) { + std::vector<int> numbers; + if (fallback_database_->FindAllExtensionNumbers(extendee->full_name(), + &numbers)) { + for (int number : numbers) { + if (tables_->FindExtension(extendee, number) == nullptr) { + TryFindExtensionInFallbackDatabase(extendee, number); + } + } + tables_->extensions_loaded_from_db_.insert(extendee); + } + } + + tables_->FindAllExtensions(extendee, out); + if (underlay_ != nullptr) { + underlay_->FindAllExtensions(extendee, out); + } +} + + +// ------------------------------------------------------------------- + +const FieldDescriptor* Descriptor::FindFieldByNumber(int key) const { + const FieldDescriptor* result = file()->tables_->FindFieldByNumber(this, key); + if (result == nullptr || result->is_extension()) { + return nullptr; + } else { + return result; + } +} + +const FieldDescriptor* Descriptor::FindFieldByLowercaseName( + ConstStringParam key) const { + const FieldDescriptor* result = + file()->tables_->FindFieldByLowercaseName(this, key); + if (result == nullptr || result->is_extension()) { + return nullptr; + } else { + return result; + } +} + +const FieldDescriptor* Descriptor::FindFieldByCamelcaseName( + ConstStringParam key) const { + const FieldDescriptor* result = + file()->tables_->FindFieldByCamelcaseName(this, key); + if (result == nullptr || result->is_extension()) { + return nullptr; + } else { + return result; + } +} + +const FieldDescriptor* Descriptor::FindFieldByName(ConstStringParam key) const { + const FieldDescriptor* field = + file()->tables_->FindNestedSymbol(this, key).field_descriptor(); + return field != nullptr && !field->is_extension() ? field : nullptr; +} + +const OneofDescriptor* Descriptor::FindOneofByName(ConstStringParam key) const { + return file()->tables_->FindNestedSymbol(this, key).oneof_descriptor(); +} + +const FieldDescriptor* Descriptor::FindExtensionByName( + ConstStringParam key) const { + const FieldDescriptor* field = + file()->tables_->FindNestedSymbol(this, key).field_descriptor(); + return field != nullptr && field->is_extension() ? field : nullptr; +} + +const FieldDescriptor* Descriptor::FindExtensionByLowercaseName( + ConstStringParam key) const { + const FieldDescriptor* result = + file()->tables_->FindFieldByLowercaseName(this, key); + if (result == nullptr || !result->is_extension()) { + return nullptr; + } else { + return result; + } +} + +const FieldDescriptor* Descriptor::FindExtensionByCamelcaseName( + ConstStringParam key) const { + const FieldDescriptor* result = + file()->tables_->FindFieldByCamelcaseName(this, key); + if (result == nullptr || !result->is_extension()) { + return nullptr; + } else { + return result; + } +} + +const Descriptor* Descriptor::FindNestedTypeByName(ConstStringParam key) const { + return file()->tables_->FindNestedSymbol(this, key).descriptor(); +} + +const EnumDescriptor* Descriptor::FindEnumTypeByName( + ConstStringParam key) const { + return file()->tables_->FindNestedSymbol(this, key).enum_descriptor(); +} + +const EnumValueDescriptor* Descriptor::FindEnumValueByName( + ConstStringParam key) const { + return file()->tables_->FindNestedSymbol(this, key).enum_value_descriptor(); +} + +const FieldDescriptor* Descriptor::map_key() const { + if (!options().map_entry()) return nullptr; + GOOGLE_DCHECK_EQ(field_count(), 2); + return field(0); +} + +const FieldDescriptor* Descriptor::map_value() const { + if (!options().map_entry()) return nullptr; + GOOGLE_DCHECK_EQ(field_count(), 2); + return field(1); +} + +const EnumValueDescriptor* EnumDescriptor::FindValueByName( + ConstStringParam key) const { + return file()->tables_->FindNestedSymbol(this, key).enum_value_descriptor(); +} + +const EnumValueDescriptor* EnumDescriptor::FindValueByNumber(int key) const { + return file()->tables_->FindEnumValueByNumber(this, key); +} + +const EnumValueDescriptor* EnumDescriptor::FindValueByNumberCreatingIfUnknown( + int key) const { + return file()->tables_->FindEnumValueByNumberCreatingIfUnknown(this, key); +} + +const MethodDescriptor* ServiceDescriptor::FindMethodByName( + ConstStringParam key) const { + return file()->tables_->FindNestedSymbol(this, key).method_descriptor(); +} + +const Descriptor* FileDescriptor::FindMessageTypeByName( + ConstStringParam key) const { + return tables_->FindNestedSymbol(this, key).descriptor(); +} + +const EnumDescriptor* FileDescriptor::FindEnumTypeByName( + ConstStringParam key) const { + return tables_->FindNestedSymbol(this, key).enum_descriptor(); +} + +const EnumValueDescriptor* FileDescriptor::FindEnumValueByName( + ConstStringParam key) const { + return tables_->FindNestedSymbol(this, key).enum_value_descriptor(); +} + +const ServiceDescriptor* FileDescriptor::FindServiceByName( + ConstStringParam key) const { + return tables_->FindNestedSymbol(this, key).service_descriptor(); +} + +const FieldDescriptor* FileDescriptor::FindExtensionByName( + ConstStringParam key) const { + const FieldDescriptor* field = + tables_->FindNestedSymbol(this, key).field_descriptor(); + return field != nullptr && field->is_extension() ? field : nullptr; +} + +const FieldDescriptor* FileDescriptor::FindExtensionByLowercaseName( + ConstStringParam key) const { + const FieldDescriptor* result = tables_->FindFieldByLowercaseName(this, key); + if (result == nullptr || !result->is_extension()) { + return nullptr; + } else { + return result; + } +} + +const FieldDescriptor* FileDescriptor::FindExtensionByCamelcaseName( + ConstStringParam key) const { + const FieldDescriptor* result = tables_->FindFieldByCamelcaseName(this, key); + if (result == nullptr || !result->is_extension()) { + return nullptr; + } else { + return result; + } +} + +void Descriptor::ExtensionRange::CopyTo( + DescriptorProto_ExtensionRange* proto) const { + proto->set_start(this->start); + proto->set_end(this->end); + if (options_ != &ExtensionRangeOptions::default_instance()) { + *proto->mutable_options() = *options_; + } +} + +const Descriptor::ExtensionRange* +Descriptor::FindExtensionRangeContainingNumber(int number) const { + // Linear search should be fine because we don't expect a message to have + // more than a couple extension ranges. + for (int i = 0; i < extension_range_count(); i++) { + if (number >= extension_range(i)->start && + number < extension_range(i)->end) { + return extension_range(i); + } + } + return nullptr; +} + +const Descriptor::ReservedRange* Descriptor::FindReservedRangeContainingNumber( + int number) const { + // TODO(chrisn): Consider a non-linear search. + for (int i = 0; i < reserved_range_count(); i++) { + if (number >= reserved_range(i)->start && number < reserved_range(i)->end) { + return reserved_range(i); + } + } + return nullptr; +} + +const EnumDescriptor::ReservedRange* +EnumDescriptor::FindReservedRangeContainingNumber(int number) const { + // TODO(chrisn): Consider a non-linear search. + for (int i = 0; i < reserved_range_count(); i++) { + if (number >= reserved_range(i)->start && + number <= reserved_range(i)->end) { + return reserved_range(i); + } + } + return nullptr; +} + +// ------------------------------------------------------------------- + +bool DescriptorPool::TryFindFileInFallbackDatabase( + StringPiece name) const { + if (fallback_database_ == nullptr) return false; + + auto name_string = std::string(name); + if (tables_->known_bad_files_.count(name_string) > 0) return false; + + FileDescriptorProto file_proto; + if (!fallback_database_->FindFileByName(name_string, &file_proto) || + BuildFileFromDatabase(file_proto) == nullptr) { + tables_->known_bad_files_.insert(std::move(name_string)); + return false; + } + return true; +} + +bool DescriptorPool::IsSubSymbolOfBuiltType(StringPiece name) const { + auto prefix = std::string(name); + for (;;) { + std::string::size_type dot_pos = prefix.find_last_of('.'); + if (dot_pos == std::string::npos) { + break; + } + prefix = prefix.substr(0, dot_pos); + Symbol symbol = tables_->FindSymbol(prefix); + // If the symbol type is anything other than PACKAGE, then its complete + // definition is already known. + if (!symbol.IsNull() && !symbol.IsPackage()) { + return true; + } + } + if (underlay_ != nullptr) { + // Check to see if any prefix of this symbol exists in the underlay. + return underlay_->IsSubSymbolOfBuiltType(name); + } + return false; +} + +bool DescriptorPool::TryFindSymbolInFallbackDatabase( + StringPiece name) const { + if (fallback_database_ == nullptr) return false; + + auto name_string = std::string(name); + if (tables_->known_bad_symbols_.count(name_string) > 0) return false; + + FileDescriptorProto file_proto; + if ( // We skip looking in the fallback database if the name is a sub-symbol + // of any descriptor that already exists in the descriptor pool (except + // for package descriptors). This is valid because all symbols except + // for packages are defined in a single file, so if the symbol exists + // then we should already have its definition. + // + // The other reason to do this is to support "overriding" type + // definitions by merging two databases that define the same type. (Yes, + // people do this.) The main difficulty with making this work is that + // FindFileContainingSymbol() is allowed to return both false positives + // (e.g., SimpleDescriptorDatabase, UpgradedDescriptorDatabase) and + // false negatives (e.g. ProtoFileParser, SourceTreeDescriptorDatabase). + // When two such databases are merged, looking up a non-existent + // sub-symbol of a type that already exists in the descriptor pool can + // result in an attempt to load multiple definitions of the same type. + // The check below avoids this. + IsSubSymbolOfBuiltType(name) + + // Look up file containing this symbol in fallback database. + || !fallback_database_->FindFileContainingSymbol(name_string, &file_proto) + + // Check if we've already built this file. If so, it apparently doesn't + // contain the symbol we're looking for. Some DescriptorDatabases + // return false positives. + || tables_->FindFile(file_proto.name()) != nullptr + + // Build the file. + || BuildFileFromDatabase(file_proto) == nullptr) { + tables_->known_bad_symbols_.insert(std::move(name_string)); + return false; + } + + return true; +} + +bool DescriptorPool::TryFindExtensionInFallbackDatabase( + const Descriptor* containing_type, int field_number) const { + if (fallback_database_ == nullptr) return false; + + FileDescriptorProto file_proto; + if (!fallback_database_->FindFileContainingExtension( + containing_type->full_name(), field_number, &file_proto)) { + return false; + } + + if (tables_->FindFile(file_proto.name()) != nullptr) { + // We've already loaded this file, and it apparently doesn't contain the + // extension we're looking for. Some DescriptorDatabases return false + // positives. + return false; + } + + if (BuildFileFromDatabase(file_proto) == nullptr) { + return false; + } + + return true; +} + +// =================================================================== + +bool FieldDescriptor::is_map_message_type() const { + return type_descriptor_.message_type->options().map_entry(); +} + +std::string FieldDescriptor::DefaultValueAsString( + bool quote_string_type) const { + GOOGLE_CHECK(has_default_value()) << "No default value"; + switch (cpp_type()) { + case CPPTYPE_INT32: + return StrCat(default_value_int32_t()); + case CPPTYPE_INT64: + return StrCat(default_value_int64_t()); + case CPPTYPE_UINT32: + return StrCat(default_value_uint32_t()); + case CPPTYPE_UINT64: + return StrCat(default_value_uint64_t()); + case CPPTYPE_FLOAT: + return SimpleFtoa(default_value_float()); + case CPPTYPE_DOUBLE: + return SimpleDtoa(default_value_double()); + case CPPTYPE_BOOL: + return default_value_bool() ? "true" : "false"; + case CPPTYPE_STRING: + if (quote_string_type) { + return "\"" + CEscape(default_value_string()) + "\""; + } else { + if (type() == TYPE_BYTES) { + return CEscape(default_value_string()); + } else { + return default_value_string(); + } + } + case CPPTYPE_ENUM: + return default_value_enum()->name(); + case CPPTYPE_MESSAGE: + GOOGLE_LOG(DFATAL) << "Messages can't have default values!"; + break; + } + GOOGLE_LOG(FATAL) << "Can't get here: failed to get default value as string"; + return ""; +} + +// CopyTo methods ==================================================== + +void FileDescriptor::CopyTo(FileDescriptorProto* proto) const { + proto->set_name(name()); + if (!package().empty()) proto->set_package(package()); + // TODO(liujisi): Also populate when syntax="proto2". + if (syntax() == SYNTAX_PROTO3) proto->set_syntax(SyntaxName(syntax())); + + for (int i = 0; i < dependency_count(); i++) { + proto->add_dependency(dependency(i)->name()); + } + + for (int i = 0; i < public_dependency_count(); i++) { + proto->add_public_dependency(public_dependencies_[i]); + } + + for (int i = 0; i < weak_dependency_count(); i++) { + proto->add_weak_dependency(weak_dependencies_[i]); + } + + for (int i = 0; i < message_type_count(); i++) { + message_type(i)->CopyTo(proto->add_message_type()); + } + for (int i = 0; i < enum_type_count(); i++) { + enum_type(i)->CopyTo(proto->add_enum_type()); + } + for (int i = 0; i < service_count(); i++) { + service(i)->CopyTo(proto->add_service()); + } + for (int i = 0; i < extension_count(); i++) { + extension(i)->CopyTo(proto->add_extension()); + } + + if (&options() != &FileOptions::default_instance()) { + proto->mutable_options()->CopyFrom(options()); + } +} + +void FileDescriptor::CopyJsonNameTo(FileDescriptorProto* proto) const { + if (message_type_count() != proto->message_type_size() || + extension_count() != proto->extension_size()) { + GOOGLE_LOG(ERROR) << "Cannot copy json_name to a proto of a different size."; + return; + } + for (int i = 0; i < message_type_count(); i++) { + message_type(i)->CopyJsonNameTo(proto->mutable_message_type(i)); + } + for (int i = 0; i < extension_count(); i++) { + extension(i)->CopyJsonNameTo(proto->mutable_extension(i)); + } +} + +void FileDescriptor::CopySourceCodeInfoTo(FileDescriptorProto* proto) const { + if (source_code_info_ && + source_code_info_ != &SourceCodeInfo::default_instance()) { + proto->mutable_source_code_info()->CopyFrom(*source_code_info_); + } +} + +void Descriptor::CopyTo(DescriptorProto* proto) const { + proto->set_name(name()); + + for (int i = 0; i < field_count(); i++) { + field(i)->CopyTo(proto->add_field()); + } + for (int i = 0; i < oneof_decl_count(); i++) { + oneof_decl(i)->CopyTo(proto->add_oneof_decl()); + } + for (int i = 0; i < nested_type_count(); i++) { + nested_type(i)->CopyTo(proto->add_nested_type()); + } + for (int i = 0; i < enum_type_count(); i++) { + enum_type(i)->CopyTo(proto->add_enum_type()); + } + for (int i = 0; i < extension_range_count(); i++) { + extension_range(i)->CopyTo(proto->add_extension_range()); + } + for (int i = 0; i < extension_count(); i++) { + extension(i)->CopyTo(proto->add_extension()); + } + for (int i = 0; i < reserved_range_count(); i++) { + DescriptorProto::ReservedRange* range = proto->add_reserved_range(); + range->set_start(reserved_range(i)->start); + range->set_end(reserved_range(i)->end); + } + for (int i = 0; i < reserved_name_count(); i++) { + proto->add_reserved_name(reserved_name(i)); + } + + if (&options() != &MessageOptions::default_instance()) { + proto->mutable_options()->CopyFrom(options()); + } +} + +void Descriptor::CopyJsonNameTo(DescriptorProto* proto) const { + if (field_count() != proto->field_size() || + nested_type_count() != proto->nested_type_size() || + extension_count() != proto->extension_size()) { + GOOGLE_LOG(ERROR) << "Cannot copy json_name to a proto of a different size."; + return; + } + for (int i = 0; i < field_count(); i++) { + field(i)->CopyJsonNameTo(proto->mutable_field(i)); + } + for (int i = 0; i < nested_type_count(); i++) { + nested_type(i)->CopyJsonNameTo(proto->mutable_nested_type(i)); + } + for (int i = 0; i < extension_count(); i++) { + extension(i)->CopyJsonNameTo(proto->mutable_extension(i)); + } +} + +void FieldDescriptor::CopyTo(FieldDescriptorProto* proto) const { + proto->set_name(name()); + proto->set_number(number()); + if (has_json_name_) { + proto->set_json_name(json_name()); + } + if (proto3_optional_) { + proto->set_proto3_optional(true); + } + // Some compilers do not allow static_cast directly between two enum types, + // so we must cast to int first. + proto->set_label(static_cast<FieldDescriptorProto::Label>( + implicit_cast<int>(label()))); + proto->set_type(static_cast<FieldDescriptorProto::Type>( + implicit_cast<int>(type()))); + + if (is_extension()) { + if (!containing_type()->is_unqualified_placeholder_) { + proto->set_extendee("."); + } + proto->mutable_extendee()->append(containing_type()->full_name()); + } + + if (cpp_type() == CPPTYPE_MESSAGE) { + if (message_type()->is_placeholder_) { + // We don't actually know if the type is a message type. It could be + // an enum. + proto->clear_type(); + } + + if (!message_type()->is_unqualified_placeholder_) { + proto->set_type_name("."); + } + proto->mutable_type_name()->append(message_type()->full_name()); + } else if (cpp_type() == CPPTYPE_ENUM) { + if (!enum_type()->is_unqualified_placeholder_) { + proto->set_type_name("."); + } + proto->mutable_type_name()->append(enum_type()->full_name()); + } + + if (has_default_value()) { + proto->set_default_value(DefaultValueAsString(false)); + } + + if (containing_oneof() != nullptr && !is_extension()) { + proto->set_oneof_index(containing_oneof()->index()); + } + + if (&options() != &FieldOptions::default_instance()) { + proto->mutable_options()->CopyFrom(options()); + } +} + +void FieldDescriptor::CopyJsonNameTo(FieldDescriptorProto* proto) const { + proto->set_json_name(json_name()); +} + +void OneofDescriptor::CopyTo(OneofDescriptorProto* proto) const { + proto->set_name(name()); + if (&options() != &OneofOptions::default_instance()) { + proto->mutable_options()->CopyFrom(options()); + } +} + +void EnumDescriptor::CopyTo(EnumDescriptorProto* proto) const { + proto->set_name(name()); + + for (int i = 0; i < value_count(); i++) { + value(i)->CopyTo(proto->add_value()); + } + for (int i = 0; i < reserved_range_count(); i++) { + EnumDescriptorProto::EnumReservedRange* range = proto->add_reserved_range(); + range->set_start(reserved_range(i)->start); + range->set_end(reserved_range(i)->end); + } + for (int i = 0; i < reserved_name_count(); i++) { + proto->add_reserved_name(reserved_name(i)); + } + + if (&options() != &EnumOptions::default_instance()) { + proto->mutable_options()->CopyFrom(options()); + } +} + +void EnumValueDescriptor::CopyTo(EnumValueDescriptorProto* proto) const { + proto->set_name(name()); + proto->set_number(number()); + + if (&options() != &EnumValueOptions::default_instance()) { + proto->mutable_options()->CopyFrom(options()); + } +} + +void ServiceDescriptor::CopyTo(ServiceDescriptorProto* proto) const { + proto->set_name(name()); + + for (int i = 0; i < method_count(); i++) { + method(i)->CopyTo(proto->add_method()); + } + + if (&options() != &ServiceOptions::default_instance()) { + proto->mutable_options()->CopyFrom(options()); + } +} + +void MethodDescriptor::CopyTo(MethodDescriptorProto* proto) const { + proto->set_name(name()); + + if (!input_type()->is_unqualified_placeholder_) { + proto->set_input_type("."); + } + proto->mutable_input_type()->append(input_type()->full_name()); + + if (!output_type()->is_unqualified_placeholder_) { + proto->set_output_type("."); + } + proto->mutable_output_type()->append(output_type()->full_name()); + + if (&options() != &MethodOptions::default_instance()) { + proto->mutable_options()->CopyFrom(options()); + } + + if (client_streaming_) { + proto->set_client_streaming(true); + } + if (server_streaming_) { + proto->set_server_streaming(true); + } +} + +// DebugString methods =============================================== + +namespace { + +bool RetrieveOptionsAssumingRightPool( + int depth, const Message& options, + std::vector<std::string>* option_entries) { + option_entries->clear(); + const Reflection* reflection = options.GetReflection(); + std::vector<const FieldDescriptor*> fields; + reflection->ListFields(options, &fields); + for (const FieldDescriptor* field : fields) { + int count = 1; + bool repeated = false; + if (field->is_repeated()) { + count = reflection->FieldSize(options, field); + repeated = true; + } + for (int j = 0; j < count; j++) { + std::string fieldval; + if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { + std::string tmp; + TextFormat::Printer printer; + printer.SetExpandAny(true); + printer.SetInitialIndentLevel(depth + 1); + printer.PrintFieldValueToString(options, field, repeated ? j : -1, + &tmp); + fieldval.append("{\n"); + fieldval.append(tmp); + fieldval.append(depth * 2, ' '); + fieldval.append("}"); + } else { + TextFormat::PrintFieldValueToString(options, field, repeated ? j : -1, + &fieldval); + } + std::string name; + if (field->is_extension()) { + name = "(." + field->full_name() + ")"; + } else { + name = field->name(); + } + option_entries->push_back(name + " = " + fieldval); + } + } + return !option_entries->empty(); +} + +// Used by each of the option formatters. +bool RetrieveOptions(int depth, const Message& options, + const DescriptorPool* pool, + std::vector<std::string>* option_entries) { + // When printing custom options for a descriptor, we must use an options + // message built on top of the same DescriptorPool where the descriptor + // is coming from. This is to ensure we are interpreting custom options + // against the right pool. + if (options.GetDescriptor()->file()->pool() == pool) { + return RetrieveOptionsAssumingRightPool(depth, options, option_entries); + } else { + const Descriptor* option_descriptor = + pool->FindMessageTypeByName(options.GetDescriptor()->full_name()); + if (option_descriptor == nullptr) { + // descriptor.proto is not in the pool. This means no custom options are + // used so we are safe to proceed with the compiled options message type. + return RetrieveOptionsAssumingRightPool(depth, options, option_entries); + } + DynamicMessageFactory factory; + std::unique_ptr<Message> dynamic_options( + factory.GetPrototype(option_descriptor)->New()); + std::string serialized = options.SerializeAsString(); + io::CodedInputStream input( + reinterpret_cast<const uint8_t*>(serialized.c_str()), + serialized.size()); + input.SetExtensionRegistry(pool, &factory); + if (dynamic_options->ParseFromCodedStream(&input)) { + return RetrieveOptionsAssumingRightPool(depth, *dynamic_options, + option_entries); + } else { + GOOGLE_LOG(ERROR) << "Found invalid proto option data for: " + << options.GetDescriptor()->full_name(); + return RetrieveOptionsAssumingRightPool(depth, options, option_entries); + } + } +} + +// Formats options that all appear together in brackets. Does not include +// brackets. +bool FormatBracketedOptions(int depth, const Message& options, + const DescriptorPool* pool, std::string* output) { + std::vector<std::string> all_options; + if (RetrieveOptions(depth, options, pool, &all_options)) { + output->append(Join(all_options, ", ")); + } + return !all_options.empty(); +} + +// Formats options one per line +bool FormatLineOptions(int depth, const Message& options, + const DescriptorPool* pool, std::string* output) { + std::string prefix(depth * 2, ' '); + std::vector<std::string> all_options; + if (RetrieveOptions(depth, options, pool, &all_options)) { + for (const std::string& option : all_options) { + strings::SubstituteAndAppend(output, "$0option $1;\n", prefix, option); + } + } + return !all_options.empty(); +} + +class SourceLocationCommentPrinter { + public: + template <typename DescType> + SourceLocationCommentPrinter(const DescType* desc, const std::string& prefix, + const DebugStringOptions& options) + : options_(options), prefix_(prefix) { + // Perform the SourceLocation lookup only if we're including user comments, + // because the lookup is fairly expensive. + have_source_loc_ = + options.include_comments && desc->GetSourceLocation(&source_loc_); + } + SourceLocationCommentPrinter(const FileDescriptor* file, + const std::vector<int>& path, + const std::string& prefix, + const DebugStringOptions& options) + : options_(options), prefix_(prefix) { + // Perform the SourceLocation lookup only if we're including user comments, + // because the lookup is fairly expensive. + have_source_loc_ = + options.include_comments && file->GetSourceLocation(path, &source_loc_); + } + void AddPreComment(std::string* output) { + if (have_source_loc_) { + // Detached leading comments. + for (const std::string& leading_detached_comment : + source_loc_.leading_detached_comments) { + *output += FormatComment(leading_detached_comment); + *output += "\n"; + } + // Attached leading comments. + if (!source_loc_.leading_comments.empty()) { + *output += FormatComment(source_loc_.leading_comments); + } + } + } + void AddPostComment(std::string* output) { + if (have_source_loc_ && source_loc_.trailing_comments.size() > 0) { + *output += FormatComment(source_loc_.trailing_comments); + } + } + + // Format comment such that each line becomes a full-line C++-style comment in + // the DebugString() output. + std::string FormatComment(const std::string& comment_text) { + std::string stripped_comment = comment_text; + StripWhitespace(&stripped_comment); + std::vector<std::string> lines = Split(stripped_comment, "\n"); + std::string output; + for (const std::string& line : lines) { + strings::SubstituteAndAppend(&output, "$0// $1\n", prefix_, line); + } + return output; + } + + private: + + bool have_source_loc_; + SourceLocation source_loc_; + DebugStringOptions options_; + std::string prefix_; +}; + +} // anonymous namespace + +std::string FileDescriptor::DebugString() const { + DebugStringOptions options; // default options + return DebugStringWithOptions(options); +} + +std::string FileDescriptor::DebugStringWithOptions( + const DebugStringOptions& debug_string_options) const { + std::string contents; + { + std::vector<int> path; + path.push_back(FileDescriptorProto::kSyntaxFieldNumber); + SourceLocationCommentPrinter syntax_comment(this, path, "", + debug_string_options); + syntax_comment.AddPreComment(&contents); + strings::SubstituteAndAppend(&contents, "syntax = \"$0\";\n\n", + SyntaxName(syntax())); + syntax_comment.AddPostComment(&contents); + } + + SourceLocationCommentPrinter comment_printer(this, "", debug_string_options); + comment_printer.AddPreComment(&contents); + + std::set<int> public_dependencies; + std::set<int> weak_dependencies; + public_dependencies.insert(public_dependencies_, + public_dependencies_ + public_dependency_count_); + weak_dependencies.insert(weak_dependencies_, + weak_dependencies_ + weak_dependency_count_); + + for (int i = 0; i < dependency_count(); i++) { + if (public_dependencies.count(i) > 0) { + strings::SubstituteAndAppend(&contents, "import public \"$0\";\n", + dependency(i)->name()); + } else if (weak_dependencies.count(i) > 0) { + strings::SubstituteAndAppend(&contents, "import weak \"$0\";\n", + dependency(i)->name()); + } else { + strings::SubstituteAndAppend(&contents, "import \"$0\";\n", + dependency(i)->name()); + } + } + + if (!package().empty()) { + std::vector<int> path; + path.push_back(FileDescriptorProto::kPackageFieldNumber); + SourceLocationCommentPrinter package_comment(this, path, "", + debug_string_options); + package_comment.AddPreComment(&contents); + strings::SubstituteAndAppend(&contents, "package $0;\n\n", package()); + package_comment.AddPostComment(&contents); + } + + if (FormatLineOptions(0, options(), pool(), &contents)) { + contents.append("\n"); // add some space if we had options + } + + for (int i = 0; i < enum_type_count(); i++) { + enum_type(i)->DebugString(0, &contents, debug_string_options); + contents.append("\n"); + } + + // Find all the 'group' type extensions; we will not output their nested + // definitions (those will be done with their group field descriptor). + std::set<const Descriptor*> groups; + for (int i = 0; i < extension_count(); i++) { + if (extension(i)->type() == FieldDescriptor::TYPE_GROUP) { + groups.insert(extension(i)->message_type()); + } + } + + for (int i = 0; i < message_type_count(); i++) { + if (groups.count(message_type(i)) == 0) { + message_type(i)->DebugString(0, &contents, debug_string_options, + /* include_opening_clause */ true); + contents.append("\n"); + } + } + + for (int i = 0; i < service_count(); i++) { + service(i)->DebugString(&contents, debug_string_options); + contents.append("\n"); + } + + const Descriptor* containing_type = nullptr; + for (int i = 0; i < extension_count(); i++) { + if (extension(i)->containing_type() != containing_type) { + if (i > 0) contents.append("}\n\n"); + containing_type = extension(i)->containing_type(); + strings::SubstituteAndAppend(&contents, "extend .$0 {\n", + containing_type->full_name()); + } + extension(i)->DebugString(1, &contents, debug_string_options); + } + if (extension_count() > 0) contents.append("}\n\n"); + + comment_printer.AddPostComment(&contents); + + return contents; +} + +std::string Descriptor::DebugString() const { + DebugStringOptions options; // default options + return DebugStringWithOptions(options); +} + +std::string Descriptor::DebugStringWithOptions( + const DebugStringOptions& options) const { + std::string contents; + DebugString(0, &contents, options, /* include_opening_clause */ true); + return contents; +} + +void Descriptor::DebugString(int depth, std::string* contents, + const DebugStringOptions& debug_string_options, + bool include_opening_clause) const { + if (options().map_entry()) { + // Do not generate debug string for auto-generated map-entry type. + return; + } + std::string prefix(depth * 2, ' '); + ++depth; + + SourceLocationCommentPrinter comment_printer(this, prefix, + debug_string_options); + comment_printer.AddPreComment(contents); + + if (include_opening_clause) { + strings::SubstituteAndAppend(contents, "$0message $1", prefix, name()); + } + contents->append(" {\n"); + + FormatLineOptions(depth, options(), file()->pool(), contents); + + // Find all the 'group' types for fields and extensions; we will not output + // their nested definitions (those will be done with their group field + // descriptor). + std::set<const Descriptor*> groups; + for (int i = 0; i < field_count(); i++) { + if (field(i)->type() == FieldDescriptor::TYPE_GROUP) { + groups.insert(field(i)->message_type()); + } + } + for (int i = 0; i < extension_count(); i++) { + if (extension(i)->type() == FieldDescriptor::TYPE_GROUP) { + groups.insert(extension(i)->message_type()); + } + } + + for (int i = 0; i < nested_type_count(); i++) { + if (groups.count(nested_type(i)) == 0) { + nested_type(i)->DebugString(depth, contents, debug_string_options, + /* include_opening_clause */ true); + } + } + for (int i = 0; i < enum_type_count(); i++) { + enum_type(i)->DebugString(depth, contents, debug_string_options); + } + for (int i = 0; i < field_count(); i++) { + if (field(i)->real_containing_oneof() == nullptr) { + field(i)->DebugString(depth, contents, debug_string_options); + } else if (field(i)->containing_oneof()->field(0) == field(i)) { + // This is the first field in this oneof, so print the whole oneof. + field(i)->containing_oneof()->DebugString(depth, contents, + debug_string_options); + } + } + + for (int i = 0; i < extension_range_count(); i++) { + strings::SubstituteAndAppend(contents, "$0 extensions $1 to $2;\n", prefix, + extension_range(i)->start, + extension_range(i)->end - 1); + } + + // Group extensions by what they extend, so they can be printed out together. + const Descriptor* containing_type = nullptr; + for (int i = 0; i < extension_count(); i++) { + if (extension(i)->containing_type() != containing_type) { + if (i > 0) strings::SubstituteAndAppend(contents, "$0 }\n", prefix); + containing_type = extension(i)->containing_type(); + strings::SubstituteAndAppend(contents, "$0 extend .$1 {\n", prefix, + containing_type->full_name()); + } + extension(i)->DebugString(depth + 1, contents, debug_string_options); + } + if (extension_count() > 0) + strings::SubstituteAndAppend(contents, "$0 }\n", prefix); + + if (reserved_range_count() > 0) { + strings::SubstituteAndAppend(contents, "$0 reserved ", prefix); + for (int i = 0; i < reserved_range_count(); i++) { + const Descriptor::ReservedRange* range = reserved_range(i); + if (range->end == range->start + 1) { + strings::SubstituteAndAppend(contents, "$0, ", range->start); + } else if (range->end > FieldDescriptor::kMaxNumber) { + strings::SubstituteAndAppend(contents, "$0 to max, ", range->start); + } else { + strings::SubstituteAndAppend(contents, "$0 to $1, ", range->start, + range->end - 1); + } + } + contents->replace(contents->size() - 2, 2, ";\n"); + } + + if (reserved_name_count() > 0) { + strings::SubstituteAndAppend(contents, "$0 reserved ", prefix); + for (int i = 0; i < reserved_name_count(); i++) { + strings::SubstituteAndAppend(contents, "\"$0\", ", + CEscape(reserved_name(i))); + } + contents->replace(contents->size() - 2, 2, ";\n"); + } + + strings::SubstituteAndAppend(contents, "$0}\n", prefix); + comment_printer.AddPostComment(contents); +} + +std::string FieldDescriptor::DebugString() const { + DebugStringOptions options; // default options + return DebugStringWithOptions(options); +} + +std::string FieldDescriptor::DebugStringWithOptions( + const DebugStringOptions& debug_string_options) const { + std::string contents; + int depth = 0; + if (is_extension()) { + strings::SubstituteAndAppend(&contents, "extend .$0 {\n", + containing_type()->full_name()); + depth = 1; + } + DebugString(depth, &contents, debug_string_options); + if (is_extension()) { + contents.append("}\n"); + } + return contents; +} + +// The field type string used in FieldDescriptor::DebugString() +std::string FieldDescriptor::FieldTypeNameDebugString() const { + switch (type()) { + case TYPE_MESSAGE: + return "." + message_type()->full_name(); + case TYPE_ENUM: + return "." + enum_type()->full_name(); + default: + return kTypeToName[type()]; + } +} + +void FieldDescriptor::DebugString( + int depth, std::string* contents, + const DebugStringOptions& debug_string_options) const { + std::string prefix(depth * 2, ' '); + std::string field_type; + + // Special case map fields. + if (is_map()) { + strings::SubstituteAndAppend( + &field_type, "map<$0, $1>", + message_type()->field(0)->FieldTypeNameDebugString(), + message_type()->field(1)->FieldTypeNameDebugString()); + } else { + field_type = FieldTypeNameDebugString(); + } + + std::string label = StrCat(kLabelToName[this->label()], " "); + + // Label is omitted for maps, oneof, and plain proto3 fields. + if (is_map() || real_containing_oneof() || + (is_optional() && !has_optional_keyword())) { + label.clear(); + } + + SourceLocationCommentPrinter comment_printer(this, prefix, + debug_string_options); + comment_printer.AddPreComment(contents); + + strings::SubstituteAndAppend( + contents, "$0$1$2 $3 = $4", prefix, label, field_type, + type() == TYPE_GROUP ? message_type()->name() : name(), number()); + + bool bracketed = false; + if (has_default_value()) { + bracketed = true; + strings::SubstituteAndAppend(contents, " [default = $0", + DefaultValueAsString(true)); + } + if (has_json_name_) { + if (!bracketed) { + bracketed = true; + contents->append(" ["); + } else { + contents->append(", "); + } + contents->append("json_name = \""); + contents->append(CEscape(json_name())); + contents->append("\""); + } + + std::string formatted_options; + if (FormatBracketedOptions(depth, options(), file()->pool(), + &formatted_options)) { + contents->append(bracketed ? ", " : " ["); + bracketed = true; + contents->append(formatted_options); + } + + if (bracketed) { + contents->append("]"); + } + + if (type() == TYPE_GROUP) { + if (debug_string_options.elide_group_body) { + contents->append(" { ... };\n"); + } else { + message_type()->DebugString(depth, contents, debug_string_options, + /* include_opening_clause */ false); + } + } else { + contents->append(";\n"); + } + + comment_printer.AddPostComment(contents); +} + +std::string OneofDescriptor::DebugString() const { + DebugStringOptions options; // default values + return DebugStringWithOptions(options); +} + +std::string OneofDescriptor::DebugStringWithOptions( + const DebugStringOptions& options) const { + std::string contents; + DebugString(0, &contents, options); + return contents; +} + +void OneofDescriptor::DebugString( + int depth, std::string* contents, + const DebugStringOptions& debug_string_options) const { + std::string prefix(depth * 2, ' '); + ++depth; + SourceLocationCommentPrinter comment_printer(this, prefix, + debug_string_options); + comment_printer.AddPreComment(contents); + strings::SubstituteAndAppend(contents, "$0oneof $1 {", prefix, name()); + + FormatLineOptions(depth, options(), containing_type()->file()->pool(), + contents); + + if (debug_string_options.elide_oneof_body) { + contents->append(" ... }\n"); + } else { + contents->append("\n"); + for (int i = 0; i < field_count(); i++) { + field(i)->DebugString(depth, contents, debug_string_options); + } + strings::SubstituteAndAppend(contents, "$0}\n", prefix); + } + comment_printer.AddPostComment(contents); +} + +std::string EnumDescriptor::DebugString() const { + DebugStringOptions options; // default values + return DebugStringWithOptions(options); +} + +std::string EnumDescriptor::DebugStringWithOptions( + const DebugStringOptions& options) const { + std::string contents; + DebugString(0, &contents, options); + return contents; +} + +void EnumDescriptor::DebugString( + int depth, std::string* contents, + const DebugStringOptions& debug_string_options) const { + std::string prefix(depth * 2, ' '); + ++depth; + + SourceLocationCommentPrinter comment_printer(this, prefix, + debug_string_options); + comment_printer.AddPreComment(contents); + + strings::SubstituteAndAppend(contents, "$0enum $1 {\n", prefix, name()); + + FormatLineOptions(depth, options(), file()->pool(), contents); + + for (int i = 0; i < value_count(); i++) { + value(i)->DebugString(depth, contents, debug_string_options); + } + + if (reserved_range_count() > 0) { + strings::SubstituteAndAppend(contents, "$0 reserved ", prefix); + for (int i = 0; i < reserved_range_count(); i++) { + const EnumDescriptor::ReservedRange* range = reserved_range(i); + if (range->end == range->start) { + strings::SubstituteAndAppend(contents, "$0, ", range->start); + } else if (range->end == INT_MAX) { + strings::SubstituteAndAppend(contents, "$0 to max, ", range->start); + } else { + strings::SubstituteAndAppend(contents, "$0 to $1, ", range->start, + range->end); + } + } + contents->replace(contents->size() - 2, 2, ";\n"); + } + + if (reserved_name_count() > 0) { + strings::SubstituteAndAppend(contents, "$0 reserved ", prefix); + for (int i = 0; i < reserved_name_count(); i++) { + strings::SubstituteAndAppend(contents, "\"$0\", ", + CEscape(reserved_name(i))); + } + contents->replace(contents->size() - 2, 2, ";\n"); + } + + strings::SubstituteAndAppend(contents, "$0}\n", prefix); + + comment_printer.AddPostComment(contents); +} + +std::string EnumValueDescriptor::DebugString() const { + DebugStringOptions options; // default values + return DebugStringWithOptions(options); +} + +std::string EnumValueDescriptor::DebugStringWithOptions( + const DebugStringOptions& options) const { + std::string contents; + DebugString(0, &contents, options); + return contents; +} + +void EnumValueDescriptor::DebugString( + int depth, std::string* contents, + const DebugStringOptions& debug_string_options) const { + std::string prefix(depth * 2, ' '); + + SourceLocationCommentPrinter comment_printer(this, prefix, + debug_string_options); + comment_printer.AddPreComment(contents); + + strings::SubstituteAndAppend(contents, "$0$1 = $2", prefix, name(), number()); + + std::string formatted_options; + if (FormatBracketedOptions(depth, options(), type()->file()->pool(), + &formatted_options)) { + strings::SubstituteAndAppend(contents, " [$0]", formatted_options); + } + contents->append(";\n"); + + comment_printer.AddPostComment(contents); +} + +std::string ServiceDescriptor::DebugString() const { + DebugStringOptions options; // default values + return DebugStringWithOptions(options); +} + +std::string ServiceDescriptor::DebugStringWithOptions( + const DebugStringOptions& options) const { + std::string contents; + DebugString(&contents, options); + return contents; +} + +void ServiceDescriptor::DebugString( + std::string* contents, + const DebugStringOptions& debug_string_options) const { + SourceLocationCommentPrinter comment_printer(this, /* prefix */ "", + debug_string_options); + comment_printer.AddPreComment(contents); + + strings::SubstituteAndAppend(contents, "service $0 {\n", name()); + + FormatLineOptions(1, options(), file()->pool(), contents); + + for (int i = 0; i < method_count(); i++) { + method(i)->DebugString(1, contents, debug_string_options); + } + + contents->append("}\n"); + + comment_printer.AddPostComment(contents); +} + +std::string MethodDescriptor::DebugString() const { + DebugStringOptions options; // default values + return DebugStringWithOptions(options); +} + +std::string MethodDescriptor::DebugStringWithOptions( + const DebugStringOptions& options) const { + std::string contents; + DebugString(0, &contents, options); + return contents; +} + +void MethodDescriptor::DebugString( + int depth, std::string* contents, + const DebugStringOptions& debug_string_options) const { + std::string prefix(depth * 2, ' '); + ++depth; + + SourceLocationCommentPrinter comment_printer(this, prefix, + debug_string_options); + comment_printer.AddPreComment(contents); + + strings::SubstituteAndAppend( + contents, "$0rpc $1($4.$2) returns ($5.$3)", prefix, name(), + input_type()->full_name(), output_type()->full_name(), + client_streaming() ? "stream " : "", server_streaming() ? "stream " : ""); + + std::string formatted_options; + if (FormatLineOptions(depth, options(), service()->file()->pool(), + &formatted_options)) { + strings::SubstituteAndAppend(contents, " {\n$0$1}\n", formatted_options, + prefix); + } else { + contents->append(";\n"); + } + + comment_printer.AddPostComment(contents); +} + +// Location methods =============================================== + +bool FileDescriptor::GetSourceLocation(const std::vector<int>& path, + SourceLocation* out_location) const { + GOOGLE_CHECK(out_location != nullptr); + if (source_code_info_) { + if (const SourceCodeInfo_Location* loc = + tables_->GetSourceLocation(path, source_code_info_)) { + const RepeatedField<int32_t>& span = loc->span(); + if (span.size() == 3 || span.size() == 4) { + out_location->start_line = span.Get(0); + out_location->start_column = span.Get(1); + out_location->end_line = span.Get(span.size() == 3 ? 0 : 2); + out_location->end_column = span.Get(span.size() - 1); + + out_location->leading_comments = loc->leading_comments(); + out_location->trailing_comments = loc->trailing_comments(); + out_location->leading_detached_comments.assign( + loc->leading_detached_comments().begin(), + loc->leading_detached_comments().end()); + return true; + } + } + } + return false; +} + +bool FileDescriptor::GetSourceLocation(SourceLocation* out_location) const { + std::vector<int> path; // empty path for root FileDescriptor + return GetSourceLocation(path, out_location); +} + +bool FieldDescriptor::is_packed() const { + if (!is_packable()) return false; + if (file_->syntax() == FileDescriptor::SYNTAX_PROTO2) { + return (options_ != nullptr) && options_->packed(); + } else { + return options_ == nullptr || !options_->has_packed() || options_->packed(); + } +} + +bool Descriptor::GetSourceLocation(SourceLocation* out_location) const { + std::vector<int> path; + GetLocationPath(&path); + return file()->GetSourceLocation(path, out_location); +} + +bool FieldDescriptor::GetSourceLocation(SourceLocation* out_location) const { + std::vector<int> path; + GetLocationPath(&path); + return file()->GetSourceLocation(path, out_location); +} + +bool OneofDescriptor::GetSourceLocation(SourceLocation* out_location) const { + std::vector<int> path; + GetLocationPath(&path); + return containing_type()->file()->GetSourceLocation(path, out_location); +} + +bool EnumDescriptor::GetSourceLocation(SourceLocation* out_location) const { + std::vector<int> path; + GetLocationPath(&path); + return file()->GetSourceLocation(path, out_location); +} + +bool MethodDescriptor::GetSourceLocation(SourceLocation* out_location) const { + std::vector<int> path; + GetLocationPath(&path); + return service()->file()->GetSourceLocation(path, out_location); +} + +bool ServiceDescriptor::GetSourceLocation(SourceLocation* out_location) const { + std::vector<int> path; + GetLocationPath(&path); + return file()->GetSourceLocation(path, out_location); +} + +bool EnumValueDescriptor::GetSourceLocation( + SourceLocation* out_location) const { + std::vector<int> path; + GetLocationPath(&path); + return type()->file()->GetSourceLocation(path, out_location); +} + +void Descriptor::GetLocationPath(std::vector<int>* output) const { + if (containing_type()) { + containing_type()->GetLocationPath(output); + output->push_back(DescriptorProto::kNestedTypeFieldNumber); + output->push_back(index()); + } else { + output->push_back(FileDescriptorProto::kMessageTypeFieldNumber); + output->push_back(index()); + } +} + +void FieldDescriptor::GetLocationPath(std::vector<int>* output) const { + if (is_extension()) { + if (extension_scope() == nullptr) { + output->push_back(FileDescriptorProto::kExtensionFieldNumber); + output->push_back(index()); + } else { + extension_scope()->GetLocationPath(output); + output->push_back(DescriptorProto::kExtensionFieldNumber); + output->push_back(index()); + } + } else { + containing_type()->GetLocationPath(output); + output->push_back(DescriptorProto::kFieldFieldNumber); + output->push_back(index()); + } +} + +void OneofDescriptor::GetLocationPath(std::vector<int>* output) const { + containing_type()->GetLocationPath(output); + output->push_back(DescriptorProto::kOneofDeclFieldNumber); + output->push_back(index()); +} + +void EnumDescriptor::GetLocationPath(std::vector<int>* output) const { + if (containing_type()) { + containing_type()->GetLocationPath(output); + output->push_back(DescriptorProto::kEnumTypeFieldNumber); + output->push_back(index()); + } else { + output->push_back(FileDescriptorProto::kEnumTypeFieldNumber); + output->push_back(index()); + } +} + +void EnumValueDescriptor::GetLocationPath(std::vector<int>* output) const { + type()->GetLocationPath(output); + output->push_back(EnumDescriptorProto::kValueFieldNumber); + output->push_back(index()); +} + +void ServiceDescriptor::GetLocationPath(std::vector<int>* output) const { + output->push_back(FileDescriptorProto::kServiceFieldNumber); + output->push_back(index()); +} + +void MethodDescriptor::GetLocationPath(std::vector<int>* output) const { + service()->GetLocationPath(output); + output->push_back(ServiceDescriptorProto::kMethodFieldNumber); + output->push_back(index()); +} + +// =================================================================== + +namespace { + +// Represents an options message to interpret. Extension names in the option +// name are resolved relative to name_scope. element_name and orig_opt are +// used only for error reporting (since the parser records locations against +// pointers in the original options, not the mutable copy). The Message must be +// one of the Options messages in descriptor.proto. +struct OptionsToInterpret { + OptionsToInterpret(const std::string& ns, const std::string& el, + const std::vector<int>& path, const Message* orig_opt, + Message* opt) + : name_scope(ns), + element_name(el), + element_path(path), + original_options(orig_opt), + options(opt) {} + std::string name_scope; + std::string element_name; + std::vector<int> element_path; + const Message* original_options; + Message* options; +}; + +} // namespace + +class DescriptorBuilder { + public: + DescriptorBuilder(const DescriptorPool* pool, DescriptorPool::Tables* tables, + DescriptorPool::ErrorCollector* error_collector); + ~DescriptorBuilder(); + + const FileDescriptor* BuildFile(const FileDescriptorProto& proto); + + private: + friend class OptionInterpreter; + + // Non-recursive part of BuildFile functionality. + FileDescriptor* BuildFileImpl(const FileDescriptorProto& proto, + internal::FlatAllocator& alloc); + + const DescriptorPool* pool_; + DescriptorPool::Tables* tables_; // for convenience + DescriptorPool::ErrorCollector* error_collector_; + + // As we build descriptors we store copies of the options messages in + // them. We put pointers to those copies in this vector, as we build, so we + // can later (after cross-linking) interpret those options. + std::vector<OptionsToInterpret> options_to_interpret_; + + bool had_errors_; + std::string filename_; + FileDescriptor* file_; + FileDescriptorTables* file_tables_; + std::set<const FileDescriptor*> dependencies_; + + struct MessageHints { + int fields_to_suggest = 0; + const Message* first_reason = nullptr; + DescriptorPool::ErrorCollector::ErrorLocation first_reason_location = + DescriptorPool::ErrorCollector::ErrorLocation::OTHER; + + void RequestHintOnFieldNumbers( + const Message& reason, + DescriptorPool::ErrorCollector::ErrorLocation reason_location, + int range_start = 0, int range_end = 1) { + auto fit = [](int value) { + return std::min(std::max(value, 0), FieldDescriptor::kMaxNumber); + }; + fields_to_suggest = + fit(fields_to_suggest + fit(fit(range_end) - fit(range_start))); + if (first_reason) return; + first_reason = &reason; + first_reason_location = reason_location; + } + }; + + std::unordered_map<const Descriptor*, MessageHints> message_hints_; + + // unused_dependency_ is used to record the unused imported files. + // Note: public import is not considered. + std::set<const FileDescriptor*> unused_dependency_; + + // If LookupSymbol() finds a symbol that is in a file which is not a declared + // dependency of this file, it will fail, but will set + // possible_undeclared_dependency_ to point at that file. This is only used + // by AddNotDefinedError() to report a more useful error message. + // possible_undeclared_dependency_name_ is the name of the symbol that was + // actually found in possible_undeclared_dependency_, which may be a parent + // of the symbol actually looked for. + const FileDescriptor* possible_undeclared_dependency_; + std::string possible_undeclared_dependency_name_; + + // If LookupSymbol() could resolve a symbol which is not defined, + // record the resolved name. This is only used by AddNotDefinedError() + // to report a more useful error message. + std::string undefine_resolved_name_; + + // Tracker for current recursion depth to implement recursion protection. + // + // Counts down to 0 when there is no depth remaining. + // + // Maximum recursion depth corresponds to 32 nested message declarations. + int recursion_depth_ = 32; + + void AddError(const std::string& element_name, const Message& descriptor, + DescriptorPool::ErrorCollector::ErrorLocation location, + const std::string& error); + void AddError(const std::string& element_name, const Message& descriptor, + DescriptorPool::ErrorCollector::ErrorLocation location, + const char* error); + void AddRecursiveImportError(const FileDescriptorProto& proto, int from_here); + void AddTwiceListedError(const FileDescriptorProto& proto, int index); + void AddImportError(const FileDescriptorProto& proto, int index); + + // Adds an error indicating that undefined_symbol was not defined. Must + // only be called after LookupSymbol() fails. + void AddNotDefinedError( + const std::string& element_name, const Message& descriptor, + DescriptorPool::ErrorCollector::ErrorLocation location, + const std::string& undefined_symbol); + + void AddWarning(const std::string& element_name, const Message& descriptor, + DescriptorPool::ErrorCollector::ErrorLocation location, + const std::string& error); + + // Silly helper which determines if the given file is in the given package. + // I.e., either file->package() == package_name or file->package() is a + // nested package within package_name. + bool IsInPackage(const FileDescriptor* file, const std::string& package_name); + + // Helper function which finds all public dependencies of the given file, and + // stores the them in the dependencies_ set in the builder. + void RecordPublicDependencies(const FileDescriptor* file); + + // Like tables_->FindSymbol(), but additionally: + // - Search the pool's underlay if not found in tables_. + // - Insure that the resulting Symbol is from one of the file's declared + // dependencies. + Symbol FindSymbol(const std::string& name, bool build_it = true); + + // Like FindSymbol() but does not require that the symbol is in one of the + // file's declared dependencies. + Symbol FindSymbolNotEnforcingDeps(const std::string& name, + bool build_it = true); + + // This implements the body of FindSymbolNotEnforcingDeps(). + Symbol FindSymbolNotEnforcingDepsHelper(const DescriptorPool* pool, + const std::string& name, + bool build_it = true); + + // Like FindSymbol(), but looks up the name relative to some other symbol + // name. This first searches siblings of relative_to, then siblings of its + // parents, etc. For example, LookupSymbol("foo.bar", "baz.moo.corge") makes + // the following calls, returning the first non-null result: + // FindSymbol("baz.moo.foo.bar"), FindSymbol("baz.foo.bar"), + // FindSymbol("foo.bar"). If AllowUnknownDependencies() has been called + // on the DescriptorPool, this will generate a placeholder type if + // the name is not found (unless the name itself is malformed). The + // placeholder_type parameter indicates what kind of placeholder should be + // constructed in this case. The resolve_mode parameter determines whether + // any symbol is returned, or only symbols that are types. Note, however, + // that LookupSymbol may still return a non-type symbol in LOOKUP_TYPES mode, + // if it believes that's all it could refer to. The caller should always + // check that it receives the type of symbol it was expecting. + enum ResolveMode { LOOKUP_ALL, LOOKUP_TYPES }; + Symbol LookupSymbol(const std::string& name, const std::string& relative_to, + DescriptorPool::PlaceholderType placeholder_type = + DescriptorPool::PLACEHOLDER_MESSAGE, + ResolveMode resolve_mode = LOOKUP_ALL, + bool build_it = true); + + // Like LookupSymbol() but will not return a placeholder even if + // AllowUnknownDependencies() has been used. + Symbol LookupSymbolNoPlaceholder(const std::string& name, + const std::string& relative_to, + ResolveMode resolve_mode = LOOKUP_ALL, + bool build_it = true); + + // Calls tables_->AddSymbol() and records an error if it fails. Returns + // true if successful or false if failed, though most callers can ignore + // the return value since an error has already been recorded. + bool AddSymbol(const std::string& full_name, const void* parent, + const std::string& name, const Message& proto, Symbol symbol); + + // Like AddSymbol(), but succeeds if the symbol is already defined as long + // as the existing definition is also a package (because it's OK to define + // the same package in two different files). Also adds all parents of the + // package to the symbol table (e.g. AddPackage("foo.bar", ...) will add + // "foo.bar" and "foo" to the table). + void AddPackage(const std::string& name, const Message& proto, + FileDescriptor* file); + + // Checks that the symbol name contains only alphanumeric characters and + // underscores. Records an error otherwise. + void ValidateSymbolName(const std::string& name, const std::string& full_name, + const Message& proto); + + // Allocates a copy of orig_options in tables_ and stores it in the + // descriptor. Remembers its uninterpreted options, to be interpreted + // later. DescriptorT must be one of the Descriptor messages from + // descriptor.proto. + template <class DescriptorT> + void AllocateOptions(const typename DescriptorT::OptionsType& orig_options, + DescriptorT* descriptor, int options_field_tag, + const std::string& option_name, + internal::FlatAllocator& alloc); + // Specialization for FileOptions. + void AllocateOptions(const FileOptions& orig_options, + FileDescriptor* descriptor, + internal::FlatAllocator& alloc); + + // Implementation for AllocateOptions(). Don't call this directly. + template <class DescriptorT> + void AllocateOptionsImpl( + const std::string& name_scope, const std::string& element_name, + const typename DescriptorT::OptionsType& orig_options, + DescriptorT* descriptor, const std::vector<int>& options_path, + const std::string& option_name, internal::FlatAllocator& alloc); + + // Allocates an array of two strings, the first one is a copy of `proto_name`, + // and the second one is the full name. + // Full proto name is "scope.proto_name" if scope is non-empty and + // "proto_name" otherwise. + const std::string* AllocateNameStrings(const std::string& scope, + const std::string& proto_name, + internal::FlatAllocator& alloc); + + // These methods all have the same signature for the sake of the BUILD_ARRAY + // macro, below. + void BuildMessage(const DescriptorProto& proto, const Descriptor* parent, + Descriptor* result, internal::FlatAllocator& alloc); + void BuildFieldOrExtension(const FieldDescriptorProto& proto, + Descriptor* parent, FieldDescriptor* result, + bool is_extension, internal::FlatAllocator& alloc); + void BuildField(const FieldDescriptorProto& proto, Descriptor* parent, + FieldDescriptor* result, internal::FlatAllocator& alloc) { + BuildFieldOrExtension(proto, parent, result, false, alloc); + } + void BuildExtension(const FieldDescriptorProto& proto, Descriptor* parent, + FieldDescriptor* result, internal::FlatAllocator& alloc) { + BuildFieldOrExtension(proto, parent, result, true, alloc); + } + void BuildExtensionRange(const DescriptorProto::ExtensionRange& proto, + const Descriptor* parent, + Descriptor::ExtensionRange* result, + internal::FlatAllocator& alloc); + void BuildReservedRange(const DescriptorProto::ReservedRange& proto, + const Descriptor* parent, + Descriptor::ReservedRange* result, + internal::FlatAllocator& alloc); + void BuildReservedRange(const EnumDescriptorProto::EnumReservedRange& proto, + const EnumDescriptor* parent, + EnumDescriptor::ReservedRange* result, + internal::FlatAllocator& alloc); + void BuildOneof(const OneofDescriptorProto& proto, Descriptor* parent, + OneofDescriptor* result, internal::FlatAllocator& alloc); + void CheckEnumValueUniqueness(const EnumDescriptorProto& proto, + const EnumDescriptor* result); + void BuildEnum(const EnumDescriptorProto& proto, const Descriptor* parent, + EnumDescriptor* result, internal::FlatAllocator& alloc); + void BuildEnumValue(const EnumValueDescriptorProto& proto, + const EnumDescriptor* parent, EnumValueDescriptor* result, + internal::FlatAllocator& alloc); + void BuildService(const ServiceDescriptorProto& proto, const void* dummy, + ServiceDescriptor* result, internal::FlatAllocator& alloc); + void BuildMethod(const MethodDescriptorProto& proto, + const ServiceDescriptor* parent, MethodDescriptor* result, + internal::FlatAllocator& alloc); + + void LogUnusedDependency(const FileDescriptorProto& proto, + const FileDescriptor* result); + + // Must be run only after building. + // + // NOTE: Options will not be available during cross-linking, as they + // have not yet been interpreted. Defer any handling of options to the + // Validate*Options methods. + void CrossLinkFile(FileDescriptor* file, const FileDescriptorProto& proto); + void CrossLinkMessage(Descriptor* message, const DescriptorProto& proto); + void CrossLinkField(FieldDescriptor* field, + const FieldDescriptorProto& proto); + void CrossLinkExtensionRange(Descriptor::ExtensionRange* range, + const DescriptorProto::ExtensionRange& proto); + void CrossLinkEnum(EnumDescriptor* enum_type, + const EnumDescriptorProto& proto); + void CrossLinkEnumValue(EnumValueDescriptor* enum_value, + const EnumValueDescriptorProto& proto); + void CrossLinkService(ServiceDescriptor* service, + const ServiceDescriptorProto& proto); + void CrossLinkMethod(MethodDescriptor* method, + const MethodDescriptorProto& proto); + void SuggestFieldNumbers(FileDescriptor* file, + const FileDescriptorProto& proto); + + // Must be run only after cross-linking. + void InterpretOptions(); + + // A helper class for interpreting options. + class OptionInterpreter { + public: + // Creates an interpreter that operates in the context of the pool of the + // specified builder, which must not be nullptr. We don't take ownership of + // the builder. + explicit OptionInterpreter(DescriptorBuilder* builder); + + ~OptionInterpreter(); + + // Interprets the uninterpreted options in the specified Options message. + // On error, calls AddError() on the underlying builder and returns false. + // Otherwise returns true. + bool InterpretOptions(OptionsToInterpret* options_to_interpret); + + // Updates the given source code info by re-writing uninterpreted option + // locations to refer to the corresponding interpreted option. + void UpdateSourceCodeInfo(SourceCodeInfo* info); + + class AggregateOptionFinder; + + private: + // Interprets uninterpreted_option_ on the specified message, which + // must be the mutable copy of the original options message to which + // uninterpreted_option_ belongs. The given src_path is the source + // location path to the uninterpreted option, and options_path is the + // source location path to the options message. The location paths are + // recorded and then used in UpdateSourceCodeInfo. + bool InterpretSingleOption(Message* options, + const std::vector<int>& src_path, + const std::vector<int>& options_path); + + // Adds the uninterpreted_option to the given options message verbatim. + // Used when AllowUnknownDependencies() is in effect and we can't find + // the option's definition. + void AddWithoutInterpreting(const UninterpretedOption& uninterpreted_option, + Message* options); + + // A recursive helper function that drills into the intermediate fields + // in unknown_fields to check if field innermost_field is set on the + // innermost message. Returns false and sets an error if so. + bool ExamineIfOptionIsSet( + std::vector<const FieldDescriptor*>::const_iterator + intermediate_fields_iter, + std::vector<const FieldDescriptor*>::const_iterator + intermediate_fields_end, + const FieldDescriptor* innermost_field, + const std::string& debug_msg_name, + const UnknownFieldSet& unknown_fields); + + // Validates the value for the option field of the currently interpreted + // option and then sets it on the unknown_field. + bool SetOptionValue(const FieldDescriptor* option_field, + UnknownFieldSet* unknown_fields); + + // Parses an aggregate value for a CPPTYPE_MESSAGE option and + // saves it into *unknown_fields. + bool SetAggregateOption(const FieldDescriptor* option_field, + UnknownFieldSet* unknown_fields); + + // Convenience functions to set an int field the right way, depending on + // its wire type (a single int CppType can represent multiple wire types). + void SetInt32(int number, int32_t value, FieldDescriptor::Type type, + UnknownFieldSet* unknown_fields); + void SetInt64(int number, int64_t value, FieldDescriptor::Type type, + UnknownFieldSet* unknown_fields); + void SetUInt32(int number, uint32_t value, FieldDescriptor::Type type, + UnknownFieldSet* unknown_fields); + void SetUInt64(int number, uint64_t value, FieldDescriptor::Type type, + UnknownFieldSet* unknown_fields); + + // A helper function that adds an error at the specified location of the + // option we're currently interpreting, and returns false. + bool AddOptionError(DescriptorPool::ErrorCollector::ErrorLocation location, + const std::string& msg) { + builder_->AddError(options_to_interpret_->element_name, + *uninterpreted_option_, location, msg); + return false; + } + + // A helper function that adds an error at the location of the option name + // and returns false. + bool AddNameError(const std::string& msg) { +#ifdef PROTOBUF_INTERNAL_IGNORE_FIELD_NAME_ERRORS_ + return true; +#else // PROTOBUF_INTERNAL_IGNORE_FIELD_NAME_ERRORS_ + return AddOptionError(DescriptorPool::ErrorCollector::OPTION_NAME, msg); +#endif // PROTOBUF_INTERNAL_IGNORE_FIELD_NAME_ERRORS_ + } + + // A helper function that adds an error at the location of the option name + // and returns false. + bool AddValueError(const std::string& msg) { + return AddOptionError(DescriptorPool::ErrorCollector::OPTION_VALUE, msg); + } + + // We interpret against this builder's pool. Is never nullptr. We don't own + // this pointer. + DescriptorBuilder* builder_; + + // The options we're currently interpreting, or nullptr if we're not in a + // call to InterpretOptions. + const OptionsToInterpret* options_to_interpret_; + + // The option we're currently interpreting within options_to_interpret_, or + // nullptr if we're not in a call to InterpretOptions(). This points to a + // submessage of the original option, not the mutable copy. Therefore we + // can use it to find locations recorded by the parser. + const UninterpretedOption* uninterpreted_option_; + + // This maps the element path of uninterpreted options to the element path + // of the resulting interpreted option. This is used to modify a file's + // source code info to account for option interpretation. + std::map<std::vector<int>, std::vector<int>> interpreted_paths_; + + // This maps the path to a repeated option field to the known number of + // elements the field contains. This is used to track the compute the + // index portion of the element path when interpreting a single option. + std::map<std::vector<int>, int> repeated_option_counts_; + + // Factory used to create the dynamic messages we need to parse + // any aggregate option values we encounter. + DynamicMessageFactory dynamic_factory_; + + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(OptionInterpreter); + }; + + // Work-around for broken compilers: According to the C++ standard, + // OptionInterpreter should have access to the private members of any class + // which has declared DescriptorBuilder as a friend. Unfortunately some old + // versions of GCC and other compilers do not implement this correctly. So, + // we have to have these intermediate methods to provide access. We also + // redundantly declare OptionInterpreter a friend just to make things extra + // clear for these bad compilers. + friend class OptionInterpreter; + friend class OptionInterpreter::AggregateOptionFinder; + + static inline bool get_allow_unknown(const DescriptorPool* pool) { + return pool->allow_unknown_; + } + static inline bool get_enforce_weak(const DescriptorPool* pool) { + return pool->enforce_weak_; + } + static inline bool get_is_placeholder(const Descriptor* descriptor) { + return descriptor != nullptr && descriptor->is_placeholder_; + } + static inline void assert_mutex_held(const DescriptorPool* pool) { + if (pool->mutex_ != nullptr) { + pool->mutex_->AssertHeld(); + } + } + + // Must be run only after options have been interpreted. + // + // NOTE: Validation code must only reference the options in the mutable + // descriptors, which are the ones that have been interpreted. The const + // proto references are passed in only so they can be provided to calls to + // AddError(). Do not look at their options, which have not been interpreted. + void ValidateFileOptions(FileDescriptor* file, + const FileDescriptorProto& proto); + void ValidateMessageOptions(Descriptor* message, + const DescriptorProto& proto); + void ValidateFieldOptions(FieldDescriptor* field, + const FieldDescriptorProto& proto); + void ValidateEnumOptions(EnumDescriptor* enm, + const EnumDescriptorProto& proto); + void ValidateEnumValueOptions(EnumValueDescriptor* enum_value, + const EnumValueDescriptorProto& proto); + void ValidateExtensionRangeOptions( + const std::string& full_name, Descriptor::ExtensionRange* extension_range, + const DescriptorProto_ExtensionRange& proto); + void ValidateServiceOptions(ServiceDescriptor* service, + const ServiceDescriptorProto& proto); + void ValidateMethodOptions(MethodDescriptor* method, + const MethodDescriptorProto& proto); + void ValidateProto3(FileDescriptor* file, const FileDescriptorProto& proto); + void ValidateProto3Message(Descriptor* message, const DescriptorProto& proto); + void ValidateProto3Field(FieldDescriptor* field, + const FieldDescriptorProto& proto); + void ValidateProto3Enum(EnumDescriptor* enm, + const EnumDescriptorProto& proto); + + // Returns true if the map entry message is compatible with the + // auto-generated entry message from map fields syntax. + bool ValidateMapEntry(FieldDescriptor* field, + const FieldDescriptorProto& proto); + + // Recursively detects naming conflicts with map entry types for a + // better error message. + void DetectMapConflicts(const Descriptor* message, + const DescriptorProto& proto); + + void ValidateJSType(FieldDescriptor* field, + const FieldDescriptorProto& proto); +}; + +const FileDescriptor* DescriptorPool::BuildFile( + const FileDescriptorProto& proto) { + GOOGLE_CHECK(fallback_database_ == nullptr) + << "Cannot call BuildFile on a DescriptorPool that uses a " + "DescriptorDatabase. You must instead find a way to get your file " + "into the underlying database."; + GOOGLE_CHECK(mutex_ == nullptr); // Implied by the above GOOGLE_CHECK. + tables_->known_bad_symbols_.clear(); + tables_->known_bad_files_.clear(); + return DescriptorBuilder(this, tables_.get(), nullptr).BuildFile(proto); +} + +const FileDescriptor* DescriptorPool::BuildFileCollectingErrors( + const FileDescriptorProto& proto, ErrorCollector* error_collector) { + GOOGLE_CHECK(fallback_database_ == nullptr) + << "Cannot call BuildFile on a DescriptorPool that uses a " + "DescriptorDatabase. You must instead find a way to get your file " + "into the underlying database."; + GOOGLE_CHECK(mutex_ == nullptr); // Implied by the above GOOGLE_CHECK. + tables_->known_bad_symbols_.clear(); + tables_->known_bad_files_.clear(); + return DescriptorBuilder(this, tables_.get(), error_collector) + .BuildFile(proto); +} + +const FileDescriptor* DescriptorPool::BuildFileFromDatabase( + const FileDescriptorProto& proto) const { + mutex_->AssertHeld(); + if (tables_->known_bad_files_.count(proto.name()) > 0) { + return nullptr; + } + const FileDescriptor* result = + DescriptorBuilder(this, tables_.get(), default_error_collector_) + .BuildFile(proto); + if (result == nullptr) { + tables_->known_bad_files_.insert(proto.name()); + } + return result; +} + +DescriptorBuilder::DescriptorBuilder( + const DescriptorPool* pool, DescriptorPool::Tables* tables, + DescriptorPool::ErrorCollector* error_collector) + : pool_(pool), + tables_(tables), + error_collector_(error_collector), + had_errors_(false), + possible_undeclared_dependency_(nullptr), + undefine_resolved_name_("") {} + +DescriptorBuilder::~DescriptorBuilder() {} + +void DescriptorBuilder::AddError( + const std::string& element_name, const Message& descriptor, + DescriptorPool::ErrorCollector::ErrorLocation location, + const std::string& error) { + if (error_collector_ == nullptr) { + if (!had_errors_) { + GOOGLE_LOG(ERROR) << "Invalid proto descriptor for file \"" << filename_ + << "\":"; + } + GOOGLE_LOG(ERROR) << " " << element_name << ": " << error; + } else { + error_collector_->AddError(filename_, element_name, &descriptor, location, + error); + } + had_errors_ = true; +} + +void DescriptorBuilder::AddError( + const std::string& element_name, const Message& descriptor, + DescriptorPool::ErrorCollector::ErrorLocation location, const char* error) { + AddError(element_name, descriptor, location, std::string(error)); +} + +void DescriptorBuilder::AddNotDefinedError( + const std::string& element_name, const Message& descriptor, + DescriptorPool::ErrorCollector::ErrorLocation location, + const std::string& undefined_symbol) { + if (possible_undeclared_dependency_ == nullptr && + undefine_resolved_name_.empty()) { + AddError(element_name, descriptor, location, + "\"" + undefined_symbol + "\" is not defined."); + } else { + if (possible_undeclared_dependency_ != nullptr) { + AddError(element_name, descriptor, location, + "\"" + possible_undeclared_dependency_name_ + + "\" seems to be defined in \"" + + possible_undeclared_dependency_->name() + + "\", which is not " + "imported by \"" + + filename_ + + "\". To use it here, please " + "add the necessary import."); + } + if (!undefine_resolved_name_.empty()) { + AddError(element_name, descriptor, location, + "\"" + undefined_symbol + "\" is resolved to \"" + + undefine_resolved_name_ + + "\", which is not defined. " + "The innermost scope is searched first in name resolution. " + "Consider using a leading '.'(i.e., \"." + + undefined_symbol + "\") to start from the outermost scope."); + } + } +} + +void DescriptorBuilder::AddWarning( + const std::string& element_name, const Message& descriptor, + DescriptorPool::ErrorCollector::ErrorLocation location, + const std::string& error) { + if (error_collector_ == nullptr) { + GOOGLE_LOG(WARNING) << filename_ << " " << element_name << ": " << error; + } else { + error_collector_->AddWarning(filename_, element_name, &descriptor, location, + error); + } +} + +bool DescriptorBuilder::IsInPackage(const FileDescriptor* file, + const std::string& package_name) { + return HasPrefixString(file->package(), package_name) && + (file->package().size() == package_name.size() || + file->package()[package_name.size()] == '.'); +} + +void DescriptorBuilder::RecordPublicDependencies(const FileDescriptor* file) { + if (file == nullptr || !dependencies_.insert(file).second) return; + for (int i = 0; file != nullptr && i < file->public_dependency_count(); i++) { + RecordPublicDependencies(file->public_dependency(i)); + } +} + +Symbol DescriptorBuilder::FindSymbolNotEnforcingDepsHelper( + const DescriptorPool* pool, const std::string& name, bool build_it) { + // If we are looking at an underlay, we must lock its mutex_, since we are + // accessing the underlay's tables_ directly. + MutexLockMaybe lock((pool == pool_) ? nullptr : pool->mutex_); + + Symbol result = pool->tables_->FindSymbol(name); + if (result.IsNull() && pool->underlay_ != nullptr) { + // Symbol not found; check the underlay. + result = FindSymbolNotEnforcingDepsHelper(pool->underlay_, name); + } + + if (result.IsNull()) { + // With lazily_build_dependencies_, a symbol lookup at cross link time is + // not guaranteed to be successful. In most cases, build_it will be false, + // which intentionally prevents us from building an import until it's + // actually needed. In some cases, like registering an extension, we want + // to build the file containing the symbol, and build_it will be set. + // Also, build_it will be true when !lazily_build_dependencies_, to provide + // better error reporting of missing dependencies. + if (build_it && pool->TryFindSymbolInFallbackDatabase(name)) { + result = pool->tables_->FindSymbol(name); + } + } + + return result; +} + +Symbol DescriptorBuilder::FindSymbolNotEnforcingDeps(const std::string& name, + bool build_it) { + Symbol result = FindSymbolNotEnforcingDepsHelper(pool_, name, build_it); + // Only find symbols which were defined in this file or one of its + // dependencies. + const FileDescriptor* file = result.GetFile(); + if (file == file_ || dependencies_.count(file) > 0) { + unused_dependency_.erase(file); + } + return result; +} + +Symbol DescriptorBuilder::FindSymbol(const std::string& name, bool build_it) { + Symbol result = FindSymbolNotEnforcingDeps(name, build_it); + + if (result.IsNull()) return result; + + if (!pool_->enforce_dependencies_) { + // Hack for CompilerUpgrader, and also used for lazily_build_dependencies_ + return result; + } + + // Only find symbols which were defined in this file or one of its + // dependencies. + const FileDescriptor* file = result.GetFile(); + if (file == file_ || dependencies_.count(file) > 0) { + return result; + } + + if (result.IsPackage()) { + // Arg, this is overcomplicated. The symbol is a package name. It could + // be that the package was defined in multiple files. result.GetFile() + // returns the first file we saw that used this package. We've determined + // that that file is not a direct dependency of the file we are currently + // building, but it could be that some other file which *is* a direct + // dependency also defines the same package. We can't really rule out this + // symbol unless none of the dependencies define it. + if (IsInPackage(file_, name)) return result; + for (std::set<const FileDescriptor*>::const_iterator it = + dependencies_.begin(); + it != dependencies_.end(); ++it) { + // Note: A dependency may be nullptr if it was not found or had errors. + if (*it != nullptr && IsInPackage(*it, name)) return result; + } + } + + possible_undeclared_dependency_ = file; + possible_undeclared_dependency_name_ = name; + return Symbol(); +} + +Symbol DescriptorBuilder::LookupSymbolNoPlaceholder( + const std::string& name, const std::string& relative_to, + ResolveMode resolve_mode, bool build_it) { + possible_undeclared_dependency_ = nullptr; + undefine_resolved_name_.clear(); + + if (!name.empty() && name[0] == '.') { + // Fully-qualified name. + return FindSymbol(name.substr(1), build_it); + } + + // If name is something like "Foo.Bar.baz", and symbols named "Foo" are + // defined in multiple parent scopes, we only want to find "Bar.baz" in the + // innermost one. E.g., the following should produce an error: + // message Bar { message Baz {} } + // message Foo { + // message Bar { + // } + // optional Bar.Baz baz = 1; + // } + // So, we look for just "Foo" first, then look for "Bar.baz" within it if + // found. + std::string::size_type name_dot_pos = name.find_first_of('.'); + std::string first_part_of_name; + if (name_dot_pos == std::string::npos) { + first_part_of_name = name; + } else { + first_part_of_name = name.substr(0, name_dot_pos); + } + + std::string scope_to_try(relative_to); + + while (true) { + // Chop off the last component of the scope. + std::string::size_type dot_pos = scope_to_try.find_last_of('.'); + if (dot_pos == std::string::npos) { + return FindSymbol(name, build_it); + } else { + scope_to_try.erase(dot_pos); + } + + // Append ".first_part_of_name" and try to find. + std::string::size_type old_size = scope_to_try.size(); + scope_to_try.append(1, '.'); + scope_to_try.append(first_part_of_name); + Symbol result = FindSymbol(scope_to_try, build_it); + if (!result.IsNull()) { + if (first_part_of_name.size() < name.size()) { + // name is a compound symbol, of which we only found the first part. + // Now try to look up the rest of it. + if (result.IsAggregate()) { + scope_to_try.append(name, first_part_of_name.size(), + name.size() - first_part_of_name.size()); + result = FindSymbol(scope_to_try, build_it); + if (result.IsNull()) { + undefine_resolved_name_ = scope_to_try; + } + return result; + } else { + // We found a symbol but it's not an aggregate. Continue the loop. + } + } else { + if (resolve_mode == LOOKUP_TYPES && !result.IsType()) { + // We found a symbol but it's not a type. Continue the loop. + } else { + return result; + } + } + } + + // Not found. Remove the name so we can try again. + scope_to_try.erase(old_size); + } +} + +Symbol DescriptorBuilder::LookupSymbol( + const std::string& name, const std::string& relative_to, + DescriptorPool::PlaceholderType placeholder_type, ResolveMode resolve_mode, + bool build_it) { + Symbol result = + LookupSymbolNoPlaceholder(name, relative_to, resolve_mode, build_it); + if (result.IsNull() && pool_->allow_unknown_) { + // Not found, but AllowUnknownDependencies() is enabled. Return a + // placeholder instead. + result = pool_->NewPlaceholderWithMutexHeld(name, placeholder_type); + } + return result; +} + +static bool ValidateQualifiedName(StringPiece name) { + bool last_was_period = false; + + for (char character : name) { + // I don't trust isalnum() due to locales. :( + if (('a' <= character && character <= 'z') || + ('A' <= character && character <= 'Z') || + ('0' <= character && character <= '9') || (character == '_')) { + last_was_period = false; + } else if (character == '.') { + if (last_was_period) return false; + last_was_period = true; + } else { + return false; + } + } + + return !name.empty() && !last_was_period; +} + +Symbol DescriptorPool::NewPlaceholder(StringPiece name, + PlaceholderType placeholder_type) const { + MutexLockMaybe lock(mutex_); + return NewPlaceholderWithMutexHeld(name, placeholder_type); +} + +Symbol DescriptorPool::NewPlaceholderWithMutexHeld( + StringPiece name, PlaceholderType placeholder_type) const { + if (mutex_) { + mutex_->AssertHeld(); + } + // Compute names. + StringPiece placeholder_full_name; + StringPiece placeholder_name; + const std::string* placeholder_package; + + if (!ValidateQualifiedName(name)) return Symbol(); + if (name[0] == '.') { + // Fully-qualified. + placeholder_full_name = name.substr(1); + } else { + placeholder_full_name = name; + } + + // Create the placeholders. + internal::FlatAllocator alloc; + alloc.PlanArray<FileDescriptor>(1); + alloc.PlanArray<std::string>(2); + if (placeholder_type == PLACEHOLDER_ENUM) { + alloc.PlanArray<EnumDescriptor>(1); + alloc.PlanArray<EnumValueDescriptor>(1); + alloc.PlanArray<std::string>(2); // names for the descriptor. + alloc.PlanArray<std::string>(2); // names for the value. + } else { + alloc.PlanArray<Descriptor>(1); + alloc.PlanArray<std::string>(2); // names for the descriptor. + if (placeholder_type == PLACEHOLDER_EXTENDABLE_MESSAGE) { + alloc.PlanArray<Descriptor::ExtensionRange>(1); + } + } + alloc.FinalizePlanning(tables_); + + const std::string::size_type dotpos = placeholder_full_name.find_last_of('.'); + if (dotpos != std::string::npos) { + placeholder_package = + alloc.AllocateStrings(placeholder_full_name.substr(0, dotpos)); + placeholder_name = placeholder_full_name.substr(dotpos + 1); + } else { + placeholder_package = alloc.AllocateStrings(""); + placeholder_name = placeholder_full_name; + } + + FileDescriptor* placeholder_file = NewPlaceholderFileWithMutexHeld( + StrCat(placeholder_full_name, ".placeholder.proto"), alloc); + placeholder_file->package_ = placeholder_package; + + if (placeholder_type == PLACEHOLDER_ENUM) { + placeholder_file->enum_type_count_ = 1; + placeholder_file->enum_types_ = alloc.AllocateArray<EnumDescriptor>(1); + + EnumDescriptor* placeholder_enum = &placeholder_file->enum_types_[0]; + memset(static_cast<void*>(placeholder_enum), 0, sizeof(*placeholder_enum)); + + placeholder_enum->all_names_ = + alloc.AllocateStrings(placeholder_name, placeholder_full_name); + placeholder_enum->file_ = placeholder_file; + placeholder_enum->options_ = &EnumOptions::default_instance(); + placeholder_enum->is_placeholder_ = true; + placeholder_enum->is_unqualified_placeholder_ = (name[0] != '.'); + + // Enums must have at least one value. + placeholder_enum->value_count_ = 1; + placeholder_enum->values_ = alloc.AllocateArray<EnumValueDescriptor>(1); + // Disable fast-path lookup for this enum. + placeholder_enum->sequential_value_limit_ = -1; + + EnumValueDescriptor* placeholder_value = &placeholder_enum->values_[0]; + memset(static_cast<void*>(placeholder_value), 0, + sizeof(*placeholder_value)); + + // Note that enum value names are siblings of their type, not children. + placeholder_value->all_names_ = alloc.AllocateStrings( + "PLACEHOLDER_VALUE", placeholder_package->empty() + ? "PLACEHOLDER_VALUE" + : *placeholder_package + ".PLACEHOLDER_VALUE"); + + placeholder_value->number_ = 0; + placeholder_value->type_ = placeholder_enum; + placeholder_value->options_ = &EnumValueOptions::default_instance(); + + return Symbol(placeholder_enum); + } else { + placeholder_file->message_type_count_ = 1; + placeholder_file->message_types_ = alloc.AllocateArray<Descriptor>(1); + + Descriptor* placeholder_message = &placeholder_file->message_types_[0]; + memset(static_cast<void*>(placeholder_message), 0, + sizeof(*placeholder_message)); + + placeholder_message->all_names_ = + alloc.AllocateStrings(placeholder_name, placeholder_full_name); + placeholder_message->file_ = placeholder_file; + placeholder_message->options_ = &MessageOptions::default_instance(); + placeholder_message->is_placeholder_ = true; + placeholder_message->is_unqualified_placeholder_ = (name[0] != '.'); + + if (placeholder_type == PLACEHOLDER_EXTENDABLE_MESSAGE) { + placeholder_message->extension_range_count_ = 1; + placeholder_message->extension_ranges_ = + alloc.AllocateArray<Descriptor::ExtensionRange>(1); + placeholder_message->extension_ranges_[0].start = 1; + // kMaxNumber + 1 because ExtensionRange::end is exclusive. + placeholder_message->extension_ranges_[0].end = + FieldDescriptor::kMaxNumber + 1; + placeholder_message->extension_ranges_[0].options_ = nullptr; + } + + return Symbol(placeholder_message); + } +} + +FileDescriptor* DescriptorPool::NewPlaceholderFile( + StringPiece name) const { + MutexLockMaybe lock(mutex_); + internal::FlatAllocator alloc; + alloc.PlanArray<FileDescriptor>(1); + alloc.PlanArray<std::string>(1); + alloc.FinalizePlanning(tables_); + + return NewPlaceholderFileWithMutexHeld(name, alloc); +} + +FileDescriptor* DescriptorPool::NewPlaceholderFileWithMutexHeld( + StringPiece name, internal::FlatAllocator& alloc) const { + if (mutex_) { + mutex_->AssertHeld(); + } + FileDescriptor* placeholder = alloc.AllocateArray<FileDescriptor>(1); + memset(static_cast<void*>(placeholder), 0, sizeof(*placeholder)); + + placeholder->name_ = alloc.AllocateStrings(name); + placeholder->package_ = &internal::GetEmptyString(); + placeholder->pool_ = this; + placeholder->options_ = &FileOptions::default_instance(); + placeholder->tables_ = &FileDescriptorTables::GetEmptyInstance(); + placeholder->source_code_info_ = &SourceCodeInfo::default_instance(); + placeholder->is_placeholder_ = true; + placeholder->syntax_ = FileDescriptor::SYNTAX_UNKNOWN; + placeholder->finished_building_ = true; + // All other fields are zero or nullptr. + + return placeholder; +} + +bool DescriptorBuilder::AddSymbol(const std::string& full_name, + const void* parent, const std::string& name, + const Message& proto, Symbol symbol) { + // If the caller passed nullptr for the parent, the symbol is at file scope. + // Use its file as the parent instead. + if (parent == nullptr) parent = file_; + + if (full_name.find('\0') != std::string::npos) { + AddError(full_name, proto, DescriptorPool::ErrorCollector::NAME, + "\"" + full_name + "\" contains null character."); + return false; + } + if (tables_->AddSymbol(full_name, symbol)) { + if (!file_tables_->AddAliasUnderParent(parent, name, symbol)) { + // This is only possible if there was already an error adding something of + // the same name. + if (!had_errors_) { + GOOGLE_LOG(DFATAL) << "\"" << full_name + << "\" not previously defined in " + "symbols_by_name_, but was defined in " + "symbols_by_parent_; this shouldn't be possible."; + } + return false; + } + return true; + } else { + const FileDescriptor* other_file = tables_->FindSymbol(full_name).GetFile(); + if (other_file == file_) { + std::string::size_type dot_pos = full_name.find_last_of('.'); + if (dot_pos == std::string::npos) { + AddError(full_name, proto, DescriptorPool::ErrorCollector::NAME, + "\"" + full_name + "\" is already defined."); + } else { + AddError(full_name, proto, DescriptorPool::ErrorCollector::NAME, + "\"" + full_name.substr(dot_pos + 1) + + "\" is already defined in \"" + + full_name.substr(0, dot_pos) + "\"."); + } + } else { + // Symbol seems to have been defined in a different file. + AddError(full_name, proto, DescriptorPool::ErrorCollector::NAME, + "\"" + full_name + "\" is already defined in file \"" + + (other_file == nullptr ? "null" : other_file->name()) + + "\"."); + } + return false; + } +} + +void DescriptorBuilder::AddPackage(const std::string& name, + const Message& proto, FileDescriptor* file) { + if (name.find('\0') != std::string::npos) { + AddError(name, proto, DescriptorPool::ErrorCollector::NAME, + "\"" + name + "\" contains null character."); + return; + } + + Symbol existing_symbol = tables_->FindSymbol(name); + // It's OK to redefine a package. + if (existing_symbol.IsNull()) { + if (&name == &file->package()) { + // It is the toplevel package name, so insert the descriptor directly. + tables_->AddSymbol(file->package(), Symbol(file)); + } else { + auto* package = tables_->Allocate<Symbol::Subpackage>(); + // If the name is the package name, then it is already in the arena. + // If not, copy it there. It came from the call to AddPackage below. + package->name_size = static_cast<int>(name.size()); + package->file = file; + tables_->AddSymbol(name, Symbol(package)); + } + // Also add parent package, if any. + std::string::size_type dot_pos = name.find_last_of('.'); + if (dot_pos == std::string::npos) { + // No parents. + ValidateSymbolName(name, name, proto); + } else { + // Has parent. + AddPackage(name.substr(0, dot_pos), proto, file); + ValidateSymbolName(name.substr(dot_pos + 1), name, proto); + } + } else if (!existing_symbol.IsPackage()) { + // Symbol seems to have been defined in a different file. + const FileDescriptor* other_file = existing_symbol.GetFile(); + AddError(name, proto, DescriptorPool::ErrorCollector::NAME, + "\"" + name + + "\" is already defined (as something other than " + "a package) in file \"" + + (other_file == nullptr ? "null" : other_file->name()) + "\"."); + } +} + +void DescriptorBuilder::ValidateSymbolName(const std::string& name, + const std::string& full_name, + const Message& proto) { + if (name.empty()) { + AddError(full_name, proto, DescriptorPool::ErrorCollector::NAME, + "Missing name."); + } else { + for (char character : name) { + // I don't trust isalnum() due to locales. :( + if ((character < 'a' || 'z' < character) && + (character < 'A' || 'Z' < character) && + (character < '0' || '9' < character) && (character != '_')) { + AddError(full_name, proto, DescriptorPool::ErrorCollector::NAME, + "\"" + name + "\" is not a valid identifier."); + return; + } + } + } +} + +// ------------------------------------------------------------------- + +// This generic implementation is good for all descriptors except +// FileDescriptor. +template <class DescriptorT> +void DescriptorBuilder::AllocateOptions( + const typename DescriptorT::OptionsType& orig_options, + DescriptorT* descriptor, int options_field_tag, + const std::string& option_name, internal::FlatAllocator& alloc) { + std::vector<int> options_path; + descriptor->GetLocationPath(&options_path); + options_path.push_back(options_field_tag); + AllocateOptionsImpl(descriptor->full_name(), descriptor->full_name(), + orig_options, descriptor, options_path, option_name, + alloc); +} + +// We specialize for FileDescriptor. +void DescriptorBuilder::AllocateOptions(const FileOptions& orig_options, + FileDescriptor* descriptor, + internal::FlatAllocator& alloc) { + std::vector<int> options_path; + options_path.push_back(FileDescriptorProto::kOptionsFieldNumber); + // We add the dummy token so that LookupSymbol does the right thing. + AllocateOptionsImpl(descriptor->package() + ".dummy", descriptor->name(), + orig_options, descriptor, options_path, + "google.protobuf.FileOptions", alloc); +} + +template <class DescriptorT> +void DescriptorBuilder::AllocateOptionsImpl( + const std::string& name_scope, const std::string& element_name, + const typename DescriptorT::OptionsType& orig_options, + DescriptorT* descriptor, const std::vector<int>& options_path, + const std::string& option_name, internal::FlatAllocator& alloc) { + auto* options = alloc.AllocateArray<typename DescriptorT::OptionsType>(1); + + if (!orig_options.IsInitialized()) { + AddError(name_scope + "." + element_name, orig_options, + DescriptorPool::ErrorCollector::OPTION_NAME, + "Uninterpreted option is missing name or value."); + return; + } + + // Avoid using MergeFrom()/CopyFrom() in this class to make it -fno-rtti + // friendly. Without RTTI, MergeFrom() and CopyFrom() will fallback to the + // reflection based method, which requires the Descriptor. However, we are in + // the middle of building the descriptors, thus the deadlock. + options->ParseFromString(orig_options.SerializeAsString()); + descriptor->options_ = options; + + // Don't add to options_to_interpret_ unless there were uninterpreted + // options. This not only avoids unnecessary work, but prevents a + // bootstrapping problem when building descriptors for descriptor.proto. + // descriptor.proto does not contain any uninterpreted options, but + // attempting to interpret options anyway will cause + // OptionsType::GetDescriptor() to be called which may then deadlock since + // we're still trying to build it. + if (options->uninterpreted_option_size() > 0) { + options_to_interpret_.push_back(OptionsToInterpret( + name_scope, element_name, options_path, &orig_options, options)); + } + + // If the custom option is in unknown fields, no need to interpret it. + // Remove the dependency file from unused_dependency. + const UnknownFieldSet& unknown_fields = orig_options.unknown_fields(); + if (!unknown_fields.empty()) { + // Can not use options->GetDescriptor() which may case deadlock. + Symbol msg_symbol = tables_->FindSymbol(option_name); + if (msg_symbol.type() == Symbol::MESSAGE) { + for (int i = 0; i < unknown_fields.field_count(); ++i) { + assert_mutex_held(pool_); + const FieldDescriptor* field = + pool_->InternalFindExtensionByNumberNoLock( + msg_symbol.descriptor(), unknown_fields.field(i).number()); + if (field) { + unused_dependency_.erase(field->file()); + } + } + } + } +} + +// A common pattern: We want to convert a repeated field in the descriptor +// to an array of values, calling some method to build each value. +#define BUILD_ARRAY(INPUT, OUTPUT, NAME, METHOD, PARENT) \ + OUTPUT->NAME##_count_ = INPUT.NAME##_size(); \ + OUTPUT->NAME##s_ = alloc.AllocateArray< \ + typename std::remove_pointer<decltype(OUTPUT->NAME##s_)>::type>( \ + INPUT.NAME##_size()); \ + for (int i = 0; i < INPUT.NAME##_size(); i++) { \ + METHOD(INPUT.NAME(i), PARENT, OUTPUT->NAME##s_ + i, alloc); \ + } + +void DescriptorBuilder::AddRecursiveImportError( + const FileDescriptorProto& proto, int from_here) { + std::string error_message("File recursively imports itself: "); + for (size_t i = from_here; i < tables_->pending_files_.size(); i++) { + error_message.append(tables_->pending_files_[i]); + error_message.append(" -> "); + } + error_message.append(proto.name()); + + if (static_cast<size_t>(from_here) < tables_->pending_files_.size() - 1) { + AddError(tables_->pending_files_[from_here + 1], proto, + DescriptorPool::ErrorCollector::IMPORT, error_message); + } else { + AddError(proto.name(), proto, DescriptorPool::ErrorCollector::IMPORT, + error_message); + } +} + +void DescriptorBuilder::AddTwiceListedError(const FileDescriptorProto& proto, + int index) { + AddError(proto.dependency(index), proto, + DescriptorPool::ErrorCollector::IMPORT, + "Import \"" + proto.dependency(index) + "\" was listed twice."); +} + +void DescriptorBuilder::AddImportError(const FileDescriptorProto& proto, + int index) { + std::string message; + if (pool_->fallback_database_ == nullptr) { + message = "Import \"" + proto.dependency(index) + "\" has not been loaded."; + } else { + message = "Import \"" + proto.dependency(index) + + "\" was not found or had errors."; + } + AddError(proto.dependency(index), proto, + DescriptorPool::ErrorCollector::IMPORT, message); +} + +static bool ExistingFileMatchesProto(const FileDescriptor* existing_file, + const FileDescriptorProto& proto) { + FileDescriptorProto existing_proto; + existing_file->CopyTo(&existing_proto); + // TODO(liujisi): Remove it when CopyTo supports copying syntax params when + // syntax="proto2". + if (existing_file->syntax() == FileDescriptor::SYNTAX_PROTO2 && + proto.has_syntax()) { + existing_proto.set_syntax( + existing_file->SyntaxName(existing_file->syntax())); + } + + return existing_proto.SerializeAsString() == proto.SerializeAsString(); +} + +// These PlanAllocationSize functions will gather into the FlatAllocator all the +// necessary memory allocations that BuildXXX functions below will do on the +// Tables object. +// They *must* be kept in sync. If we miss some PlanArray call we won't have +// enough memory and will GOOGLE_CHECK-fail. +static void PlanAllocationSize( + const RepeatedPtrField<EnumValueDescriptorProto>& values, + internal::FlatAllocator& alloc) { + alloc.PlanArray<EnumValueDescriptor>(values.size()); + alloc.PlanArray<std::string>(2 * values.size()); // name + full_name + for (const auto& v : values) { + if (v.has_options()) alloc.PlanArray<EnumValueOptions>(1); + } +} + +static void PlanAllocationSize( + const RepeatedPtrField<EnumDescriptorProto>& enums, + internal::FlatAllocator& alloc) { + alloc.PlanArray<EnumDescriptor>(enums.size()); + alloc.PlanArray<std::string>(2 * enums.size()); // name + full_name + for (const auto& e : enums) { + if (e.has_options()) alloc.PlanArray<EnumOptions>(1); + PlanAllocationSize(e.value(), alloc); + alloc.PlanArray<EnumDescriptor::ReservedRange>(e.reserved_range_size()); + alloc.PlanArray<const std::string*>(e.reserved_name_size()); + alloc.PlanArray<std::string>(e.reserved_name_size()); + } +} + +static void PlanAllocationSize( + const RepeatedPtrField<OneofDescriptorProto>& oneofs, + internal::FlatAllocator& alloc) { + alloc.PlanArray<OneofDescriptor>(oneofs.size()); + alloc.PlanArray<std::string>(2 * oneofs.size()); // name + full_name + for (const auto& oneof : oneofs) { + if (oneof.has_options()) alloc.PlanArray<OneofOptions>(1); + } +} + +static void PlanAllocationSize( + const RepeatedPtrField<FieldDescriptorProto>& fields, + internal::FlatAllocator& alloc) { + alloc.PlanArray<FieldDescriptor>(fields.size()); + for (const auto& field : fields) { + if (field.has_options()) alloc.PlanArray<FieldOptions>(1); + alloc.PlanFieldNames(field.name(), + field.has_json_name() ? &field.json_name() : nullptr); + if (field.has_default_value() && field.has_type() && + (field.type() == FieldDescriptorProto::TYPE_STRING || + field.type() == FieldDescriptorProto::TYPE_BYTES)) { + // For the default string value. + alloc.PlanArray<std::string>(1); + } + } +} + +static void PlanAllocationSize( + const RepeatedPtrField<DescriptorProto::ExtensionRange>& ranges, + internal::FlatAllocator& alloc) { + alloc.PlanArray<Descriptor::ExtensionRange>(ranges.size()); + for (const auto& r : ranges) { + if (r.has_options()) alloc.PlanArray<ExtensionRangeOptions>(1); + } +} + +static void PlanAllocationSize( + const RepeatedPtrField<DescriptorProto>& messages, + internal::FlatAllocator& alloc) { + alloc.PlanArray<Descriptor>(messages.size()); + alloc.PlanArray<std::string>(2 * messages.size()); // name + full_name + + for (const auto& message : messages) { + if (message.has_options()) alloc.PlanArray<MessageOptions>(1); + PlanAllocationSize(message.nested_type(), alloc); + PlanAllocationSize(message.field(), alloc); + PlanAllocationSize(message.extension(), alloc); + PlanAllocationSize(message.extension_range(), alloc); + alloc.PlanArray<Descriptor::ReservedRange>(message.reserved_range_size()); + alloc.PlanArray<const std::string*>(message.reserved_name_size()); + alloc.PlanArray<std::string>(message.reserved_name_size()); + PlanAllocationSize(message.enum_type(), alloc); + PlanAllocationSize(message.oneof_decl(), alloc); + } +} + +static void PlanAllocationSize( + const RepeatedPtrField<MethodDescriptorProto>& methods, + internal::FlatAllocator& alloc) { + alloc.PlanArray<MethodDescriptor>(methods.size()); + alloc.PlanArray<std::string>(2 * methods.size()); // name + full_name + for (const auto& m : methods) { + if (m.has_options()) alloc.PlanArray<MethodOptions>(1); + } +} + +static void PlanAllocationSize( + const RepeatedPtrField<ServiceDescriptorProto>& services, + internal::FlatAllocator& alloc) { + alloc.PlanArray<ServiceDescriptor>(services.size()); + alloc.PlanArray<std::string>(2 * services.size()); // name + full_name + for (const auto& service : services) { + if (service.has_options()) alloc.PlanArray<ServiceOptions>(1); + PlanAllocationSize(service.method(), alloc); + } +} + +static void PlanAllocationSize(const FileDescriptorProto& proto, + internal::FlatAllocator& alloc) { + alloc.PlanArray<FileDescriptor>(1); + alloc.PlanArray<FileDescriptorTables>(1); + alloc.PlanArray<std::string>(2); // name + package + if (proto.has_options()) alloc.PlanArray<FileOptions>(1); + if (proto.has_source_code_info()) alloc.PlanArray<SourceCodeInfo>(1); + + PlanAllocationSize(proto.service(), alloc); + PlanAllocationSize(proto.message_type(), alloc); + PlanAllocationSize(proto.enum_type(), alloc); + PlanAllocationSize(proto.extension(), alloc); + + alloc.PlanArray<int>(proto.weak_dependency_size()); + alloc.PlanArray<int>(proto.public_dependency_size()); + alloc.PlanArray<const FileDescriptor*>(proto.dependency_size()); +} + +const FileDescriptor* DescriptorBuilder::BuildFile( + const FileDescriptorProto& proto) { + filename_ = proto.name(); + + // Check if the file already exists and is identical to the one being built. + // Note: This only works if the input is canonical -- that is, it + // fully-qualifies all type names, has no UninterpretedOptions, etc. + // This is fine, because this idempotency "feature" really only exists to + // accommodate one hack in the proto1->proto2 migration layer. + const FileDescriptor* existing_file = tables_->FindFile(filename_); + if (existing_file != nullptr) { + // File already in pool. Compare the existing one to the input. + if (ExistingFileMatchesProto(existing_file, proto)) { + // They're identical. Return the existing descriptor. + return existing_file; + } + + // Not a match. The error will be detected and handled later. + } + + // Check to see if this file is already on the pending files list. + // TODO(kenton): Allow recursive imports? It may not work with some + // (most?) programming languages. E.g., in C++, a forward declaration + // of a type is not sufficient to allow it to be used even in a + // generated header file due to inlining. This could perhaps be + // worked around using tricks involving inserting #include statements + // mid-file, but that's pretty ugly, and I'm pretty sure there are + // some languages out there that do not allow recursive dependencies + // at all. + for (size_t i = 0; i < tables_->pending_files_.size(); i++) { + if (tables_->pending_files_[i] == proto.name()) { + AddRecursiveImportError(proto, i); + return nullptr; + } + } + + static const int kMaximumPackageLength = 511; + if (proto.package().size() > kMaximumPackageLength) { + AddError(proto.package(), proto, DescriptorPool::ErrorCollector::NAME, + "Package name is too long"); + return nullptr; + } + + // If we have a fallback_database_, and we aren't doing lazy import building, + // attempt to load all dependencies now, before checkpointing tables_. This + // avoids confusion with recursive checkpoints. + if (!pool_->lazily_build_dependencies_) { + if (pool_->fallback_database_ != nullptr) { + tables_->pending_files_.push_back(proto.name()); + for (int i = 0; i < proto.dependency_size(); i++) { + if (tables_->FindFile(proto.dependency(i)) == nullptr && + (pool_->underlay_ == nullptr || + pool_->underlay_->FindFileByName(proto.dependency(i)) == + nullptr)) { + // We don't care what this returns since we'll find out below anyway. + pool_->TryFindFileInFallbackDatabase(proto.dependency(i)); + } + } + tables_->pending_files_.pop_back(); + } + } + + // Checkpoint the tables so that we can roll back if something goes wrong. + tables_->AddCheckpoint(); + + internal::FlatAllocator alloc; + PlanAllocationSize(proto, alloc); + alloc.FinalizePlanning(tables_); + FileDescriptor* result = BuildFileImpl(proto, alloc); + + file_tables_->FinalizeTables(); + if (result) { + tables_->ClearLastCheckpoint(); + result->finished_building_ = true; + alloc.ExpectConsumed(); + } else { + tables_->RollbackToLastCheckpoint(); + } + + return result; +} + +FileDescriptor* DescriptorBuilder::BuildFileImpl( + const FileDescriptorProto& proto, internal::FlatAllocator& alloc) { + FileDescriptor* result = alloc.AllocateArray<FileDescriptor>(1); + file_ = result; + + result->is_placeholder_ = false; + result->finished_building_ = false; + SourceCodeInfo* info = nullptr; + if (proto.has_source_code_info()) { + info = alloc.AllocateArray<SourceCodeInfo>(1); + info->CopyFrom(proto.source_code_info()); + result->source_code_info_ = info; + } else { + result->source_code_info_ = &SourceCodeInfo::default_instance(); + } + + file_tables_ = alloc.AllocateArray<FileDescriptorTables>(1); + file_->tables_ = file_tables_; + + if (!proto.has_name()) { + AddError("", proto, DescriptorPool::ErrorCollector::OTHER, + "Missing field: FileDescriptorProto.name."); + } + + // TODO(liujisi): Report error when the syntax is empty after all the protos + // have added the syntax statement. + if (proto.syntax().empty() || proto.syntax() == "proto2") { + file_->syntax_ = FileDescriptor::SYNTAX_PROTO2; + } else if (proto.syntax() == "proto3") { + file_->syntax_ = FileDescriptor::SYNTAX_PROTO3; + } else { + file_->syntax_ = FileDescriptor::SYNTAX_UNKNOWN; + AddError(proto.name(), proto, DescriptorPool::ErrorCollector::OTHER, + "Unrecognized syntax: " + proto.syntax()); + } + + result->name_ = alloc.AllocateStrings(proto.name()); + if (proto.has_package()) { + result->package_ = alloc.AllocateStrings(proto.package()); + } else { + // We cannot rely on proto.package() returning a valid string if + // proto.has_package() is false, because we might be running at static + // initialization time, in which case default values have not yet been + // initialized. + result->package_ = alloc.AllocateStrings(""); + } + result->pool_ = pool_; + + if (result->name().find('\0') != std::string::npos) { + AddError(result->name(), proto, DescriptorPool::ErrorCollector::NAME, + "\"" + result->name() + "\" contains null character."); + return nullptr; + } + + // Add to tables. + if (!tables_->AddFile(result)) { + AddError(proto.name(), proto, DescriptorPool::ErrorCollector::OTHER, + "A file with this name is already in the pool."); + // Bail out early so that if this is actually the exact same file, we + // don't end up reporting that every single symbol is already defined. + return nullptr; + } + if (!result->package().empty()) { + if (std::count(result->package().begin(), result->package().end(), '.') > + kPackageLimit) { + AddError(result->package(), proto, DescriptorPool::ErrorCollector::NAME, + "Exceeds Maximum Package Depth"); + return nullptr; + } + AddPackage(result->package(), proto, result); + } + + // Make sure all dependencies are loaded. + std::set<std::string> seen_dependencies; + result->dependency_count_ = proto.dependency_size(); + result->dependencies_ = + alloc.AllocateArray<const FileDescriptor*>(proto.dependency_size()); + result->dependencies_once_ = nullptr; + unused_dependency_.clear(); + std::set<int> weak_deps; + for (int i = 0; i < proto.weak_dependency_size(); ++i) { + weak_deps.insert(proto.weak_dependency(i)); + } + + bool need_lazy_deps = false; + for (int i = 0; i < proto.dependency_size(); i++) { + if (!seen_dependencies.insert(proto.dependency(i)).second) { + AddTwiceListedError(proto, i); + } + + const FileDescriptor* dependency = tables_->FindFile(proto.dependency(i)); + if (dependency == nullptr && pool_->underlay_ != nullptr) { + dependency = pool_->underlay_->FindFileByName(proto.dependency(i)); + } + + if (dependency == result) { + // Recursive import. dependency/result is not fully initialized, and it's + // dangerous to try to do anything with it. The recursive import error + // will be detected and reported in DescriptorBuilder::BuildFile(). + return nullptr; + } + + if (dependency == nullptr) { + if (!pool_->lazily_build_dependencies_) { + if (pool_->allow_unknown_ || + (!pool_->enforce_weak_ && weak_deps.find(i) != weak_deps.end())) { + internal::FlatAllocator lazy_dep_alloc; + lazy_dep_alloc.PlanArray<FileDescriptor>(1); + lazy_dep_alloc.PlanArray<std::string>(1); + lazy_dep_alloc.FinalizePlanning(tables_); + dependency = pool_->NewPlaceholderFileWithMutexHeld( + proto.dependency(i), lazy_dep_alloc); + } else { + AddImportError(proto, i); + } + } + } else { + // Add to unused_dependency_ to track unused imported files. + // Note: do not track unused imported files for public import. + if (pool_->enforce_dependencies_ && + (pool_->unused_import_track_files_.find(proto.name()) != + pool_->unused_import_track_files_.end()) && + (dependency->public_dependency_count() == 0)) { + unused_dependency_.insert(dependency); + } + } + + result->dependencies_[i] = dependency; + if (pool_->lazily_build_dependencies_ && !dependency) { + need_lazy_deps = true; + } + } + if (need_lazy_deps) { + int total_char_size = 0; + for (int i = 0; i < proto.dependency_size(); i++) { + if (result->dependencies_[i] == nullptr) { + total_char_size += static_cast<int>(proto.dependency(i).size()); + } + ++total_char_size; // For NUL char + } + + void* data = tables_->AllocateBytes( + static_cast<int>(sizeof(internal::once_flag) + total_char_size)); + result->dependencies_once_ = ::new (data) internal::once_flag{}; + char* name_data = reinterpret_cast<char*>(result->dependencies_once_ + 1); + + for (int i = 0; i < proto.dependency_size(); i++) { + if (result->dependencies_[i] == nullptr) { + memcpy(name_data, proto.dependency(i).c_str(), + proto.dependency(i).size()); + name_data += proto.dependency(i).size(); + } + *name_data++ = '\0'; + } + } + + // Check public dependencies. + int public_dependency_count = 0; + result->public_dependencies_ = + alloc.AllocateArray<int>(proto.public_dependency_size()); + for (int i = 0; i < proto.public_dependency_size(); i++) { + // Only put valid public dependency indexes. + int index = proto.public_dependency(i); + if (index >= 0 && index < proto.dependency_size()) { + result->public_dependencies_[public_dependency_count++] = index; + // Do not track unused imported files for public import. + // Calling dependency(i) builds that file when doing lazy imports, + // need to avoid doing this. Unused dependency detection isn't done + // when building lazily, anyways. + if (!pool_->lazily_build_dependencies_) { + unused_dependency_.erase(result->dependency(index)); + } + } else { + AddError(proto.name(), proto, DescriptorPool::ErrorCollector::OTHER, + "Invalid public dependency index."); + } + } + result->public_dependency_count_ = public_dependency_count; + + // Build dependency set + dependencies_.clear(); + // We don't/can't do proper dependency error checking when + // lazily_build_dependencies_, and calling dependency(i) will force + // a dependency to be built, which we don't want. + if (!pool_->lazily_build_dependencies_) { + for (int i = 0; i < result->dependency_count(); i++) { + RecordPublicDependencies(result->dependency(i)); + } + } + + // Check weak dependencies. + int weak_dependency_count = 0; + result->weak_dependencies_ = + alloc.AllocateArray<int>(proto.weak_dependency_size()); + for (int i = 0; i < proto.weak_dependency_size(); i++) { + int index = proto.weak_dependency(i); + if (index >= 0 && index < proto.dependency_size()) { + result->weak_dependencies_[weak_dependency_count++] = index; + } else { + AddError(proto.name(), proto, DescriptorPool::ErrorCollector::OTHER, + "Invalid weak dependency index."); + } + } + result->weak_dependency_count_ = weak_dependency_count; + + // Convert children. + BUILD_ARRAY(proto, result, message_type, BuildMessage, nullptr); + BUILD_ARRAY(proto, result, enum_type, BuildEnum, nullptr); + BUILD_ARRAY(proto, result, service, BuildService, nullptr); + BUILD_ARRAY(proto, result, extension, BuildExtension, nullptr); + + // Copy options. + result->options_ = nullptr; // Set to default_instance later if necessary. + if (proto.has_options()) { + AllocateOptions(proto.options(), result, alloc); + } + + // Note that the following steps must occur in exactly the specified order. + + // Cross-link. + CrossLinkFile(result, proto); + + if (!message_hints_.empty()) { + SuggestFieldNumbers(result, proto); + } + + // Interpret any remaining uninterpreted options gathered into + // options_to_interpret_ during descriptor building. Cross-linking has made + // extension options known, so all interpretations should now succeed. + if (!had_errors_) { + OptionInterpreter option_interpreter(this); + for (std::vector<OptionsToInterpret>::iterator iter = + options_to_interpret_.begin(); + iter != options_to_interpret_.end(); ++iter) { + option_interpreter.InterpretOptions(&(*iter)); + } + options_to_interpret_.clear(); + if (info != nullptr) { + option_interpreter.UpdateSourceCodeInfo(info); + } + } + + // Validate options. See comments at InternalSetLazilyBuildDependencies about + // error checking and lazy import building. + if (!had_errors_ && !pool_->lazily_build_dependencies_) { + ValidateFileOptions(result, proto); + } + + // Additional naming conflict check for map entry types. Only need to check + // this if there are already errors. + if (had_errors_) { + for (int i = 0; i < proto.message_type_size(); ++i) { + DetectMapConflicts(result->message_type(i), proto.message_type(i)); + } + } + + + // Again, see comments at InternalSetLazilyBuildDependencies about error + // checking. Also, don't log unused dependencies if there were previous + // errors, since the results might be inaccurate. + if (!had_errors_ && !unused_dependency_.empty() && + !pool_->lazily_build_dependencies_) { + LogUnusedDependency(proto, result); + } + + if (had_errors_) { + return nullptr; + } else { + return result; + } +} + + +const std::string* DescriptorBuilder::AllocateNameStrings( + const std::string& scope, const std::string& proto_name, + internal::FlatAllocator& alloc) { + if (scope.empty()) { + return alloc.AllocateStrings(proto_name, proto_name); + } else { + return alloc.AllocateStrings(proto_name, + StrCat(scope, ".", proto_name)); + } +} + +namespace { + +// Helper for BuildMessage below. +struct IncrementWhenDestroyed { + ~IncrementWhenDestroyed() { ++to_increment; } + int& to_increment; +}; + +} // namespace + +void DescriptorBuilder::BuildMessage(const DescriptorProto& proto, + const Descriptor* parent, + Descriptor* result, + internal::FlatAllocator& alloc) { + const std::string& scope = + (parent == nullptr) ? file_->package() : parent->full_name(); + result->all_names_ = AllocateNameStrings(scope, proto.name(), alloc); + ValidateSymbolName(proto.name(), result->full_name(), proto); + + result->file_ = file_; + result->containing_type_ = parent; + result->is_placeholder_ = false; + result->is_unqualified_placeholder_ = false; + result->well_known_type_ = Descriptor::WELLKNOWNTYPE_UNSPECIFIED; + result->options_ = nullptr; // Set to default_instance later if necessary. + + auto it = pool_->tables_->well_known_types_.find(result->full_name()); + if (it != pool_->tables_->well_known_types_.end()) { + result->well_known_type_ = it->second; + } + + // Calculate the continuous sequence of fields. + // These can be fast-path'd during lookup and don't need to be added to the + // tables. + // We use uint16_t to save space for sequential_field_limit_, so stop before + // overflowing it. Worst case, we are not taking full advantage on huge + // messages, but it is unlikely. + result->sequential_field_limit_ = 0; + for (int i = 0; i < std::numeric_limits<uint16_t>::max() && + i < proto.field_size() && proto.field(i).number() == i + 1; + ++i) { + result->sequential_field_limit_ = i + 1; + } + + // Build oneofs first so that fields and extension ranges can refer to them. + BUILD_ARRAY(proto, result, oneof_decl, BuildOneof, result); + BUILD_ARRAY(proto, result, field, BuildField, result); + BUILD_ARRAY(proto, result, enum_type, BuildEnum, result); + BUILD_ARRAY(proto, result, extension_range, BuildExtensionRange, result); + BUILD_ARRAY(proto, result, extension, BuildExtension, result); + BUILD_ARRAY(proto, result, reserved_range, BuildReservedRange, result); + + // Before building submessages, check recursion limit. + --recursion_depth_; + IncrementWhenDestroyed revert{recursion_depth_}; + if (recursion_depth_ <= 0) { + AddError(result->full_name(), proto, DescriptorPool::ErrorCollector::OTHER, + "Reached maximum recursion limit for nested messages."); + result->nested_types_ = nullptr; + result->nested_type_count_ = 0; + return; + } + BUILD_ARRAY(proto, result, nested_type, BuildMessage, result); + + // Copy reserved names. + int reserved_name_count = proto.reserved_name_size(); + result->reserved_name_count_ = reserved_name_count; + result->reserved_names_ = + alloc.AllocateArray<const std::string*>(reserved_name_count); + for (int i = 0; i < reserved_name_count; ++i) { + result->reserved_names_[i] = + alloc.AllocateStrings(proto.reserved_name(i)); + } + + // Copy options. + if (proto.has_options()) { + AllocateOptions(proto.options(), result, + DescriptorProto::kOptionsFieldNumber, + "google.protobuf.MessageOptions", alloc); + } + + AddSymbol(result->full_name(), parent, result->name(), proto, Symbol(result)); + + for (int i = 0; i < proto.reserved_range_size(); i++) { + const DescriptorProto_ReservedRange& range1 = proto.reserved_range(i); + for (int j = i + 1; j < proto.reserved_range_size(); j++) { + const DescriptorProto_ReservedRange& range2 = proto.reserved_range(j); + if (range1.end() > range2.start() && range2.end() > range1.start()) { + AddError(result->full_name(), proto.reserved_range(i), + DescriptorPool::ErrorCollector::NUMBER, + strings::Substitute("Reserved range $0 to $1 overlaps with " + "already-defined range $2 to $3.", + range2.start(), range2.end() - 1, + range1.start(), range1.end() - 1)); + } + } + } + + HASH_SET<std::string> reserved_name_set; + for (int i = 0; i < proto.reserved_name_size(); i++) { + const std::string& name = proto.reserved_name(i); + if (reserved_name_set.find(name) == reserved_name_set.end()) { + reserved_name_set.insert(name); + } else { + AddError(name, proto, DescriptorPool::ErrorCollector::NAME, + strings::Substitute("Field name \"$0\" is reserved multiple times.", + name)); + } + } + + + for (int i = 0; i < result->field_count(); i++) { + const FieldDescriptor* field = result->field(i); + for (int j = 0; j < result->extension_range_count(); j++) { + const Descriptor::ExtensionRange* range = result->extension_range(j); + if (range->start <= field->number() && field->number() < range->end) { + message_hints_[result].RequestHintOnFieldNumbers( + proto.extension_range(j), DescriptorPool::ErrorCollector::NUMBER); + AddError( + field->full_name(), proto.extension_range(j), + DescriptorPool::ErrorCollector::NUMBER, + strings::Substitute( + "Extension range $0 to $1 includes field \"$2\" ($3).", + range->start, range->end - 1, field->name(), field->number())); + } + } + for (int j = 0; j < result->reserved_range_count(); j++) { + const Descriptor::ReservedRange* range = result->reserved_range(j); + if (range->start <= field->number() && field->number() < range->end) { + message_hints_[result].RequestHintOnFieldNumbers( + proto.reserved_range(j), DescriptorPool::ErrorCollector::NUMBER); + AddError(field->full_name(), proto.reserved_range(j), + DescriptorPool::ErrorCollector::NUMBER, + strings::Substitute("Field \"$0\" uses reserved number $1.", + field->name(), field->number())); + } + } + if (reserved_name_set.find(field->name()) != reserved_name_set.end()) { + AddError( + field->full_name(), proto.field(i), + DescriptorPool::ErrorCollector::NAME, + strings::Substitute("Field name \"$0\" is reserved.", field->name())); + } + + } + + // Check that extension ranges don't overlap and don't include + // reserved field numbers or names. + for (int i = 0; i < result->extension_range_count(); i++) { + const Descriptor::ExtensionRange* range1 = result->extension_range(i); + for (int j = 0; j < result->reserved_range_count(); j++) { + const Descriptor::ReservedRange* range2 = result->reserved_range(j); + if (range1->end > range2->start && range2->end > range1->start) { + AddError(result->full_name(), proto.extension_range(i), + DescriptorPool::ErrorCollector::NUMBER, + strings::Substitute("Extension range $0 to $1 overlaps with " + "reserved range $2 to $3.", + range1->start, range1->end - 1, range2->start, + range2->end - 1)); + } + } + for (int j = i + 1; j < result->extension_range_count(); j++) { + const Descriptor::ExtensionRange* range2 = result->extension_range(j); + if (range1->end > range2->start && range2->end > range1->start) { + AddError(result->full_name(), proto.extension_range(i), + DescriptorPool::ErrorCollector::NUMBER, + strings::Substitute("Extension range $0 to $1 overlaps with " + "already-defined range $2 to $3.", + range2->start, range2->end - 1, range1->start, + range1->end - 1)); + } + } + } +} + +void DescriptorBuilder::BuildFieldOrExtension(const FieldDescriptorProto& proto, + Descriptor* parent, + FieldDescriptor* result, + bool is_extension, + internal::FlatAllocator& alloc) { + const std::string& scope = + (parent == nullptr) ? file_->package() : parent->full_name(); + + // We allocate all names in a single array, and dedup them. + // We remember the indices for the potentially deduped values. + auto all_names = alloc.AllocateFieldNames( + proto.name(), scope, + proto.has_json_name() ? &proto.json_name() : nullptr); + result->all_names_ = all_names.array; + result->lowercase_name_index_ = all_names.lowercase_index; + result->camelcase_name_index_ = all_names.camelcase_index; + result->json_name_index_ = all_names.json_index; + + ValidateSymbolName(proto.name(), result->full_name(), proto); + + result->file_ = file_; + result->number_ = proto.number(); + result->is_extension_ = is_extension; + result->is_oneof_ = false; + result->proto3_optional_ = proto.proto3_optional(); + + if (proto.proto3_optional() && + file_->syntax() != FileDescriptor::SYNTAX_PROTO3) { + AddError(result->full_name(), proto, DescriptorPool::ErrorCollector::TYPE, + "The [proto3_optional=true] option may only be set on proto3" + "fields, not " + + result->full_name()); + } + + result->has_json_name_ = proto.has_json_name(); + + // Some compilers do not allow static_cast directly between two enum types, + // so we must cast to int first. + result->type_ = static_cast<FieldDescriptor::Type>( + implicit_cast<int>(proto.type())); + result->label_ = static_cast<FieldDescriptor::Label>( + implicit_cast<int>(proto.label())); + + if (result->label_ == FieldDescriptor::LABEL_REQUIRED) { + // An extension cannot have a required field (b/13365836). + if (result->is_extension_) { + AddError(result->full_name(), proto, + // Error location `TYPE`: we would really like to indicate + // `LABEL`, but the `ErrorLocation` enum has no entry for this, + // and we don't necessarily know about all implementations of the + // `ErrorCollector` interface to extend them to handle the new + // error location type properly. + DescriptorPool::ErrorCollector::TYPE, + "The extension " + result->full_name() + " cannot be required."); + } + } + + // Some of these may be filled in when cross-linking. + result->containing_type_ = nullptr; + result->type_once_ = nullptr; + result->default_value_enum_ = nullptr; + + result->has_default_value_ = proto.has_default_value(); + if (proto.has_default_value() && result->is_repeated()) { + AddError(result->full_name(), proto, + DescriptorPool::ErrorCollector::DEFAULT_VALUE, + "Repeated fields can't have default values."); + } + + if (proto.has_type()) { + if (proto.has_default_value()) { + char* end_pos = nullptr; + switch (result->cpp_type()) { + case FieldDescriptor::CPPTYPE_INT32: + result->default_value_int32_t_ = + strtol(proto.default_value().c_str(), &end_pos, 0); + break; + case FieldDescriptor::CPPTYPE_INT64: + result->default_value_int64_t_ = + strto64(proto.default_value().c_str(), &end_pos, 0); + break; + case FieldDescriptor::CPPTYPE_UINT32: + result->default_value_uint32_t_ = + strtoul(proto.default_value().c_str(), &end_pos, 0); + break; + case FieldDescriptor::CPPTYPE_UINT64: + result->default_value_uint64_t_ = + strtou64(proto.default_value().c_str(), &end_pos, 0); + break; + case FieldDescriptor::CPPTYPE_FLOAT: + if (proto.default_value() == "inf") { + result->default_value_float_ = + std::numeric_limits<float>::infinity(); + } else if (proto.default_value() == "-inf") { + result->default_value_float_ = + -std::numeric_limits<float>::infinity(); + } else if (proto.default_value() == "nan") { + result->default_value_float_ = + std::numeric_limits<float>::quiet_NaN(); + } else { + result->default_value_float_ = io::SafeDoubleToFloat( + io::NoLocaleStrtod(proto.default_value().c_str(), &end_pos)); + } + break; + case FieldDescriptor::CPPTYPE_DOUBLE: + if (proto.default_value() == "inf") { + result->default_value_double_ = + std::numeric_limits<double>::infinity(); + } else if (proto.default_value() == "-inf") { + result->default_value_double_ = + -std::numeric_limits<double>::infinity(); + } else if (proto.default_value() == "nan") { + result->default_value_double_ = + std::numeric_limits<double>::quiet_NaN(); + } else { + result->default_value_double_ = + io::NoLocaleStrtod(proto.default_value().c_str(), &end_pos); + } + break; + case FieldDescriptor::CPPTYPE_BOOL: + if (proto.default_value() == "true") { + result->default_value_bool_ = true; + } else if (proto.default_value() == "false") { + result->default_value_bool_ = false; + } else { + AddError(result->full_name(), proto, + DescriptorPool::ErrorCollector::DEFAULT_VALUE, + "Boolean default must be true or false."); + } + break; + case FieldDescriptor::CPPTYPE_ENUM: + // This will be filled in when cross-linking. + result->default_value_enum_ = nullptr; + break; + case FieldDescriptor::CPPTYPE_STRING: + if (result->type() == FieldDescriptor::TYPE_BYTES) { + result->default_value_string_ = alloc.AllocateStrings( + UnescapeCEscapeString(proto.default_value())); + } else { + result->default_value_string_ = + alloc.AllocateStrings(proto.default_value()); + } + break; + case FieldDescriptor::CPPTYPE_MESSAGE: + AddError(result->full_name(), proto, + DescriptorPool::ErrorCollector::DEFAULT_VALUE, + "Messages can't have default values."); + result->has_default_value_ = false; + result->default_generated_instance_ = nullptr; + break; + } + + if (end_pos != nullptr) { + // end_pos is only set non-null by the parsers for numeric types, + // above. This checks that the default was non-empty and had no extra + // junk after the end of the number. + if (proto.default_value().empty() || *end_pos != '\0') { + AddError(result->full_name(), proto, + DescriptorPool::ErrorCollector::DEFAULT_VALUE, + "Couldn't parse default value \"" + proto.default_value() + + "\"."); + } + } + } else { + // No explicit default value + switch (result->cpp_type()) { + case FieldDescriptor::CPPTYPE_INT32: + result->default_value_int32_t_ = 0; + break; + case FieldDescriptor::CPPTYPE_INT64: + result->default_value_int64_t_ = 0; + break; + case FieldDescriptor::CPPTYPE_UINT32: + result->default_value_uint32_t_ = 0; + break; + case FieldDescriptor::CPPTYPE_UINT64: + result->default_value_uint64_t_ = 0; + break; + case FieldDescriptor::CPPTYPE_FLOAT: + result->default_value_float_ = 0.0f; + break; + case FieldDescriptor::CPPTYPE_DOUBLE: + result->default_value_double_ = 0.0; + break; + case FieldDescriptor::CPPTYPE_BOOL: + result->default_value_bool_ = false; + break; + case FieldDescriptor::CPPTYPE_ENUM: + // This will be filled in when cross-linking. + result->default_value_enum_ = nullptr; + break; + case FieldDescriptor::CPPTYPE_STRING: + result->default_value_string_ = &internal::GetEmptyString(); + break; + case FieldDescriptor::CPPTYPE_MESSAGE: + result->default_generated_instance_ = nullptr; + break; + } + } + } + + if (result->number() <= 0) { + message_hints_[parent].RequestHintOnFieldNumbers( + proto, DescriptorPool::ErrorCollector::NUMBER); + AddError(result->full_name(), proto, DescriptorPool::ErrorCollector::NUMBER, + "Field numbers must be positive integers."); + } else if (!is_extension && result->number() > FieldDescriptor::kMaxNumber) { + // Only validate that the number is within the valid field range if it is + // not an extension. Since extension numbers are validated with the + // extendee's valid set of extension numbers, and those are in turn + // validated against the max allowed number, the check is unnecessary for + // extension fields. + // This avoids cross-linking issues that arise when attempting to check if + // the extendee is a message_set_wire_format message, which has a higher max + // on extension numbers. + message_hints_[parent].RequestHintOnFieldNumbers( + proto, DescriptorPool::ErrorCollector::NUMBER); + AddError(result->full_name(), proto, DescriptorPool::ErrorCollector::NUMBER, + strings::Substitute("Field numbers cannot be greater than $0.", + FieldDescriptor::kMaxNumber)); + } else if (result->number() >= FieldDescriptor::kFirstReservedNumber && + result->number() <= FieldDescriptor::kLastReservedNumber) { + message_hints_[parent].RequestHintOnFieldNumbers( + proto, DescriptorPool::ErrorCollector::NUMBER); + AddError(result->full_name(), proto, DescriptorPool::ErrorCollector::NUMBER, + strings::Substitute( + "Field numbers $0 through $1 are reserved for the protocol " + "buffer library implementation.", + FieldDescriptor::kFirstReservedNumber, + FieldDescriptor::kLastReservedNumber)); + } + + if (is_extension) { + if (!proto.has_extendee()) { + AddError(result->full_name(), proto, + DescriptorPool::ErrorCollector::EXTENDEE, + "FieldDescriptorProto.extendee not set for extension field."); + } + + result->scope_.extension_scope = parent; + + if (proto.has_oneof_index()) { + AddError(result->full_name(), proto, DescriptorPool::ErrorCollector::TYPE, + "FieldDescriptorProto.oneof_index should not be set for " + "extensions."); + } + } else { + if (proto.has_extendee()) { + AddError(result->full_name(), proto, + DescriptorPool::ErrorCollector::EXTENDEE, + "FieldDescriptorProto.extendee set for non-extension field."); + } + + result->containing_type_ = parent; + + if (proto.has_oneof_index()) { + if (proto.oneof_index() < 0 || + proto.oneof_index() >= parent->oneof_decl_count()) { + AddError(result->full_name(), proto, + DescriptorPool::ErrorCollector::TYPE, + strings::Substitute("FieldDescriptorProto.oneof_index $0 is " + "out of range for type \"$1\".", + proto.oneof_index(), parent->name())); + } else { + result->is_oneof_ = true; + result->scope_.containing_oneof = + parent->oneof_decl(proto.oneof_index()); + } + } + } + + // Copy options. + result->options_ = nullptr; // Set to default_instance later if necessary. + if (proto.has_options()) { + AllocateOptions(proto.options(), result, + FieldDescriptorProto::kOptionsFieldNumber, + "google.protobuf.FieldOptions", alloc); + } + + AddSymbol(result->full_name(), parent, result->name(), proto, Symbol(result)); +} + +void DescriptorBuilder::BuildExtensionRange( + const DescriptorProto::ExtensionRange& proto, const Descriptor* parent, + Descriptor::ExtensionRange* result, internal::FlatAllocator& alloc) { + result->start = proto.start(); + result->end = proto.end(); + if (result->start <= 0) { + message_hints_[parent].RequestHintOnFieldNumbers( + proto, DescriptorPool::ErrorCollector::NUMBER, result->start, + result->end); + AddError(parent->full_name(), proto, DescriptorPool::ErrorCollector::NUMBER, + "Extension numbers must be positive integers."); + } + + // Checking of the upper bound of the extension range is deferred until after + // options interpreting. This allows messages with message_set_wire_format to + // have extensions beyond FieldDescriptor::kMaxNumber, since the extension + // numbers are actually used as int32s in the message_set_wire_format. + + if (result->start >= result->end) { + AddError(parent->full_name(), proto, DescriptorPool::ErrorCollector::NUMBER, + "Extension range end number must be greater than start number."); + } + + result->options_ = nullptr; // Set to default_instance later if necessary. + if (proto.has_options()) { + std::vector<int> options_path; + parent->GetLocationPath(&options_path); + options_path.push_back(DescriptorProto::kExtensionRangeFieldNumber); + // find index of this extension range in order to compute path + int index; + for (index = 0; parent->extension_ranges_ + index != result; index++) { + } + options_path.push_back(index); + options_path.push_back(DescriptorProto_ExtensionRange::kOptionsFieldNumber); + AllocateOptionsImpl(parent->full_name(), parent->full_name(), + proto.options(), result, options_path, + "google.protobuf.ExtensionRangeOptions", alloc); + } +} + +void DescriptorBuilder::BuildReservedRange( + const DescriptorProto::ReservedRange& proto, const Descriptor* parent, + Descriptor::ReservedRange* result, internal::FlatAllocator&) { + result->start = proto.start(); + result->end = proto.end(); + if (result->start <= 0) { + message_hints_[parent].RequestHintOnFieldNumbers( + proto, DescriptorPool::ErrorCollector::NUMBER, result->start, + result->end); + AddError(parent->full_name(), proto, DescriptorPool::ErrorCollector::NUMBER, + "Reserved numbers must be positive integers."); + } +} + +void DescriptorBuilder::BuildReservedRange( + const EnumDescriptorProto::EnumReservedRange& proto, + const EnumDescriptor* parent, EnumDescriptor::ReservedRange* result, + internal::FlatAllocator&) { + result->start = proto.start(); + result->end = proto.end(); + + if (result->start > result->end) { + AddError(parent->full_name(), proto, DescriptorPool::ErrorCollector::NUMBER, + "Reserved range end number must be greater than start number."); + } +} + +void DescriptorBuilder::BuildOneof(const OneofDescriptorProto& proto, + Descriptor* parent, OneofDescriptor* result, + internal::FlatAllocator& alloc) { + result->all_names_ = + AllocateNameStrings(parent->full_name(), proto.name(), alloc); + ValidateSymbolName(proto.name(), result->full_name(), proto); + + result->containing_type_ = parent; + + // We need to fill these in later. + result->field_count_ = 0; + result->fields_ = nullptr; + result->options_ = nullptr; + + // Copy options. + if (proto.has_options()) { + AllocateOptions(proto.options(), result, + OneofDescriptorProto::kOptionsFieldNumber, + "google.protobuf.OneofOptions", alloc); + } + + AddSymbol(result->full_name(), parent, result->name(), proto, Symbol(result)); +} + +void DescriptorBuilder::CheckEnumValueUniqueness( + const EnumDescriptorProto& proto, const EnumDescriptor* result) { + + // Check that enum labels are still unique when we remove the enum prefix from + // values that have it. + // + // This will fail for something like: + // + // enum MyEnum { + // MY_ENUM_FOO = 0; + // FOO = 1; + // } + // + // By enforcing this reasonable constraint, we allow code generators to strip + // the prefix and/or PascalCase it without creating conflicts. This can lead + // to much nicer language-specific enums like: + // + // enum NameType { + // FirstName = 1, + // LastName = 2, + // } + // + // Instead of: + // + // enum NameType { + // NAME_TYPE_FIRST_NAME = 1, + // NAME_TYPE_LAST_NAME = 2, + // } + PrefixRemover remover(result->name()); + std::map<std::string, const EnumValueDescriptor*> values; + for (int i = 0; i < result->value_count(); i++) { + const EnumValueDescriptor* value = result->value(i); + std::string stripped = + EnumValueToPascalCase(remover.MaybeRemove(value->name())); + std::pair<std::map<std::string, const EnumValueDescriptor*>::iterator, bool> + insert_result = values.insert(std::make_pair(stripped, value)); + bool inserted = insert_result.second; + + // We don't throw the error if the two conflicting symbols are identical, or + // if they map to the same number. In the former case, the normal symbol + // duplication error will fire so we don't need to (and its error message + // will make more sense). We allow the latter case so users can create + // aliases which add or remove the prefix (code generators that do prefix + // stripping should de-dup the labels in this case). + if (!inserted && insert_result.first->second->name() != value->name() && + insert_result.first->second->number() != value->number()) { + std::string error_message = + "Enum name " + value->name() + " has the same name as " + + values[stripped]->name() + + " if you ignore case and strip out the enum name prefix (if any). " + "This is error-prone and can lead to undefined behavior. " + "Please avoid doing this. If you are using allow_alias, please " + "assign the same numeric value to both enums."; + // There are proto2 enums out there with conflicting names, so to preserve + // compatibility we issue only a warning for proto2. + if (result->file()->syntax() == FileDescriptor::SYNTAX_PROTO2) { + AddWarning(value->full_name(), proto.value(i), + DescriptorPool::ErrorCollector::NAME, error_message); + } else { + AddError(value->full_name(), proto.value(i), + DescriptorPool::ErrorCollector::NAME, error_message); + } + } + } +} + +void DescriptorBuilder::BuildEnum(const EnumDescriptorProto& proto, + const Descriptor* parent, + EnumDescriptor* result, + internal::FlatAllocator& alloc) { + const std::string& scope = + (parent == nullptr) ? file_->package() : parent->full_name(); + + result->all_names_ = AllocateNameStrings(scope, proto.name(), alloc); + ValidateSymbolName(proto.name(), result->full_name(), proto); + result->file_ = file_; + result->containing_type_ = parent; + result->is_placeholder_ = false; + result->is_unqualified_placeholder_ = false; + + if (proto.value_size() == 0) { + // We cannot allow enums with no values because this would mean there + // would be no valid default value for fields of this type. + AddError(result->full_name(), proto, DescriptorPool::ErrorCollector::NAME, + "Enums must contain at least one value."); + } + + // Calculate the continuous sequence of the labels. + // These can be fast-path'd during lookup and don't need to be added to the + // tables. + // We use uint16_t to save space for sequential_value_limit_, so stop before + // overflowing it. Worst case, we are not taking full advantage on huge + // enums, but it is unlikely. + for (int i = 0; + i < std::numeric_limits<uint16_t>::max() && i < proto.value_size() && + // We do the math in int64_t to avoid overflows. + proto.value(i).number() == + static_cast<int64_t>(i) + proto.value(0).number(); + ++i) { + result->sequential_value_limit_ = i; + } + + BUILD_ARRAY(proto, result, value, BuildEnumValue, result); + BUILD_ARRAY(proto, result, reserved_range, BuildReservedRange, result); + + // Copy reserved names. + int reserved_name_count = proto.reserved_name_size(); + result->reserved_name_count_ = reserved_name_count; + result->reserved_names_ = + alloc.AllocateArray<const std::string*>(reserved_name_count); + for (int i = 0; i < reserved_name_count; ++i) { + result->reserved_names_[i] = + alloc.AllocateStrings(proto.reserved_name(i)); + } + + CheckEnumValueUniqueness(proto, result); + + // Copy options. + result->options_ = nullptr; // Set to default_instance later if necessary. + if (proto.has_options()) { + AllocateOptions(proto.options(), result, + EnumDescriptorProto::kOptionsFieldNumber, + "google.protobuf.EnumOptions", alloc); + } + + AddSymbol(result->full_name(), parent, result->name(), proto, Symbol(result)); + + for (int i = 0; i < proto.reserved_range_size(); i++) { + const EnumDescriptorProto_EnumReservedRange& range1 = + proto.reserved_range(i); + for (int j = i + 1; j < proto.reserved_range_size(); j++) { + const EnumDescriptorProto_EnumReservedRange& range2 = + proto.reserved_range(j); + if (range1.end() >= range2.start() && range2.end() >= range1.start()) { + AddError(result->full_name(), proto.reserved_range(i), + DescriptorPool::ErrorCollector::NUMBER, + strings::Substitute("Reserved range $0 to $1 overlaps with " + "already-defined range $2 to $3.", + range2.start(), range2.end(), range1.start(), + range1.end())); + } + } + } + + HASH_SET<std::string> reserved_name_set; + for (int i = 0; i < proto.reserved_name_size(); i++) { + const std::string& name = proto.reserved_name(i); + if (reserved_name_set.find(name) == reserved_name_set.end()) { + reserved_name_set.insert(name); + } else { + AddError(name, proto, DescriptorPool::ErrorCollector::NAME, + strings::Substitute("Enum value \"$0\" is reserved multiple times.", + name)); + } + } + + for (int i = 0; i < result->value_count(); i++) { + const EnumValueDescriptor* value = result->value(i); + for (int j = 0; j < result->reserved_range_count(); j++) { + const EnumDescriptor::ReservedRange* range = result->reserved_range(j); + if (range->start <= value->number() && value->number() <= range->end) { + AddError(value->full_name(), proto.reserved_range(j), + DescriptorPool::ErrorCollector::NUMBER, + strings::Substitute("Enum value \"$0\" uses reserved number $1.", + value->name(), value->number())); + } + } + if (reserved_name_set.find(value->name()) != reserved_name_set.end()) { + AddError( + value->full_name(), proto.value(i), + DescriptorPool::ErrorCollector::NAME, + strings::Substitute("Enum value \"$0\" is reserved.", value->name())); + } + } +} + +void DescriptorBuilder::BuildEnumValue(const EnumValueDescriptorProto& proto, + const EnumDescriptor* parent, + EnumValueDescriptor* result, + internal::FlatAllocator& alloc) { + // Note: full_name for enum values is a sibling to the parent's name, not a + // child of it. + std::string full_name; + size_t scope_len = parent->full_name().size() - parent->name().size(); + full_name.reserve(scope_len + proto.name().size()); + full_name.append(parent->full_name().data(), scope_len); + full_name.append(proto.name()); + + result->all_names_ = + alloc.AllocateStrings(proto.name(), std::move(full_name)); + result->number_ = proto.number(); + result->type_ = parent; + + ValidateSymbolName(proto.name(), result->full_name(), proto); + + // Copy options. + result->options_ = nullptr; // Set to default_instance later if necessary. + if (proto.has_options()) { + AllocateOptions(proto.options(), result, + EnumValueDescriptorProto::kOptionsFieldNumber, + "google.protobuf.EnumValueOptions", alloc); + } + + // Again, enum values are weird because we makes them appear as siblings + // of the enum type instead of children of it. So, we use + // parent->containing_type() as the value's parent. + bool added_to_outer_scope = + AddSymbol(result->full_name(), parent->containing_type(), result->name(), + proto, Symbol::EnumValue(result, 0)); + + // However, we also want to be able to search for values within a single + // enum type, so we add it as a child of the enum type itself, too. + // Note: This could fail, but if it does, the error has already been + // reported by the above AddSymbol() call, so we ignore the return code. + bool added_to_inner_scope = file_tables_->AddAliasUnderParent( + parent, result->name(), Symbol::EnumValue(result, 1)); + + if (added_to_inner_scope && !added_to_outer_scope) { + // This value did not conflict with any values defined in the same enum, + // but it did conflict with some other symbol defined in the enum type's + // scope. Let's print an additional error to explain this. + std::string outer_scope; + if (parent->containing_type() == nullptr) { + outer_scope = file_->package(); + } else { + outer_scope = parent->containing_type()->full_name(); + } + + if (outer_scope.empty()) { + outer_scope = "the global scope"; + } else { + outer_scope = "\"" + outer_scope + "\""; + } + + AddError(result->full_name(), proto, DescriptorPool::ErrorCollector::NAME, + "Note that enum values use C++ scoping rules, meaning that " + "enum values are siblings of their type, not children of it. " + "Therefore, \"" + + result->name() + "\" must be unique within " + outer_scope + + ", not just within \"" + parent->name() + "\"."); + } + + // An enum is allowed to define two numbers that refer to the same value. + // FindValueByNumber() should return the first such value, so we simply + // ignore AddEnumValueByNumber()'s return code. + file_tables_->AddEnumValueByNumber(result); +} + +void DescriptorBuilder::BuildService(const ServiceDescriptorProto& proto, + const void* /* dummy */, + ServiceDescriptor* result, + internal::FlatAllocator& alloc) { + result->all_names_ = + AllocateNameStrings(file_->package(), proto.name(), alloc); + result->file_ = file_; + ValidateSymbolName(proto.name(), result->full_name(), proto); + + BUILD_ARRAY(proto, result, method, BuildMethod, result); + + // Copy options. + result->options_ = nullptr; // Set to default_instance later if necessary. + if (proto.has_options()) { + AllocateOptions(proto.options(), result, + ServiceDescriptorProto::kOptionsFieldNumber, + "google.protobuf.ServiceOptions", alloc); + } + + AddSymbol(result->full_name(), nullptr, result->name(), proto, + Symbol(result)); +} + +void DescriptorBuilder::BuildMethod(const MethodDescriptorProto& proto, + const ServiceDescriptor* parent, + MethodDescriptor* result, + internal::FlatAllocator& alloc) { + result->service_ = parent; + result->all_names_ = + AllocateNameStrings(parent->full_name(), proto.name(), alloc); + + ValidateSymbolName(proto.name(), result->full_name(), proto); + + // These will be filled in when cross-linking. + result->input_type_.Init(); + result->output_type_.Init(); + + // Copy options. + result->options_ = nullptr; // Set to default_instance later if necessary. + if (proto.has_options()) { + AllocateOptions(proto.options(), result, + MethodDescriptorProto::kOptionsFieldNumber, + "google.protobuf.MethodOptions", alloc); + } + + result->client_streaming_ = proto.client_streaming(); + result->server_streaming_ = proto.server_streaming(); + + AddSymbol(result->full_name(), parent, result->name(), proto, Symbol(result)); +} + +#undef BUILD_ARRAY + +// ------------------------------------------------------------------- + +void DescriptorBuilder::CrossLinkFile(FileDescriptor* file, + const FileDescriptorProto& proto) { + if (file->options_ == nullptr) { + file->options_ = &FileOptions::default_instance(); + } + + for (int i = 0; i < file->message_type_count(); i++) { + CrossLinkMessage(&file->message_types_[i], proto.message_type(i)); + } + + for (int i = 0; i < file->extension_count(); i++) { + CrossLinkField(&file->extensions_[i], proto.extension(i)); + } + + for (int i = 0; i < file->enum_type_count(); i++) { + CrossLinkEnum(&file->enum_types_[i], proto.enum_type(i)); + } + + for (int i = 0; i < file->service_count(); i++) { + CrossLinkService(&file->services_[i], proto.service(i)); + } +} + +void DescriptorBuilder::CrossLinkMessage(Descriptor* message, + const DescriptorProto& proto) { + if (message->options_ == nullptr) { + message->options_ = &MessageOptions::default_instance(); + } + + for (int i = 0; i < message->nested_type_count(); i++) { + CrossLinkMessage(&message->nested_types_[i], proto.nested_type(i)); + } + + for (int i = 0; i < message->enum_type_count(); i++) { + CrossLinkEnum(&message->enum_types_[i], proto.enum_type(i)); + } + + for (int i = 0; i < message->field_count(); i++) { + CrossLinkField(&message->fields_[i], proto.field(i)); + } + + for (int i = 0; i < message->extension_count(); i++) { + CrossLinkField(&message->extensions_[i], proto.extension(i)); + } + + for (int i = 0; i < message->extension_range_count(); i++) { + CrossLinkExtensionRange(&message->extension_ranges_[i], + proto.extension_range(i)); + } + + // Set up field array for each oneof. + + // First count the number of fields per oneof. + for (int i = 0; i < message->field_count(); i++) { + const OneofDescriptor* oneof_decl = message->field(i)->containing_oneof(); + if (oneof_decl != nullptr) { + // Make sure fields belonging to the same oneof are defined consecutively. + // This enables optimizations in codegens and reflection libraries to + // skip fields in the oneof group, as only one of the field can be set. + // Note that field_count() returns how many fields in this oneof we have + // seen so far. field_count() > 0 guarantees that i > 0, so field(i-1) is + // safe. + if (oneof_decl->field_count() > 0 && + message->field(i - 1)->containing_oneof() != oneof_decl) { + AddError(message->full_name() + "." + message->field(i - 1)->name(), + proto.field(i - 1), DescriptorPool::ErrorCollector::TYPE, + strings::Substitute( + "Fields in the same oneof must be defined consecutively. " + "\"$0\" cannot be defined before the completion of the " + "\"$1\" oneof definition.", + message->field(i - 1)->name(), oneof_decl->name())); + } + // Must go through oneof_decls_ array to get a non-const version of the + // OneofDescriptor. + auto& out_oneof_decl = message->oneof_decls_[oneof_decl->index()]; + if (out_oneof_decl.field_count_ == 0) { + out_oneof_decl.fields_ = message->field(i); + } + + if (!had_errors_) { + // Verify that they are contiguous. + // This is assumed by OneofDescriptor::field(i). + // But only if there are no errors. + GOOGLE_CHECK_EQ(out_oneof_decl.fields_ + out_oneof_decl.field_count_, + message->field(i)); + } + ++out_oneof_decl.field_count_; + } + } + + // Then verify the sizes. + for (int i = 0; i < message->oneof_decl_count(); i++) { + OneofDescriptor* oneof_decl = &message->oneof_decls_[i]; + + if (oneof_decl->field_count() == 0) { + AddError(message->full_name() + "." + oneof_decl->name(), + proto.oneof_decl(i), DescriptorPool::ErrorCollector::NAME, + "Oneof must have at least one field."); + } + + if (oneof_decl->options_ == nullptr) { + oneof_decl->options_ = &OneofOptions::default_instance(); + } + } + + for (int i = 0; i < message->field_count(); i++) { + const FieldDescriptor* field = message->field(i); + if (field->proto3_optional_) { + if (!field->containing_oneof() || + !field->containing_oneof()->is_synthetic()) { + AddError(message->full_name(), proto.field(i), + DescriptorPool::ErrorCollector::OTHER, + "Fields with proto3_optional set must be " + "a member of a one-field oneof"); + } + } + } + + // Synthetic oneofs must be last. + int first_synthetic = -1; + for (int i = 0; i < message->oneof_decl_count(); i++) { + const OneofDescriptor* oneof = message->oneof_decl(i); + if (oneof->is_synthetic()) { + if (first_synthetic == -1) { + first_synthetic = i; + } + } else { + if (first_synthetic != -1) { + AddError(message->full_name(), proto.oneof_decl(i), + DescriptorPool::ErrorCollector::OTHER, + "Synthetic oneofs must be after all other oneofs"); + } + } + } + + if (first_synthetic == -1) { + message->real_oneof_decl_count_ = message->oneof_decl_count_; + } else { + message->real_oneof_decl_count_ = first_synthetic; + } +} + +void DescriptorBuilder::CrossLinkExtensionRange( + Descriptor::ExtensionRange* range, + const DescriptorProto::ExtensionRange& /*proto*/) { + if (range->options_ == nullptr) { + range->options_ = &ExtensionRangeOptions::default_instance(); + } +} + +void DescriptorBuilder::CrossLinkField(FieldDescriptor* field, + const FieldDescriptorProto& proto) { + if (field->options_ == nullptr) { + field->options_ = &FieldOptions::default_instance(); + } + + if (proto.has_extendee()) { + Symbol extendee = + LookupSymbol(proto.extendee(), field->full_name(), + DescriptorPool::PLACEHOLDER_EXTENDABLE_MESSAGE); + if (extendee.IsNull()) { + AddNotDefinedError(field->full_name(), proto, + DescriptorPool::ErrorCollector::EXTENDEE, + proto.extendee()); + return; + } else if (extendee.type() != Symbol::MESSAGE) { + AddError(field->full_name(), proto, + DescriptorPool::ErrorCollector::EXTENDEE, + "\"" + proto.extendee() + "\" is not a message type."); + return; + } + field->containing_type_ = extendee.descriptor(); + + const Descriptor::ExtensionRange* extension_range = + field->containing_type()->FindExtensionRangeContainingNumber( + field->number()); + + if (extension_range == nullptr) { + // Set of valid extension numbers for MessageSet is different (< 2^32) + // from other extendees (< 2^29). If unknown deps are allowed, we may not + // have that information, and wrongly deem the extension as invalid. + auto skip_check = get_allow_unknown(pool_) && + proto.extendee() == "google.protobuf.bridge.MessageSet"; + if (!skip_check) { + AddError(field->full_name(), proto, + DescriptorPool::ErrorCollector::NUMBER, + strings::Substitute("\"$0\" does not declare $1 as an " + "extension number.", + field->containing_type()->full_name(), + field->number())); + } + } + } + + if (field->containing_oneof() != nullptr) { + if (field->label() != FieldDescriptor::LABEL_OPTIONAL) { + // Note that this error will never happen when parsing .proto files. + // It can only happen if you manually construct a FileDescriptorProto + // that is incorrect. + AddError(field->full_name(), proto, DescriptorPool::ErrorCollector::NAME, + "Fields of oneofs must themselves have label LABEL_OPTIONAL."); + } + } + + if (proto.has_type_name()) { + // Assume we are expecting a message type unless the proto contains some + // evidence that it expects an enum type. This only makes a difference if + // we end up creating a placeholder. + bool expecting_enum = (proto.type() == FieldDescriptorProto::TYPE_ENUM) || + proto.has_default_value(); + + // In case of weak fields we force building the dependency. We need to know + // if the type exist or not. If it doesn't exist we substitute Empty which + // should only be done if the type can't be found in the generated pool. + // TODO(gerbens) Ideally we should query the database directly to check + // if weak fields exist or not so that we don't need to force building + // weak dependencies. However the name lookup rules for symbols are + // somewhat complicated, so I defer it too another CL. + bool is_weak = !pool_->enforce_weak_ && proto.options().weak(); + bool is_lazy = pool_->lazily_build_dependencies_ && !is_weak; + + Symbol type = + LookupSymbol(proto.type_name(), field->full_name(), + expecting_enum ? DescriptorPool::PLACEHOLDER_ENUM + : DescriptorPool::PLACEHOLDER_MESSAGE, + LOOKUP_TYPES, !is_lazy); + + if (type.IsNull()) { + if (is_lazy) { + // Save the symbol names for later for lookup, and allocate the once + // object needed for the accessors. + const std::string& name = proto.type_name(); + + int name_sizes = static_cast<int>(name.size() + 1 + + proto.default_value().size() + 1); + + field->type_once_ = ::new (tables_->AllocateBytes(static_cast<int>( + sizeof(internal::once_flag) + name_sizes))) internal::once_flag{}; + char* names = reinterpret_cast<char*>(field->type_once_ + 1); + + memcpy(names, name.c_str(), name.size() + 1); + memcpy(names + name.size() + 1, proto.default_value().c_str(), + proto.default_value().size() + 1); + + // AddFieldByNumber and AddExtension are done later in this function, + // and can/must be done if the field type was not found. The related + // error checking is not necessary when in lazily_build_dependencies_ + // mode, and can't be done without building the type's descriptor, + // which we don't want to do. + file_tables_->AddFieldByNumber(field); + if (field->is_extension()) { + tables_->AddExtension(field); + } + return; + } else { + // If the type is a weak type, we change the type to a google.protobuf.Empty + // field. + if (is_weak) { + type = FindSymbol(kNonLinkedWeakMessageReplacementName); + } + if (type.IsNull()) { + AddNotDefinedError(field->full_name(), proto, + DescriptorPool::ErrorCollector::TYPE, + proto.type_name()); + return; + } + } + } + + if (!proto.has_type()) { + // Choose field type based on symbol. + if (type.type() == Symbol::MESSAGE) { + field->type_ = FieldDescriptor::TYPE_MESSAGE; + } else if (type.type() == Symbol::ENUM) { + field->type_ = FieldDescriptor::TYPE_ENUM; + } else { + AddError(field->full_name(), proto, + DescriptorPool::ErrorCollector::TYPE, + "\"" + proto.type_name() + "\" is not a type."); + return; + } + } + + if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { + field->type_descriptor_.message_type = type.descriptor(); + if (field->type_descriptor_.message_type == nullptr) { + AddError(field->full_name(), proto, + DescriptorPool::ErrorCollector::TYPE, + "\"" + proto.type_name() + "\" is not a message type."); + return; + } + + if (field->has_default_value()) { + AddError(field->full_name(), proto, + DescriptorPool::ErrorCollector::DEFAULT_VALUE, + "Messages can't have default values."); + } + } else if (field->cpp_type() == FieldDescriptor::CPPTYPE_ENUM) { + field->type_descriptor_.enum_type = type.enum_descriptor(); + if (field->type_descriptor_.enum_type == nullptr) { + AddError(field->full_name(), proto, + DescriptorPool::ErrorCollector::TYPE, + "\"" + proto.type_name() + "\" is not an enum type."); + return; + } + + if (field->enum_type()->is_placeholder_) { + // We can't look up default values for placeholder types. We'll have + // to just drop them. + field->has_default_value_ = false; + } + + if (field->has_default_value()) { + // Ensure that the default value is an identifier. Parser cannot always + // verify this because it does not have complete type information. + // N.B. that this check yields better error messages but is not + // necessary for correctness (an enum symbol must be a valid identifier + // anyway), only for better errors. + if (!io::Tokenizer::IsIdentifier(proto.default_value())) { + AddError(field->full_name(), proto, + DescriptorPool::ErrorCollector::DEFAULT_VALUE, + "Default value for an enum field must be an identifier."); + } else { + // We can't just use field->enum_type()->FindValueByName() here + // because that locks the pool's mutex, which we have already locked + // at this point. + const EnumValueDescriptor* default_value = + LookupSymbolNoPlaceholder(proto.default_value(), + field->enum_type()->full_name()) + .enum_value_descriptor(); + + if (default_value != nullptr && + default_value->type() == field->enum_type()) { + field->default_value_enum_ = default_value; + } else { + AddError(field->full_name(), proto, + DescriptorPool::ErrorCollector::DEFAULT_VALUE, + "Enum type \"" + field->enum_type()->full_name() + + "\" has no value named \"" + proto.default_value() + + "\"."); + } + } + } else if (field->enum_type()->value_count() > 0) { + // All enums must have at least one value, or we would have reported + // an error elsewhere. We use the first defined value as the default + // if a default is not explicitly defined. + field->default_value_enum_ = field->enum_type()->value(0); + } + } else { + AddError(field->full_name(), proto, DescriptorPool::ErrorCollector::TYPE, + "Field with primitive type has type_name."); + } + } else { + if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE || + field->cpp_type() == FieldDescriptor::CPPTYPE_ENUM) { + AddError(field->full_name(), proto, DescriptorPool::ErrorCollector::TYPE, + "Field with message or enum type missing type_name."); + } + } + + // Add the field to the fields-by-number table. + // Note: We have to do this *after* cross-linking because extensions do not + // know their containing type until now. If we're in + // lazily_build_dependencies_ mode, we're guaranteed there's no errors, so no + // risk to calling containing_type() or other accessors that will build + // dependencies. + if (!file_tables_->AddFieldByNumber(field)) { + const FieldDescriptor* conflicting_field = file_tables_->FindFieldByNumber( + field->containing_type(), field->number()); + std::string containing_type_name = + field->containing_type() == nullptr + ? "unknown" + : field->containing_type()->full_name(); + if (field->is_extension()) { + AddError(field->full_name(), proto, + DescriptorPool::ErrorCollector::NUMBER, + strings::Substitute("Extension number $0 has already been used " + "in \"$1\" by extension \"$2\".", + field->number(), containing_type_name, + conflicting_field->full_name())); + } else { + AddError(field->full_name(), proto, + DescriptorPool::ErrorCollector::NUMBER, + strings::Substitute("Field number $0 has already been used in " + "\"$1\" by field \"$2\".", + field->number(), containing_type_name, + conflicting_field->name())); + } + } else { + if (field->is_extension()) { + if (!tables_->AddExtension(field)) { + const FieldDescriptor* conflicting_field = + tables_->FindExtension(field->containing_type(), field->number()); + std::string containing_type_name = + field->containing_type() == nullptr + ? "unknown" + : field->containing_type()->full_name(); + std::string error_msg = strings::Substitute( + "Extension number $0 has already been used in \"$1\" by extension " + "\"$2\" defined in $3.", + field->number(), containing_type_name, + conflicting_field->full_name(), conflicting_field->file()->name()); + // Conflicting extension numbers should be an error. However, before + // turning this into an error we need to fix all existing broken + // protos first. + // TODO(xiaofeng): Change this to an error. + AddWarning(field->full_name(), proto, + DescriptorPool::ErrorCollector::NUMBER, error_msg); + } + } + } +} + +void DescriptorBuilder::CrossLinkEnum(EnumDescriptor* enum_type, + const EnumDescriptorProto& proto) { + if (enum_type->options_ == nullptr) { + enum_type->options_ = &EnumOptions::default_instance(); + } + + for (int i = 0; i < enum_type->value_count(); i++) { + CrossLinkEnumValue(&enum_type->values_[i], proto.value(i)); + } +} + +void DescriptorBuilder::CrossLinkEnumValue( + EnumValueDescriptor* enum_value, + const EnumValueDescriptorProto& /* proto */) { + if (enum_value->options_ == nullptr) { + enum_value->options_ = &EnumValueOptions::default_instance(); + } +} + +void DescriptorBuilder::CrossLinkService(ServiceDescriptor* service, + const ServiceDescriptorProto& proto) { + if (service->options_ == nullptr) { + service->options_ = &ServiceOptions::default_instance(); + } + + for (int i = 0; i < service->method_count(); i++) { + CrossLinkMethod(&service->methods_[i], proto.method(i)); + } +} + +void DescriptorBuilder::CrossLinkMethod(MethodDescriptor* method, + const MethodDescriptorProto& proto) { + if (method->options_ == nullptr) { + method->options_ = &MethodOptions::default_instance(); + } + + Symbol input_type = + LookupSymbol(proto.input_type(), method->full_name(), + DescriptorPool::PLACEHOLDER_MESSAGE, LOOKUP_ALL, + !pool_->lazily_build_dependencies_); + if (input_type.IsNull()) { + if (!pool_->lazily_build_dependencies_) { + AddNotDefinedError(method->full_name(), proto, + DescriptorPool::ErrorCollector::INPUT_TYPE, + proto.input_type()); + } else { + method->input_type_.SetLazy(proto.input_type(), file_); + } + } else if (input_type.type() != Symbol::MESSAGE) { + AddError(method->full_name(), proto, + DescriptorPool::ErrorCollector::INPUT_TYPE, + "\"" + proto.input_type() + "\" is not a message type."); + } else { + method->input_type_.Set(input_type.descriptor()); + } + + Symbol output_type = + LookupSymbol(proto.output_type(), method->full_name(), + DescriptorPool::PLACEHOLDER_MESSAGE, LOOKUP_ALL, + !pool_->lazily_build_dependencies_); + if (output_type.IsNull()) { + if (!pool_->lazily_build_dependencies_) { + AddNotDefinedError(method->full_name(), proto, + DescriptorPool::ErrorCollector::OUTPUT_TYPE, + proto.output_type()); + } else { + method->output_type_.SetLazy(proto.output_type(), file_); + } + } else if (output_type.type() != Symbol::MESSAGE) { + AddError(method->full_name(), proto, + DescriptorPool::ErrorCollector::OUTPUT_TYPE, + "\"" + proto.output_type() + "\" is not a message type."); + } else { + method->output_type_.Set(output_type.descriptor()); + } +} + +void DescriptorBuilder::SuggestFieldNumbers(FileDescriptor* file, + const FileDescriptorProto& proto) { + for (int message_index = 0; message_index < file->message_type_count(); + message_index++) { + const Descriptor* message = &file->message_types_[message_index]; + auto* hints = FindOrNull(message_hints_, message); + if (!hints) continue; + constexpr int kMaxSuggestions = 3; + int fields_to_suggest = std::min(kMaxSuggestions, hints->fields_to_suggest); + if (fields_to_suggest <= 0) continue; + struct Range { + int from; + int to; + }; + std::vector<Range> used_ordinals; + auto add_ordinal = [&](int ordinal) { + if (ordinal <= 0 || ordinal > FieldDescriptor::kMaxNumber) return; + if (!used_ordinals.empty() && + ordinal == used_ordinals.back().to) { + used_ordinals.back().to = ordinal + 1; + } else { + used_ordinals.push_back({ordinal, ordinal + 1}); + } + }; + auto add_range = [&](int from, int to) { + from = std::max(0, std::min(FieldDescriptor::kMaxNumber + 1, from)); + to = std::max(0, std::min(FieldDescriptor::kMaxNumber + 1, to)); + if (from >= to) return; + used_ordinals.push_back({from, to}); + }; + for (int i = 0; i < message->field_count(); i++) { + add_ordinal(message->field(i)->number()); + } + for (int i = 0; i < message->extension_count(); i++) { + add_ordinal(message->extension(i)->number()); + } + for (int i = 0; i < message->reserved_range_count(); i++) { + auto range = message->reserved_range(i); + add_range(range->start, range->end); + } + for (int i = 0; i < message->extension_range_count(); i++) { + auto range = message->extension_range(i); + add_range(range->start, range->end); + } + used_ordinals.push_back( + {FieldDescriptor::kMaxNumber, FieldDescriptor::kMaxNumber + 1}); + used_ordinals.push_back({FieldDescriptor::kFirstReservedNumber, + FieldDescriptor::kLastReservedNumber}); + std::sort(used_ordinals.begin(), used_ordinals.end(), + [](Range lhs, Range rhs) { + return std::tie(lhs.from, lhs.to) < std::tie(rhs.from, rhs.to); + }); + int current_ordinal = 1; + std::stringstream id_list; + id_list << "Suggested field numbers for " << message->full_name() << ": "; + const char* separator = ""; + for (auto& current_range : used_ordinals) { + while (current_ordinal < current_range.from && fields_to_suggest > 0) { + id_list << separator << current_ordinal++; + separator = ", "; + fields_to_suggest--; + } + if (fields_to_suggest == 0) break; + current_ordinal = std::max(current_ordinal, current_range.to); + } + if (hints->first_reason) { + AddError(message->full_name(), *hints->first_reason, + hints->first_reason_location, id_list.str()); + } + } +} + +// ------------------------------------------------------------------- + +#define VALIDATE_OPTIONS_FROM_ARRAY(descriptor, array_name, type) \ + for (int i = 0; i < descriptor->array_name##_count(); ++i) { \ + Validate##type##Options(descriptor->array_name##s_ + i, \ + proto.array_name(i)); \ + } + +// Determine if the file uses optimize_for = LITE_RUNTIME, being careful to +// avoid problems that exist at init time. +static bool IsLite(const FileDescriptor* file) { + // TODO(kenton): I don't even remember how many of these conditions are + // actually possible. I'm just being super-safe. + return file != nullptr && + &file->options() != &FileOptions::default_instance() && + file->options().optimize_for() == FileOptions::LITE_RUNTIME; +} + +void DescriptorBuilder::ValidateFileOptions(FileDescriptor* file, + const FileDescriptorProto& proto) { + VALIDATE_OPTIONS_FROM_ARRAY(file, message_type, Message); + VALIDATE_OPTIONS_FROM_ARRAY(file, enum_type, Enum); + VALIDATE_OPTIONS_FROM_ARRAY(file, service, Service); + VALIDATE_OPTIONS_FROM_ARRAY(file, extension, Field); + + // Lite files can only be imported by other Lite files. + if (!IsLite(file)) { + for (int i = 0; i < file->dependency_count(); i++) { + if (IsLite(file->dependency(i))) { + AddError( + file->dependency(i)->name(), proto, + DescriptorPool::ErrorCollector::IMPORT, + "Files that do not use optimize_for = LITE_RUNTIME cannot import " + "files which do use this option. This file is not lite, but it " + "imports \"" + + file->dependency(i)->name() + "\" which is."); + break; + } + } + } + if (file->syntax() == FileDescriptor::SYNTAX_PROTO3) { + ValidateProto3(file, proto); + } +} + +void DescriptorBuilder::ValidateProto3(FileDescriptor* file, + const FileDescriptorProto& proto) { + for (int i = 0; i < file->extension_count(); ++i) { + ValidateProto3Field(file->extensions_ + i, proto.extension(i)); + } + for (int i = 0; i < file->message_type_count(); ++i) { + ValidateProto3Message(file->message_types_ + i, proto.message_type(i)); + } + for (int i = 0; i < file->enum_type_count(); ++i) { + ValidateProto3Enum(file->enum_types_ + i, proto.enum_type(i)); + } +} + +static std::string ToLowercaseWithoutUnderscores(const std::string& name) { + std::string result; + for (char character : name) { + if (character != '_') { + if (character >= 'A' && character <= 'Z') { + result.push_back(character - 'A' + 'a'); + } else { + result.push_back(character); + } + } + } + return result; +} + +void DescriptorBuilder::ValidateProto3Message(Descriptor* message, + const DescriptorProto& proto) { + for (int i = 0; i < message->nested_type_count(); ++i) { + ValidateProto3Message(message->nested_types_ + i, proto.nested_type(i)); + } + for (int i = 0; i < message->enum_type_count(); ++i) { + ValidateProto3Enum(message->enum_types_ + i, proto.enum_type(i)); + } + for (int i = 0; i < message->field_count(); ++i) { + ValidateProto3Field(message->fields_ + i, proto.field(i)); + } + for (int i = 0; i < message->extension_count(); ++i) { + ValidateProto3Field(message->extensions_ + i, proto.extension(i)); + } + if (message->extension_range_count() > 0) { + AddError(message->full_name(), proto.extension_range(0), + DescriptorPool::ErrorCollector::NUMBER, + "Extension ranges are not allowed in proto3."); + } + if (message->options().message_set_wire_format()) { + // Using MessageSet doesn't make sense since we disallow extensions. + AddError(message->full_name(), proto, DescriptorPool::ErrorCollector::NAME, + "MessageSet is not supported in proto3."); + } + + // In proto3, we reject field names if they conflict in camelCase. + // Note that we currently enforce a stricter rule: Field names must be + // unique after being converted to lowercase with underscores removed. + std::map<std::string, const FieldDescriptor*> name_to_field; + for (int i = 0; i < message->field_count(); ++i) { + std::string lowercase_name = + ToLowercaseWithoutUnderscores(message->field(i)->name()); + if (name_to_field.find(lowercase_name) != name_to_field.end()) { + AddError(message->full_name(), proto.field(i), + DescriptorPool::ErrorCollector::NAME, + "The JSON camel-case name of field \"" + + message->field(i)->name() + "\" conflicts with field \"" + + name_to_field[lowercase_name]->name() + "\". This is not " + + "allowed in proto3."); + } else { + name_to_field[lowercase_name] = message->field(i); + } + } +} + +void DescriptorBuilder::ValidateProto3Field(FieldDescriptor* field, + const FieldDescriptorProto& proto) { + if (field->is_extension() && + !AllowedExtendeeInProto3(field->containing_type()->full_name())) { + AddError(field->full_name(), proto, + DescriptorPool::ErrorCollector::EXTENDEE, + "Extensions in proto3 are only allowed for defining options."); + } + if (field->is_required()) { + AddError(field->full_name(), proto, DescriptorPool::ErrorCollector::TYPE, + "Required fields are not allowed in proto3."); + } + if (field->has_default_value()) { + AddError(field->full_name(), proto, + DescriptorPool::ErrorCollector::DEFAULT_VALUE, + "Explicit default values are not allowed in proto3."); + } + if (field->cpp_type() == FieldDescriptor::CPPTYPE_ENUM && + field->enum_type() && + field->enum_type()->file()->syntax() != FileDescriptor::SYNTAX_PROTO3 && + field->enum_type()->file()->syntax() != FileDescriptor::SYNTAX_UNKNOWN) { + // Proto3 messages can only use Proto3 enum types; otherwise we can't + // guarantee that the default value is zero. + AddError(field->full_name(), proto, DescriptorPool::ErrorCollector::TYPE, + "Enum type \"" + field->enum_type()->full_name() + + "\" is not a proto3 enum, but is used in \"" + + field->containing_type()->full_name() + + "\" which is a proto3 message type."); + } + if (field->type() == FieldDescriptor::TYPE_GROUP) { + AddError(field->full_name(), proto, DescriptorPool::ErrorCollector::TYPE, + "Groups are not supported in proto3 syntax."); + } +} + +void DescriptorBuilder::ValidateProto3Enum(EnumDescriptor* enm, + const EnumDescriptorProto& proto) { + if (enm->value_count() > 0 && enm->value(0)->number() != 0) { + AddError(enm->full_name(), proto.value(0), + DescriptorPool::ErrorCollector::NUMBER, + "The first enum value must be zero in proto3."); + } +} + +void DescriptorBuilder::ValidateMessageOptions(Descriptor* message, + const DescriptorProto& proto) { + VALIDATE_OPTIONS_FROM_ARRAY(message, field, Field); + VALIDATE_OPTIONS_FROM_ARRAY(message, nested_type, Message); + VALIDATE_OPTIONS_FROM_ARRAY(message, enum_type, Enum); + VALIDATE_OPTIONS_FROM_ARRAY(message, extension, Field); + + const int64_t max_extension_range = + static_cast<int64_t>(message->options().message_set_wire_format() + ? std::numeric_limits<int32_t>::max() + : FieldDescriptor::kMaxNumber); + for (int i = 0; i < message->extension_range_count(); ++i) { + if (message->extension_range(i)->end > max_extension_range + 1) { + AddError(message->full_name(), proto.extension_range(i), + DescriptorPool::ErrorCollector::NUMBER, + strings::Substitute("Extension numbers cannot be greater than $0.", + max_extension_range)); + } + + ValidateExtensionRangeOptions(message->full_name(), + message->extension_ranges_ + i, + proto.extension_range(i)); + } +} + + +void DescriptorBuilder::ValidateFieldOptions( + FieldDescriptor* field, const FieldDescriptorProto& proto) { + if (pool_->lazily_build_dependencies_ && (!field || !field->message_type())) { + return; + } + // Only message type fields may be lazy. + if (field->options().lazy() || field->options().unverified_lazy()) { + if (field->type() != FieldDescriptor::TYPE_MESSAGE) { + AddError(field->full_name(), proto, DescriptorPool::ErrorCollector::TYPE, + "[lazy = true] can only be specified for submessage fields."); + } + } + + // Only repeated primitive fields may be packed. + if (field->options().packed() && !field->is_packable()) { + AddError( + field->full_name(), proto, DescriptorPool::ErrorCollector::TYPE, + "[packed = true] can only be specified for repeated primitive fields."); + } + + // Note: Default instance may not yet be initialized here, so we have to + // avoid reading from it. + if (field->containing_type_ != nullptr && + &field->containing_type()->options() != + &MessageOptions::default_instance() && + field->containing_type()->options().message_set_wire_format()) { + if (field->is_extension()) { + if (!field->is_optional() || + field->type() != FieldDescriptor::TYPE_MESSAGE) { + AddError(field->full_name(), proto, + DescriptorPool::ErrorCollector::TYPE, + "Extensions of MessageSets must be optional messages."); + } + } else { + AddError(field->full_name(), proto, DescriptorPool::ErrorCollector::NAME, + "MessageSets cannot have fields, only extensions."); + } + } + + // Lite extensions can only be of Lite types. + if (IsLite(field->file()) && field->containing_type_ != nullptr && + !IsLite(field->containing_type()->file())) { + AddError(field->full_name(), proto, + DescriptorPool::ErrorCollector::EXTENDEE, + "Extensions to non-lite types can only be declared in non-lite " + "files. Note that you cannot extend a non-lite type to contain " + "a lite type, but the reverse is allowed."); + } + + // Validate map types. + if (field->is_map()) { + if (!ValidateMapEntry(field, proto)) { + AddError(field->full_name(), proto, DescriptorPool::ErrorCollector::TYPE, + "map_entry should not be set explicitly. Use map<KeyType, " + "ValueType> instead."); + } + } + + ValidateJSType(field, proto); + + // json_name option is not allowed on extension fields. Note that the + // json_name field in FieldDescriptorProto is always populated by protoc + // when it sends descriptor data to plugins (calculated from field name if + // the option is not explicitly set) so we can't rely on its presence to + // determine whether the json_name option is set on the field. Here we + // compare it against the default calculated json_name value and consider + // the option set if they are different. This won't catch the case when + // an user explicitly sets json_name to the default value, but should be + // good enough to catch common misuses. + if (field->is_extension() && + (field->has_json_name() && + field->json_name() != ToJsonName(field->name()))) { + AddError(field->full_name(), proto, + DescriptorPool::ErrorCollector::OPTION_NAME, + "option json_name is not allowed on extension fields."); + } + +} + +void DescriptorBuilder::ValidateEnumOptions(EnumDescriptor* enm, + const EnumDescriptorProto& proto) { + VALIDATE_OPTIONS_FROM_ARRAY(enm, value, EnumValue); + if (!enm->options().has_allow_alias() || !enm->options().allow_alias()) { + std::map<int, std::string> used_values; + for (int i = 0; i < enm->value_count(); ++i) { + const EnumValueDescriptor* enum_value = enm->value(i); + if (used_values.find(enum_value->number()) != used_values.end()) { + std::string error = + "\"" + enum_value->full_name() + + "\" uses the same enum value as \"" + + used_values[enum_value->number()] + + "\". If this is intended, set " + "'option allow_alias = true;' to the enum definition."; + if (!enm->options().allow_alias()) { + // Generate error if duplicated enum values are explicitly disallowed. + AddError(enm->full_name(), proto.value(i), + DescriptorPool::ErrorCollector::NUMBER, error); + } + } else { + used_values[enum_value->number()] = enum_value->full_name(); + } + } + } +} + +void DescriptorBuilder::ValidateEnumValueOptions( + EnumValueDescriptor* /* enum_value */, + const EnumValueDescriptorProto& /* proto */) { + // Nothing to do so far. +} + +void DescriptorBuilder::ValidateExtensionRangeOptions( + const std::string& full_name, Descriptor::ExtensionRange* extension_range, + const DescriptorProto_ExtensionRange& proto) { + (void)full_name; // Parameter is used by Google-internal code. + (void)extension_range; // Parameter is used by Google-internal code. +} + +void DescriptorBuilder::ValidateServiceOptions( + ServiceDescriptor* service, const ServiceDescriptorProto& proto) { + if (IsLite(service->file()) && + (service->file()->options().cc_generic_services() || + service->file()->options().java_generic_services())) { + AddError(service->full_name(), proto, DescriptorPool::ErrorCollector::NAME, + "Files with optimize_for = LITE_RUNTIME cannot define services " + "unless you set both options cc_generic_services and " + "java_generic_services to false."); + } + + VALIDATE_OPTIONS_FROM_ARRAY(service, method, Method); +} + +void DescriptorBuilder::ValidateMethodOptions( + MethodDescriptor* /* method */, const MethodDescriptorProto& /* proto */) { + // Nothing to do so far. +} + +bool DescriptorBuilder::ValidateMapEntry(FieldDescriptor* field, + const FieldDescriptorProto& proto) { + const Descriptor* message = field->message_type(); + if ( // Must not contain extensions, extension range or nested message or + // enums + message->extension_count() != 0 || + field->label() != FieldDescriptor::LABEL_REPEATED || + message->extension_range_count() != 0 || + message->nested_type_count() != 0 || message->enum_type_count() != 0 || + // Must contain exactly two fields + message->field_count() != 2 || + // Field name and message name must match + message->name() != ToCamelCase(field->name(), false) + "Entry" || + // Entry message must be in the same containing type of the field. + field->containing_type() != message->containing_type()) { + return false; + } + + const FieldDescriptor* key = message->map_key(); + const FieldDescriptor* value = message->map_value(); + if (key->label() != FieldDescriptor::LABEL_OPTIONAL || key->number() != 1 || + key->name() != "key") { + return false; + } + if (value->label() != FieldDescriptor::LABEL_OPTIONAL || + value->number() != 2 || value->name() != "value") { + return false; + } + + // Check key types are legal. + switch (key->type()) { + case FieldDescriptor::TYPE_ENUM: + AddError(field->full_name(), proto, DescriptorPool::ErrorCollector::TYPE, + "Key in map fields cannot be enum types."); + break; + case FieldDescriptor::TYPE_FLOAT: + case FieldDescriptor::TYPE_DOUBLE: + case FieldDescriptor::TYPE_MESSAGE: + case FieldDescriptor::TYPE_GROUP: + case FieldDescriptor::TYPE_BYTES: + AddError( + field->full_name(), proto, DescriptorPool::ErrorCollector::TYPE, + "Key in map fields cannot be float/double, bytes or message types."); + break; + case FieldDescriptor::TYPE_BOOL: + case FieldDescriptor::TYPE_INT32: + case FieldDescriptor::TYPE_INT64: + case FieldDescriptor::TYPE_SINT32: + case FieldDescriptor::TYPE_SINT64: + case FieldDescriptor::TYPE_STRING: + case FieldDescriptor::TYPE_UINT32: + case FieldDescriptor::TYPE_UINT64: + case FieldDescriptor::TYPE_FIXED32: + case FieldDescriptor::TYPE_FIXED64: + case FieldDescriptor::TYPE_SFIXED32: + case FieldDescriptor::TYPE_SFIXED64: + // Legal cases + break; + // Do not add a default, so that the compiler will complain when new types + // are added. + } + + if (value->type() == FieldDescriptor::TYPE_ENUM) { + if (value->enum_type()->value(0)->number() != 0) { + AddError(field->full_name(), proto, DescriptorPool::ErrorCollector::TYPE, + "Enum value in map must define 0 as the first value."); + } + } + + return true; +} + +void DescriptorBuilder::DetectMapConflicts(const Descriptor* message, + const DescriptorProto& proto) { + std::map<std::string, const Descriptor*> seen_types; + for (int i = 0; i < message->nested_type_count(); ++i) { + const Descriptor* nested = message->nested_type(i); + std::pair<std::map<std::string, const Descriptor*>::iterator, bool> result = + seen_types.insert(std::make_pair(nested->name(), nested)); + if (!result.second) { + if (result.first->second->options().map_entry() || + nested->options().map_entry()) { + AddError(message->full_name(), proto, + DescriptorPool::ErrorCollector::NAME, + "Expanded map entry type " + nested->name() + + " conflicts with an existing nested message type."); + break; + } + } + // Recursively test on the nested types. + DetectMapConflicts(message->nested_type(i), proto.nested_type(i)); + } + // Check for conflicted field names. + for (int i = 0; i < message->field_count(); ++i) { + const FieldDescriptor* field = message->field(i); + std::map<std::string, const Descriptor*>::iterator iter = + seen_types.find(field->name()); + if (iter != seen_types.end() && iter->second->options().map_entry()) { + AddError(message->full_name(), proto, + DescriptorPool::ErrorCollector::NAME, + "Expanded map entry type " + iter->second->name() + + " conflicts with an existing field."); + } + } + // Check for conflicted enum names. + for (int i = 0; i < message->enum_type_count(); ++i) { + const EnumDescriptor* enum_desc = message->enum_type(i); + std::map<std::string, const Descriptor*>::iterator iter = + seen_types.find(enum_desc->name()); + if (iter != seen_types.end() && iter->second->options().map_entry()) { + AddError(message->full_name(), proto, + DescriptorPool::ErrorCollector::NAME, + "Expanded map entry type " + iter->second->name() + + " conflicts with an existing enum type."); + } + } + // Check for conflicted oneof names. + for (int i = 0; i < message->oneof_decl_count(); ++i) { + const OneofDescriptor* oneof_desc = message->oneof_decl(i); + std::map<std::string, const Descriptor*>::iterator iter = + seen_types.find(oneof_desc->name()); + if (iter != seen_types.end() && iter->second->options().map_entry()) { + AddError(message->full_name(), proto, + DescriptorPool::ErrorCollector::NAME, + "Expanded map entry type " + iter->second->name() + + " conflicts with an existing oneof type."); + } + } +} + +void DescriptorBuilder::ValidateJSType(FieldDescriptor* field, + const FieldDescriptorProto& proto) { + FieldOptions::JSType jstype = field->options().jstype(); + // The default is always acceptable. + if (jstype == FieldOptions::JS_NORMAL) { + return; + } + + switch (field->type()) { + // Integral 64-bit types may be represented as JavaScript numbers or + // strings. + case FieldDescriptor::TYPE_UINT64: + case FieldDescriptor::TYPE_INT64: + case FieldDescriptor::TYPE_SINT64: + case FieldDescriptor::TYPE_FIXED64: + case FieldDescriptor::TYPE_SFIXED64: + if (jstype == FieldOptions::JS_STRING || + jstype == FieldOptions::JS_NUMBER) { + return; + } + AddError(field->full_name(), proto, DescriptorPool::ErrorCollector::TYPE, + "Illegal jstype for int64, uint64, sint64, fixed64 " + "or sfixed64 field: " + + FieldOptions_JSType_descriptor()->value(jstype)->name()); + break; + + // No other types permit a jstype option. + default: + AddError(field->full_name(), proto, DescriptorPool::ErrorCollector::TYPE, + "jstype is only allowed on int64, uint64, sint64, fixed64 " + "or sfixed64 fields."); + break; + } +} + +#undef VALIDATE_OPTIONS_FROM_ARRAY + +// ------------------------------------------------------------------- + +DescriptorBuilder::OptionInterpreter::OptionInterpreter( + DescriptorBuilder* builder) + : builder_(builder) { + GOOGLE_CHECK(builder_); +} + +DescriptorBuilder::OptionInterpreter::~OptionInterpreter() {} + +bool DescriptorBuilder::OptionInterpreter::InterpretOptions( + OptionsToInterpret* options_to_interpret) { + // Note that these may be in different pools, so we can't use the same + // descriptor and reflection objects on both. + Message* options = options_to_interpret->options; + const Message* original_options = options_to_interpret->original_options; + + bool failed = false; + options_to_interpret_ = options_to_interpret; + + // Find the uninterpreted_option field in the mutable copy of the options + // and clear them, since we're about to interpret them. + const FieldDescriptor* uninterpreted_options_field = + options->GetDescriptor()->FindFieldByName("uninterpreted_option"); + GOOGLE_CHECK(uninterpreted_options_field != nullptr) + << "No field named \"uninterpreted_option\" in the Options proto."; + options->GetReflection()->ClearField(options, uninterpreted_options_field); + + std::vector<int> src_path = options_to_interpret->element_path; + src_path.push_back(uninterpreted_options_field->number()); + + // Find the uninterpreted_option field in the original options. + const FieldDescriptor* original_uninterpreted_options_field = + original_options->GetDescriptor()->FindFieldByName( + "uninterpreted_option"); + GOOGLE_CHECK(original_uninterpreted_options_field != nullptr) + << "No field named \"uninterpreted_option\" in the Options proto."; + + const int num_uninterpreted_options = + original_options->GetReflection()->FieldSize( + *original_options, original_uninterpreted_options_field); + for (int i = 0; i < num_uninterpreted_options; ++i) { + src_path.push_back(i); + uninterpreted_option_ = down_cast<const UninterpretedOption*>( + &original_options->GetReflection()->GetRepeatedMessage( + *original_options, original_uninterpreted_options_field, i)); + if (!InterpretSingleOption(options, src_path, + options_to_interpret->element_path)) { + // Error already added by InterpretSingleOption(). + failed = true; + break; + } + src_path.pop_back(); + } + // Reset these, so we don't have any dangling pointers. + uninterpreted_option_ = nullptr; + options_to_interpret_ = nullptr; + + if (!failed) { + // InterpretSingleOption() added the interpreted options in the + // UnknownFieldSet, in case the option isn't yet known to us. Now we + // serialize the options message and deserialize it back. That way, any + // option fields that we do happen to know about will get moved from the + // UnknownFieldSet into the real fields, and thus be available right away. + // If they are not known, that's OK too. They will get reparsed into the + // UnknownFieldSet and wait there until the message is parsed by something + // that does know about the options. + + // Keep the unparsed options around in case the reparsing fails. + std::unique_ptr<Message> unparsed_options(options->New()); + options->GetReflection()->Swap(unparsed_options.get(), options); + + std::string buf; + if (!unparsed_options->AppendToString(&buf) || + !options->ParseFromString(buf)) { + builder_->AddError( + options_to_interpret->element_name, *original_options, + DescriptorPool::ErrorCollector::OTHER, + "Some options could not be correctly parsed using the proto " + "descriptors compiled into this binary.\n" + "Unparsed options: " + + unparsed_options->ShortDebugString() + + "\n" + "Parsing attempt: " + + options->ShortDebugString()); + // Restore the unparsed options. + options->GetReflection()->Swap(unparsed_options.get(), options); + } + } + + return !failed; +} + +bool DescriptorBuilder::OptionInterpreter::InterpretSingleOption( + Message* options, const std::vector<int>& src_path, + const std::vector<int>& options_path) { + // First do some basic validation. + if (uninterpreted_option_->name_size() == 0) { + // This should never happen unless the parser has gone seriously awry or + // someone has manually created the uninterpreted option badly. + return AddNameError("Option must have a name."); + } + if (uninterpreted_option_->name(0).name_part() == "uninterpreted_option") { + return AddNameError( + "Option must not use reserved name " + "\"uninterpreted_option\"."); + } + + const Descriptor* options_descriptor = nullptr; + // Get the options message's descriptor from the builder's pool, so that we + // get the version that knows about any extension options declared in the file + // we're currently building. The descriptor should be there as long as the + // file we're building imported descriptor.proto. + + // Note that we use DescriptorBuilder::FindSymbolNotEnforcingDeps(), not + // DescriptorPool::FindMessageTypeByName() because we're already holding the + // pool's mutex, and the latter method locks it again. We don't use + // FindSymbol() because files that use custom options only need to depend on + // the file that defines the option, not descriptor.proto itself. + Symbol symbol = builder_->FindSymbolNotEnforcingDeps( + options->GetDescriptor()->full_name()); + options_descriptor = symbol.descriptor(); + if (options_descriptor == nullptr) { + // The options message's descriptor was not in the builder's pool, so use + // the standard version from the generated pool. We're not holding the + // generated pool's mutex, so we can search it the straightforward way. + options_descriptor = options->GetDescriptor(); + } + GOOGLE_CHECK(options_descriptor); + + // We iterate over the name parts to drill into the submessages until we find + // the leaf field for the option. As we drill down we remember the current + // submessage's descriptor in |descriptor| and the next field in that + // submessage in |field|. We also track the fields we're drilling down + // through in |intermediate_fields|. As we go, we reconstruct the full option + // name in |debug_msg_name|, for use in error messages. + const Descriptor* descriptor = options_descriptor; + const FieldDescriptor* field = nullptr; + std::vector<const FieldDescriptor*> intermediate_fields; + std::string debug_msg_name = ""; + + std::vector<int> dest_path = options_path; + + for (int i = 0; i < uninterpreted_option_->name_size(); ++i) { + builder_->undefine_resolved_name_.clear(); + const std::string& name_part = uninterpreted_option_->name(i).name_part(); + if (debug_msg_name.size() > 0) { + debug_msg_name += "."; + } + if (uninterpreted_option_->name(i).is_extension()) { + debug_msg_name += "(" + name_part + ")"; + // Search for the extension's descriptor as an extension in the builder's + // pool. Note that we use DescriptorBuilder::LookupSymbol(), not + // DescriptorPool::FindExtensionByName(), for two reasons: 1) It allows + // relative lookups, and 2) because we're already holding the pool's + // mutex, and the latter method locks it again. + symbol = + builder_->LookupSymbol(name_part, options_to_interpret_->name_scope); + field = symbol.field_descriptor(); + // If we don't find the field then the field's descriptor was not in the + // builder's pool, but there's no point in looking in the generated + // pool. We require that you import the file that defines any extensions + // you use, so they must be present in the builder's pool. + } else { + debug_msg_name += name_part; + // Search for the field's descriptor as a regular field. + field = descriptor->FindFieldByName(name_part); + } + + if (field == nullptr) { + if (get_allow_unknown(builder_->pool_)) { + // We can't find the option, but AllowUnknownDependencies() is enabled, + // so we will just leave it as uninterpreted. + AddWithoutInterpreting(*uninterpreted_option_, options); + return true; + } else if (!(builder_->undefine_resolved_name_).empty()) { + // Option is resolved to a name which is not defined. + return AddNameError( + "Option \"" + debug_msg_name + "\" is resolved to \"(" + + builder_->undefine_resolved_name_ + + ")\", which is not defined. The innermost scope is searched first " + "in name resolution. Consider using a leading '.'(i.e., \"(." + + debug_msg_name.substr(1) + + "\") to start from the outermost scope."); + } else { + return AddNameError( + "Option \"" + debug_msg_name + + "\" unknown. Ensure that your proto" + + " definition file imports the proto which defines the option."); + } + } else if (field->containing_type() != descriptor) { + if (get_is_placeholder(field->containing_type())) { + // The field is an extension of a placeholder type, so we can't + // reliably verify whether it is a valid extension to use here (e.g. + // we don't know if it is an extension of the correct *Options message, + // or if it has a valid field number, etc.). Just leave it as + // uninterpreted instead. + AddWithoutInterpreting(*uninterpreted_option_, options); + return true; + } else { + // This can only happen if, due to some insane misconfiguration of the + // pools, we find the options message in one pool but the field in + // another. This would probably imply a hefty bug somewhere. + return AddNameError("Option field \"" + debug_msg_name + + "\" is not a field or extension of message \"" + + descriptor->name() + "\"."); + } + } else { + // accumulate field numbers to form path to interpreted option + dest_path.push_back(field->number()); + + if (i < uninterpreted_option_->name_size() - 1) { + if (field->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE) { + return AddNameError("Option \"" + debug_msg_name + + "\" is an atomic type, not a message."); + } else if (field->is_repeated()) { + return AddNameError("Option field \"" + debug_msg_name + + "\" is a repeated message. Repeated message " + "options must be initialized using an " + "aggregate value."); + } else { + // Drill down into the submessage. + intermediate_fields.push_back(field); + descriptor = field->message_type(); + } + } + } + } + + // We've found the leaf field. Now we use UnknownFieldSets to set its value + // on the options message. We do so because the message may not yet know + // about its extension fields, so we may not be able to set the fields + // directly. But the UnknownFieldSets will serialize to the same wire-format + // message, so reading that message back in once the extension fields are + // known will populate them correctly. + + // First see if the option is already set. + if (!field->is_repeated() && + !ExamineIfOptionIsSet( + intermediate_fields.begin(), intermediate_fields.end(), field, + debug_msg_name, + options->GetReflection()->GetUnknownFields(*options))) { + return false; // ExamineIfOptionIsSet() already added the error. + } + + // First set the value on the UnknownFieldSet corresponding to the + // innermost message. + std::unique_ptr<UnknownFieldSet> unknown_fields(new UnknownFieldSet()); + if (!SetOptionValue(field, unknown_fields.get())) { + return false; // SetOptionValue() already added the error. + } + + // Now wrap the UnknownFieldSet with UnknownFieldSets corresponding to all + // the intermediate messages. + for (std::vector<const FieldDescriptor*>::reverse_iterator iter = + intermediate_fields.rbegin(); + iter != intermediate_fields.rend(); ++iter) { + std::unique_ptr<UnknownFieldSet> parent_unknown_fields( + new UnknownFieldSet()); + switch ((*iter)->type()) { + case FieldDescriptor::TYPE_MESSAGE: { + std::string* outstr = + parent_unknown_fields->AddLengthDelimited((*iter)->number()); + GOOGLE_CHECK(unknown_fields->SerializeToString(outstr)) + << "Unexpected failure while serializing option submessage " + << debug_msg_name << "\"."; + break; + } + + case FieldDescriptor::TYPE_GROUP: { + parent_unknown_fields->AddGroup((*iter)->number()) + ->MergeFrom(*unknown_fields); + break; + } + + default: + GOOGLE_LOG(FATAL) << "Invalid wire type for CPPTYPE_MESSAGE: " + << (*iter)->type(); + return false; + } + unknown_fields.reset(parent_unknown_fields.release()); + } + + // Now merge the UnknownFieldSet corresponding to the top-level message into + // the options message. + options->GetReflection()->MutableUnknownFields(options)->MergeFrom( + *unknown_fields); + + // record the element path of the interpreted option + if (field->is_repeated()) { + int index = repeated_option_counts_[dest_path]++; + dest_path.push_back(index); + } + interpreted_paths_[src_path] = dest_path; + + return true; +} + +void DescriptorBuilder::OptionInterpreter::UpdateSourceCodeInfo( + SourceCodeInfo* info) { + if (interpreted_paths_.empty()) { + // nothing to do! + return; + } + + // We find locations that match keys in interpreted_paths_ and + // 1) replace the path with the corresponding value in interpreted_paths_ + // 2) remove any subsequent sub-locations (sub-location is one whose path + // has the parent path as a prefix) + // + // To avoid quadratic behavior of removing interior rows as we go, + // we keep a copy. But we don't actually copy anything until we've + // found the first match (so if the source code info has no locations + // that need to be changed, there is zero copy overhead). + + RepeatedPtrField<SourceCodeInfo_Location>* locs = info->mutable_location(); + RepeatedPtrField<SourceCodeInfo_Location> new_locs; + bool copying = false; + + std::vector<int> pathv; + bool matched = false; + + for (RepeatedPtrField<SourceCodeInfo_Location>::iterator loc = locs->begin(); + loc != locs->end(); loc++) { + if (matched) { + // see if this location is in the range to remove + bool loc_matches = true; + if (loc->path_size() < static_cast<int64_t>(pathv.size())) { + loc_matches = false; + } else { + for (size_t j = 0; j < pathv.size(); j++) { + if (loc->path(j) != pathv[j]) { + loc_matches = false; + break; + } + } + } + + if (loc_matches) { + // don't copy this row since it is a sub-location that we're removing + continue; + } + + matched = false; + } + + pathv.clear(); + for (int j = 0; j < loc->path_size(); j++) { + pathv.push_back(loc->path(j)); + } + + std::map<std::vector<int>, std::vector<int>>::iterator entry = + interpreted_paths_.find(pathv); + + if (entry == interpreted_paths_.end()) { + // not a match + if (copying) { + *new_locs.Add() = *loc; + } + continue; + } + + matched = true; + + if (!copying) { + // initialize the copy we are building + copying = true; + new_locs.Reserve(locs->size()); + for (RepeatedPtrField<SourceCodeInfo_Location>::iterator it = + locs->begin(); + it != loc; it++) { + *new_locs.Add() = *it; + } + } + + // add replacement and update its path + SourceCodeInfo_Location* replacement = new_locs.Add(); + *replacement = *loc; + replacement->clear_path(); + for (std::vector<int>::iterator rit = entry->second.begin(); + rit != entry->second.end(); rit++) { + replacement->add_path(*rit); + } + } + + // if we made a changed copy, put it in place + if (copying) { + *locs = new_locs; + } +} + +void DescriptorBuilder::OptionInterpreter::AddWithoutInterpreting( + const UninterpretedOption& uninterpreted_option, Message* options) { + const FieldDescriptor* field = + options->GetDescriptor()->FindFieldByName("uninterpreted_option"); + GOOGLE_CHECK(field != nullptr); + + options->GetReflection() + ->AddMessage(options, field) + ->CopyFrom(uninterpreted_option); +} + +bool DescriptorBuilder::OptionInterpreter::ExamineIfOptionIsSet( + std::vector<const FieldDescriptor*>::const_iterator + intermediate_fields_iter, + std::vector<const FieldDescriptor*>::const_iterator intermediate_fields_end, + const FieldDescriptor* innermost_field, const std::string& debug_msg_name, + const UnknownFieldSet& unknown_fields) { + // We do linear searches of the UnknownFieldSet and its sub-groups. This + // should be fine since it's unlikely that any one options structure will + // contain more than a handful of options. + + if (intermediate_fields_iter == intermediate_fields_end) { + // We're at the innermost submessage. + for (int i = 0; i < unknown_fields.field_count(); i++) { + if (unknown_fields.field(i).number() == innermost_field->number()) { + return AddNameError("Option \"" + debug_msg_name + + "\" was already set."); + } + } + return true; + } + + for (int i = 0; i < unknown_fields.field_count(); i++) { + if (unknown_fields.field(i).number() == + (*intermediate_fields_iter)->number()) { + const UnknownField* unknown_field = &unknown_fields.field(i); + FieldDescriptor::Type type = (*intermediate_fields_iter)->type(); + // Recurse into the next submessage. + switch (type) { + case FieldDescriptor::TYPE_MESSAGE: + if (unknown_field->type() == UnknownField::TYPE_LENGTH_DELIMITED) { + UnknownFieldSet intermediate_unknown_fields; + if (intermediate_unknown_fields.ParseFromString( + unknown_field->length_delimited()) && + !ExamineIfOptionIsSet(intermediate_fields_iter + 1, + intermediate_fields_end, innermost_field, + debug_msg_name, + intermediate_unknown_fields)) { + return false; // Error already added. + } + } + break; + + case FieldDescriptor::TYPE_GROUP: + if (unknown_field->type() == UnknownField::TYPE_GROUP) { + if (!ExamineIfOptionIsSet(intermediate_fields_iter + 1, + intermediate_fields_end, innermost_field, + debug_msg_name, unknown_field->group())) { + return false; // Error already added. + } + } + break; + + default: + GOOGLE_LOG(FATAL) << "Invalid wire type for CPPTYPE_MESSAGE: " << type; + return false; + } + } + } + return true; +} + +bool DescriptorBuilder::OptionInterpreter::SetOptionValue( + const FieldDescriptor* option_field, UnknownFieldSet* unknown_fields) { + // We switch on the CppType to validate. + switch (option_field->cpp_type()) { + case FieldDescriptor::CPPTYPE_INT32: + if (uninterpreted_option_->has_positive_int_value()) { + if (uninterpreted_option_->positive_int_value() > + static_cast<uint64_t>(std::numeric_limits<int32_t>::max())) { + return AddValueError("Value out of range for int32 option \"" + + option_field->full_name() + "\"."); + } else { + SetInt32(option_field->number(), + uninterpreted_option_->positive_int_value(), + option_field->type(), unknown_fields); + } + } else if (uninterpreted_option_->has_negative_int_value()) { + if (uninterpreted_option_->negative_int_value() < + static_cast<int64_t>(std::numeric_limits<int32_t>::min())) { + return AddValueError("Value out of range for int32 option \"" + + option_field->full_name() + "\"."); + } else { + SetInt32(option_field->number(), + uninterpreted_option_->negative_int_value(), + option_field->type(), unknown_fields); + } + } else { + return AddValueError("Value must be integer for int32 option \"" + + option_field->full_name() + "\"."); + } + break; + + case FieldDescriptor::CPPTYPE_INT64: + if (uninterpreted_option_->has_positive_int_value()) { + if (uninterpreted_option_->positive_int_value() > + static_cast<uint64_t>(std::numeric_limits<int64_t>::max())) { + return AddValueError("Value out of range for int64 option \"" + + option_field->full_name() + "\"."); + } else { + SetInt64(option_field->number(), + uninterpreted_option_->positive_int_value(), + option_field->type(), unknown_fields); + } + } else if (uninterpreted_option_->has_negative_int_value()) { + SetInt64(option_field->number(), + uninterpreted_option_->negative_int_value(), + option_field->type(), unknown_fields); + } else { + return AddValueError("Value must be integer for int64 option \"" + + option_field->full_name() + "\"."); + } + break; + + case FieldDescriptor::CPPTYPE_UINT32: + if (uninterpreted_option_->has_positive_int_value()) { + if (uninterpreted_option_->positive_int_value() > + std::numeric_limits<uint32_t>::max()) { + return AddValueError("Value out of range for uint32 option \"" + + option_field->name() + "\"."); + } else { + SetUInt32(option_field->number(), + uninterpreted_option_->positive_int_value(), + option_field->type(), unknown_fields); + } + } else { + return AddValueError( + "Value must be non-negative integer for uint32 " + "option \"" + + option_field->full_name() + "\"."); + } + break; + + case FieldDescriptor::CPPTYPE_UINT64: + if (uninterpreted_option_->has_positive_int_value()) { + SetUInt64(option_field->number(), + uninterpreted_option_->positive_int_value(), + option_field->type(), unknown_fields); + } else { + return AddValueError( + "Value must be non-negative integer for uint64 " + "option \"" + + option_field->full_name() + "\"."); + } + break; + + case FieldDescriptor::CPPTYPE_FLOAT: { + float value; + if (uninterpreted_option_->has_double_value()) { + value = uninterpreted_option_->double_value(); + } else if (uninterpreted_option_->has_positive_int_value()) { + value = uninterpreted_option_->positive_int_value(); + } else if (uninterpreted_option_->has_negative_int_value()) { + value = uninterpreted_option_->negative_int_value(); + } else { + return AddValueError("Value must be number for float option \"" + + option_field->full_name() + "\"."); + } + unknown_fields->AddFixed32(option_field->number(), + internal::WireFormatLite::EncodeFloat(value)); + break; + } + + case FieldDescriptor::CPPTYPE_DOUBLE: { + double value; + if (uninterpreted_option_->has_double_value()) { + value = uninterpreted_option_->double_value(); + } else if (uninterpreted_option_->has_positive_int_value()) { + value = uninterpreted_option_->positive_int_value(); + } else if (uninterpreted_option_->has_negative_int_value()) { + value = uninterpreted_option_->negative_int_value(); + } else { + return AddValueError("Value must be number for double option \"" + + option_field->full_name() + "\"."); + } + unknown_fields->AddFixed64(option_field->number(), + internal::WireFormatLite::EncodeDouble(value)); + break; + } + + case FieldDescriptor::CPPTYPE_BOOL: + uint64_t value; + if (!uninterpreted_option_->has_identifier_value()) { + return AddValueError( + "Value must be identifier for boolean option " + "\"" + + option_field->full_name() + "\"."); + } + if (uninterpreted_option_->identifier_value() == "true") { + value = 1; + } else if (uninterpreted_option_->identifier_value() == "false") { + value = 0; + } else { + return AddValueError( + "Value must be \"true\" or \"false\" for boolean " + "option \"" + + option_field->full_name() + "\"."); + } + unknown_fields->AddVarint(option_field->number(), value); + break; + + case FieldDescriptor::CPPTYPE_ENUM: { + if (!uninterpreted_option_->has_identifier_value()) { + return AddValueError( + "Value must be identifier for enum-valued option " + "\"" + + option_field->full_name() + "\"."); + } + const EnumDescriptor* enum_type = option_field->enum_type(); + const std::string& value_name = uninterpreted_option_->identifier_value(); + const EnumValueDescriptor* enum_value = nullptr; + + if (enum_type->file()->pool() != DescriptorPool::generated_pool()) { + // Note that the enum value's fully-qualified name is a sibling of the + // enum's name, not a child of it. + std::string fully_qualified_name = enum_type->full_name(); + fully_qualified_name.resize(fully_qualified_name.size() - + enum_type->name().size()); + fully_qualified_name += value_name; + + // Search for the enum value's descriptor in the builder's pool. Note + // that we use DescriptorBuilder::FindSymbolNotEnforcingDeps(), not + // DescriptorPool::FindEnumValueByName() because we're already holding + // the pool's mutex, and the latter method locks it again. + Symbol symbol = + builder_->FindSymbolNotEnforcingDeps(fully_qualified_name); + if (auto* candicate_descriptor = symbol.enum_value_descriptor()) { + if (candicate_descriptor->type() != enum_type) { + return AddValueError( + "Enum type \"" + enum_type->full_name() + + "\" has no value named \"" + value_name + "\" for option \"" + + option_field->full_name() + + "\". This appears to be a value from a sibling type."); + } else { + enum_value = candicate_descriptor; + } + } + } else { + // The enum type is in the generated pool, so we can search for the + // value there. + enum_value = enum_type->FindValueByName(value_name); + } + + if (enum_value == nullptr) { + return AddValueError("Enum type \"" + + option_field->enum_type()->full_name() + + "\" has no value named \"" + value_name + + "\" for " + "option \"" + + option_field->full_name() + "\"."); + } else { + // Sign-extension is not a problem, since we cast directly from int32_t + // to uint64_t, without first going through uint32_t. + unknown_fields->AddVarint( + option_field->number(), + static_cast<uint64_t>(static_cast<int64_t>(enum_value->number()))); + } + break; + } + + case FieldDescriptor::CPPTYPE_STRING: + if (!uninterpreted_option_->has_string_value()) { + return AddValueError( + "Value must be quoted string for string option " + "\"" + + option_field->full_name() + "\"."); + } + // The string has already been unquoted and unescaped by the parser. + unknown_fields->AddLengthDelimited(option_field->number(), + uninterpreted_option_->string_value()); + break; + + case FieldDescriptor::CPPTYPE_MESSAGE: + if (!SetAggregateOption(option_field, unknown_fields)) { + return false; + } + break; + } + + return true; +} + +class DescriptorBuilder::OptionInterpreter::AggregateOptionFinder + : public TextFormat::Finder { + public: + DescriptorBuilder* builder_; + + const Descriptor* FindAnyType(const Message& /*message*/, + const std::string& prefix, + const std::string& name) const override { + if (prefix != internal::kTypeGoogleApisComPrefix && + prefix != internal::kTypeGoogleProdComPrefix) { + return nullptr; + } + assert_mutex_held(builder_->pool_); + return builder_->FindSymbol(name).descriptor(); + } + + const FieldDescriptor* FindExtension(Message* message, + const std::string& name) const override { + assert_mutex_held(builder_->pool_); + const Descriptor* descriptor = message->GetDescriptor(); + Symbol result = + builder_->LookupSymbolNoPlaceholder(name, descriptor->full_name()); + if (auto* field = result.field_descriptor()) { + return field; + } else if (result.type() == Symbol::MESSAGE && + descriptor->options().message_set_wire_format()) { + const Descriptor* foreign_type = result.descriptor(); + // The text format allows MessageSet items to be specified using + // the type name, rather than the extension identifier. If the symbol + // lookup returned a Message, and the enclosing Message has + // message_set_wire_format = true, then return the message set + // extension, if one exists. + for (int i = 0; i < foreign_type->extension_count(); i++) { + const FieldDescriptor* extension = foreign_type->extension(i); + if (extension->containing_type() == descriptor && + extension->type() == FieldDescriptor::TYPE_MESSAGE && + extension->is_optional() && + extension->message_type() == foreign_type) { + // Found it. + return extension; + } + } + } + return nullptr; + } +}; + +// A custom error collector to record any text-format parsing errors +namespace { +class AggregateErrorCollector : public io::ErrorCollector { + public: + std::string error_; + + void AddError(int /* line */, int /* column */, + const std::string& message) override { + if (!error_.empty()) { + error_ += "; "; + } + error_ += message; + } + + void AddWarning(int /* line */, int /* column */, + const std::string& /* message */) override { + // Ignore warnings + } +}; +} // namespace + +// We construct a dynamic message of the type corresponding to +// option_field, parse the supplied text-format string into this +// message, and serialize the resulting message to produce the value. +bool DescriptorBuilder::OptionInterpreter::SetAggregateOption( + const FieldDescriptor* option_field, UnknownFieldSet* unknown_fields) { + if (!uninterpreted_option_->has_aggregate_value()) { + return AddValueError("Option \"" + option_field->full_name() + + "\" is a message. To set the entire message, use " + "syntax like \"" + + option_field->name() + + " = { <proto text format> }\". " + "To set fields within it, use " + "syntax like \"" + + option_field->name() + ".foo = value\"."); + } + + const Descriptor* type = option_field->message_type(); + std::unique_ptr<Message> dynamic(dynamic_factory_.GetPrototype(type)->New()); + GOOGLE_CHECK(dynamic.get() != nullptr) + << "Could not create an instance of " << option_field->DebugString(); + + AggregateErrorCollector collector; + AggregateOptionFinder finder; + finder.builder_ = builder_; + TextFormat::Parser parser; + parser.RecordErrorsTo(&collector); + parser.SetFinder(&finder); + if (!parser.ParseFromString(uninterpreted_option_->aggregate_value(), + dynamic.get())) { + AddValueError("Error while parsing option value for \"" + + option_field->name() + "\": " + collector.error_); + return false; + } else { + std::string serial; + dynamic->SerializeToString(&serial); // Never fails + if (option_field->type() == FieldDescriptor::TYPE_MESSAGE) { + unknown_fields->AddLengthDelimited(option_field->number(), serial); + } else { + GOOGLE_CHECK_EQ(option_field->type(), FieldDescriptor::TYPE_GROUP); + UnknownFieldSet* group = unknown_fields->AddGroup(option_field->number()); + group->ParseFromString(serial); + } + return true; + } +} + +void DescriptorBuilder::OptionInterpreter::SetInt32( + int number, int32_t value, FieldDescriptor::Type type, + UnknownFieldSet* unknown_fields) { + switch (type) { + case FieldDescriptor::TYPE_INT32: + unknown_fields->AddVarint( + number, static_cast<uint64_t>(static_cast<int64_t>(value))); + break; + + case FieldDescriptor::TYPE_SFIXED32: + unknown_fields->AddFixed32(number, static_cast<uint32_t>(value)); + break; + + case FieldDescriptor::TYPE_SINT32: + unknown_fields->AddVarint( + number, internal::WireFormatLite::ZigZagEncode32(value)); + break; + + default: + GOOGLE_LOG(FATAL) << "Invalid wire type for CPPTYPE_INT32: " << type; + break; + } +} + +void DescriptorBuilder::OptionInterpreter::SetInt64( + int number, int64_t value, FieldDescriptor::Type type, + UnknownFieldSet* unknown_fields) { + switch (type) { + case FieldDescriptor::TYPE_INT64: + unknown_fields->AddVarint(number, static_cast<uint64_t>(value)); + break; + + case FieldDescriptor::TYPE_SFIXED64: + unknown_fields->AddFixed64(number, static_cast<uint64_t>(value)); + break; + + case FieldDescriptor::TYPE_SINT64: + unknown_fields->AddVarint( + number, internal::WireFormatLite::ZigZagEncode64(value)); + break; + + default: + GOOGLE_LOG(FATAL) << "Invalid wire type for CPPTYPE_INT64: " << type; + break; + } +} + +void DescriptorBuilder::OptionInterpreter::SetUInt32( + int number, uint32_t value, FieldDescriptor::Type type, + UnknownFieldSet* unknown_fields) { + switch (type) { + case FieldDescriptor::TYPE_UINT32: + unknown_fields->AddVarint(number, static_cast<uint64_t>(value)); + break; + + case FieldDescriptor::TYPE_FIXED32: + unknown_fields->AddFixed32(number, static_cast<uint32_t>(value)); + break; + + default: + GOOGLE_LOG(FATAL) << "Invalid wire type for CPPTYPE_UINT32: " << type; + break; + } +} + +void DescriptorBuilder::OptionInterpreter::SetUInt64( + int number, uint64_t value, FieldDescriptor::Type type, + UnknownFieldSet* unknown_fields) { + switch (type) { + case FieldDescriptor::TYPE_UINT64: + unknown_fields->AddVarint(number, value); + break; + + case FieldDescriptor::TYPE_FIXED64: + unknown_fields->AddFixed64(number, value); + break; + + default: + GOOGLE_LOG(FATAL) << "Invalid wire type for CPPTYPE_UINT64: " << type; + break; + } +} + +void DescriptorBuilder::LogUnusedDependency(const FileDescriptorProto& proto, + const FileDescriptor* result) { + (void)result; // Parameter is used by Google-internal code. + + if (!unused_dependency_.empty()) { + auto itr = pool_->unused_import_track_files_.find(proto.name()); + bool is_error = + itr != pool_->unused_import_track_files_.end() && itr->second; + for (std::set<const FileDescriptor*>::const_iterator it = + unused_dependency_.begin(); + it != unused_dependency_.end(); ++it) { + std::string error_message = "Import " + (*it)->name() + " is unused."; + if (is_error) { + AddError((*it)->name(), proto, DescriptorPool::ErrorCollector::IMPORT, + error_message); + } else { + AddWarning((*it)->name(), proto, DescriptorPool::ErrorCollector::IMPORT, + error_message); + } + } + } +} + +Symbol DescriptorPool::CrossLinkOnDemandHelper(StringPiece name, + bool expecting_enum) const { + (void)expecting_enum; // Parameter is used by Google-internal code. + auto lookup_name = std::string(name); + if (!lookup_name.empty() && lookup_name[0] == '.') { + lookup_name = lookup_name.substr(1); + } + Symbol result = tables_->FindByNameHelper(this, lookup_name); + return result; +} + +// Handle the lazy import building for a message field whose type wasn't built +// at cross link time. If that was the case, we saved the name of the type to +// be looked up when the accessor for the type was called. Set type_, +// enum_type_, message_type_, and default_value_enum_ appropriately. +void FieldDescriptor::InternalTypeOnceInit() const { + GOOGLE_CHECK(file()->finished_building_ == true); + const EnumDescriptor* enum_type = nullptr; + const char* lazy_type_name = reinterpret_cast<const char*>(type_once_ + 1); + const char* lazy_default_value_enum_name = + lazy_type_name + strlen(lazy_type_name) + 1; + Symbol result = file()->pool()->CrossLinkOnDemandHelper( + lazy_type_name, type_ == FieldDescriptor::TYPE_ENUM); + if (result.type() == Symbol::MESSAGE) { + type_ = FieldDescriptor::TYPE_MESSAGE; + type_descriptor_.message_type = result.descriptor(); + } else if (result.type() == Symbol::ENUM) { + type_ = FieldDescriptor::TYPE_ENUM; + enum_type = type_descriptor_.enum_type = result.enum_descriptor(); + } + + if (enum_type) { + if (lazy_default_value_enum_name[0] != '\0') { + // Have to build the full name now instead of at CrossLink time, + // because enum_type may not be known at the time. + std::string name = enum_type->full_name(); + // Enum values reside in the same scope as the enum type. + std::string::size_type last_dot = name.find_last_of('.'); + if (last_dot != std::string::npos) { + name = name.substr(0, last_dot) + "." + lazy_default_value_enum_name; + } else { + name = lazy_default_value_enum_name; + } + Symbol result = file()->pool()->CrossLinkOnDemandHelper(name, true); + default_value_enum_ = result.enum_value_descriptor(); + } else { + default_value_enum_ = nullptr; + } + if (!default_value_enum_) { + // We use the first defined value as the default + // if a default is not explicitly defined. + GOOGLE_CHECK(enum_type->value_count()); + default_value_enum_ = enum_type->value(0); + } + } +} + +void FieldDescriptor::TypeOnceInit(const FieldDescriptor* to_init) { + to_init->InternalTypeOnceInit(); +} + +// message_type(), enum_type(), default_value_enum(), and type() +// all share the same internal::call_once init path to do lazy +// import building and cross linking of a field of a message. +const Descriptor* FieldDescriptor::message_type() const { + if (type_once_) { + internal::call_once(*type_once_, FieldDescriptor::TypeOnceInit, this); + } + return type_ == TYPE_MESSAGE || type_ == TYPE_GROUP + ? type_descriptor_.message_type + : nullptr; +} + +const EnumDescriptor* FieldDescriptor::enum_type() const { + if (type_once_) { + internal::call_once(*type_once_, FieldDescriptor::TypeOnceInit, this); + } + return type_ == TYPE_ENUM ? type_descriptor_.enum_type : nullptr; +} + +const EnumValueDescriptor* FieldDescriptor::default_value_enum() const { + if (type_once_) { + internal::call_once(*type_once_, FieldDescriptor::TypeOnceInit, this); + } + return default_value_enum_; +} + +const std::string& FieldDescriptor::PrintableNameForExtension() const { + const bool is_message_set_extension = + is_extension() && + containing_type()->options().message_set_wire_format() && + type() == FieldDescriptor::TYPE_MESSAGE && is_optional() && + extension_scope() == message_type(); + return is_message_set_extension ? message_type()->full_name() : full_name(); +} + +void FileDescriptor::InternalDependenciesOnceInit() const { + GOOGLE_CHECK(finished_building_ == true); + const char* names_ptr = reinterpret_cast<const char*>(dependencies_once_ + 1); + for (int i = 0; i < dependency_count(); i++) { + const char* name = names_ptr; + names_ptr += strlen(name) + 1; + if (name[0] != '\0') { + dependencies_[i] = pool_->FindFileByName(name); + } + } +} + +void FileDescriptor::DependenciesOnceInit(const FileDescriptor* to_init) { + to_init->InternalDependenciesOnceInit(); +} + +const FileDescriptor* FileDescriptor::dependency(int index) const { + if (dependencies_once_) { + // Do once init for all indices, as it's unlikely only a single index would + // be called, and saves on internal::call_once allocations. + internal::call_once(*dependencies_once_, + FileDescriptor::DependenciesOnceInit, this); + } + return dependencies_[index]; +} + +const Descriptor* MethodDescriptor::input_type() const { + return input_type_.Get(service()); +} + +const Descriptor* MethodDescriptor::output_type() const { + return output_type_.Get(service()); +} + +namespace internal { +void LazyDescriptor::Set(const Descriptor* descriptor) { + GOOGLE_CHECK(!once_); + descriptor_ = descriptor; +} + +void LazyDescriptor::SetLazy(StringPiece name, + const FileDescriptor* file) { + // verify Init() has been called and Set hasn't been called yet. + GOOGLE_CHECK(!descriptor_); + GOOGLE_CHECK(!once_); + GOOGLE_CHECK(file && file->pool_); + GOOGLE_CHECK(file->pool_->lazily_build_dependencies_); + GOOGLE_CHECK(!file->finished_building_); + once_ = ::new (file->pool_->tables_->AllocateBytes(static_cast<int>( + sizeof(internal::once_flag) + name.size() + 1))) internal::once_flag{}; + char* lazy_name = reinterpret_cast<char*>(once_ + 1); + memcpy(lazy_name, name.data(), name.size()); + lazy_name[name.size()] = 0; +} + +void LazyDescriptor::Once(const ServiceDescriptor* service) { + if (once_) { + internal::call_once(*once_, [&] { + auto* file = service->file(); + GOOGLE_CHECK(file->finished_building_); + const char* lazy_name = reinterpret_cast<const char*>(once_ + 1); + descriptor_ = + file->pool_->CrossLinkOnDemandHelper(lazy_name, false).descriptor(); + }); + } +} + +} // namespace internal + +} // namespace protobuf +} // namespace google + +#include <google/protobuf/port_undef.inc> diff --git a/toolkit/components/protobuf/src/google/protobuf/descriptor.h b/toolkit/components/protobuf/src/google/protobuf/descriptor.h new file mode 100644 index 0000000000..1b8728ec63 --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/descriptor.h @@ -0,0 +1,2440 @@ +// 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. + +// Author: kenton@google.com (Kenton Varda) +// Based on original Protocol Buffers design by +// Sanjay Ghemawat, Jeff Dean, and others. +// +// This file contains classes which describe a type of protocol message. +// You can use a message's descriptor to learn at runtime what fields +// it contains and what the types of those fields are. The Message +// interface also allows you to dynamically access and modify individual +// fields by passing the FieldDescriptor of the field you are interested +// in. +// +// Most users will not care about descriptors, because they will write +// code specific to certain protocol types and will simply use the classes +// generated by the protocol compiler directly. Advanced users who want +// to operate on arbitrary types (not known at compile time) may want to +// read descriptors in order to learn about the contents of a message. +// A very small number of users will want to construct their own +// Descriptors, either because they are implementing Message manually or +// because they are writing something like the protocol compiler. +// +// For an example of how you might use descriptors, see the code example +// at the top of message.h. + +#ifndef GOOGLE_PROTOBUF_DESCRIPTOR_H__ +#define GOOGLE_PROTOBUF_DESCRIPTOR_H__ + + +#include <atomic> +#include <map> +#include <memory> +#include <set> +#include <string> +#include <vector> + +#include <google/protobuf/stubs/common.h> +#include <google/protobuf/stubs/logging.h> +#include <google/protobuf/stubs/mutex.h> +#include <google/protobuf/stubs/once.h> +#include <google/protobuf/port.h> + +// Must be included last. +#include <google/protobuf/port_def.inc> + +// TYPE_BOOL is defined in the MacOS's ConditionalMacros.h. +#ifdef TYPE_BOOL +#undef TYPE_BOOL +#endif // TYPE_BOOL + +#ifdef SWIG +#define PROTOBUF_EXPORT +#endif + + +namespace google { +namespace protobuf { + +// Defined in this file. +class Descriptor; +class FieldDescriptor; +class OneofDescriptor; +class EnumDescriptor; +class EnumValueDescriptor; +class ServiceDescriptor; +class MethodDescriptor; +class FileDescriptor; +class DescriptorDatabase; +class DescriptorPool; + +// Defined in descriptor.proto +class DescriptorProto; +class DescriptorProto_ExtensionRange; +class FieldDescriptorProto; +class OneofDescriptorProto; +class EnumDescriptorProto; +class EnumValueDescriptorProto; +class ServiceDescriptorProto; +class MethodDescriptorProto; +class FileDescriptorProto; +class MessageOptions; +class FieldOptions; +class OneofOptions; +class EnumOptions; +class EnumValueOptions; +class ExtensionRangeOptions; +class ServiceOptions; +class MethodOptions; +class FileOptions; +class UninterpretedOption; +class SourceCodeInfo; + +// Defined in message.h +class Message; +class Reflection; + +// Defined in descriptor.cc +class DescriptorBuilder; +class FileDescriptorTables; +class Symbol; + +// Defined in unknown_field_set.h. +class UnknownField; + +// Defined in command_line_interface.cc +namespace compiler { +class CommandLineInterface; +namespace cpp { +// Defined in helpers.h +class Formatter; +} // namespace cpp +} // namespace compiler + +namespace descriptor_unittest { +class DescriptorTest; +} // namespace descriptor_unittest + +// Defined in printer.h +namespace io { +class Printer; +} // namespace io + +// NB, all indices are zero-based. +struct SourceLocation { + int start_line; + int end_line; + int start_column; + int end_column; + + // Doc comments found at the source location. + // See the comments in SourceCodeInfo.Location (descriptor.proto) for details. + std::string leading_comments; + std::string trailing_comments; + std::vector<std::string> leading_detached_comments; +}; + +// Options when generating machine-parsable output from a descriptor with +// DebugString(). +struct DebugStringOptions { + // include original user comments as recorded in SourceLocation entries. N.B. + // that this must be |false| by default: several other pieces of code (for + // example, the C++ code generation for fields in the proto compiler) rely on + // DebugString() output being unobstructed by user comments. + bool include_comments; + // If true, elide the braced body in the debug string. + bool elide_group_body; + bool elide_oneof_body; + + DebugStringOptions() + : include_comments(false), + elide_group_body(false), + elide_oneof_body(false) { + } +}; + +// A class to handle the simplest cases of a lazily linked descriptor +// for a message type that isn't built at the time of cross linking, +// which is needed when a pool has lazily_build_dependencies_ set. +// Must be instantiated as mutable in a descriptor. +namespace internal { + +// The classes in this file represent a significant memory footprint for the +// library. We make sure we are not accidentally making them larger by +// hardcoding the struct size for a specific platform. Use as: +// +// PROTOBUF_INTERNAL_CHECK_CLASS_SIZE(type, expected_size_in_x84-64); +// + +#if !defined(PROTOBUF_INTERNAL_CHECK_CLASS_SIZE) +#define PROTOBUF_INTERNAL_CHECK_CLASS_SIZE(t, expected) +#endif + +class FlatAllocator; + +class PROTOBUF_EXPORT LazyDescriptor { + public: + // Init function to be called at init time of a descriptor containing + // a LazyDescriptor. + void Init() { + descriptor_ = nullptr; + once_ = nullptr; + } + + // Sets the value of the descriptor if it is known during the descriptor + // building process. Not thread safe, should only be called during the + // descriptor build process. Should not be called after SetLazy has been + // called. + void Set(const Descriptor* descriptor); + + // Sets the information needed to lazily cross link the descriptor at a later + // time, SetLazy is not thread safe, should be called only once at descriptor + // build time if the symbol wasn't found and building of the file containing + // that type is delayed because lazily_build_dependencies_ is set on the pool. + // Should not be called after Set() has been called. + void SetLazy(StringPiece name, const FileDescriptor* file); + + // Returns the current value of the descriptor, thread-safe. If SetLazy(...) + // has been called, will do a one-time cross link of the type specified, + // building the descriptor file that contains the type if necessary. + inline const Descriptor* Get(const ServiceDescriptor* service) { + Once(service); + return descriptor_; + } + + private: + void Once(const ServiceDescriptor* service); + + const Descriptor* descriptor_; + // The once_ flag is followed by a NUL terminated string for the type name. + internal::once_flag* once_; +}; + +class PROTOBUF_EXPORT SymbolBase { + private: + friend class google::protobuf::Symbol; + uint8_t symbol_type_; +}; + +// Some types have more than one SymbolBase because they have multiple +// identities in the table. We can't have duplicate direct bases, so we use this +// intermediate base to do so. +// See BuildEnumValue for details. +template <int N> +class PROTOBUF_EXPORT SymbolBaseN : public SymbolBase {}; + +} // namespace internal + +// Describes a type of protocol message, or a particular group within a +// message. To obtain the Descriptor for a given message object, call +// Message::GetDescriptor(). Generated message classes also have a +// static method called descriptor() which returns the type's descriptor. +// Use DescriptorPool to construct your own descriptors. +class PROTOBUF_EXPORT Descriptor : private internal::SymbolBase { + public: + typedef DescriptorProto Proto; + + // The name of the message type, not including its scope. + const std::string& name() const; + + // The fully-qualified name of the message type, scope delimited by + // periods. For example, message type "Foo" which is declared in package + // "bar" has full name "bar.Foo". If a type "Baz" is nested within + // Foo, Baz's full_name is "bar.Foo.Baz". To get only the part that + // comes after the last '.', use name(). + const std::string& full_name() const; + + // Index of this descriptor within the file or containing type's message + // type array. + int index() const; + + // The .proto file in which this message type was defined. Never nullptr. + const FileDescriptor* file() const; + + // If this Descriptor describes a nested type, this returns the type + // in which it is nested. Otherwise, returns nullptr. + const Descriptor* containing_type() const; + + // Get options for this message type. These are specified in the .proto file + // by placing lines like "option foo = 1234;" in the message definition. + // Allowed options are defined by MessageOptions in descriptor.proto, and any + // available extensions of that message. + const MessageOptions& options() const; + + // Write the contents of this Descriptor into the given DescriptorProto. + // The target DescriptorProto must be clear before calling this; if it + // isn't, the result may be garbage. + void CopyTo(DescriptorProto* proto) const; + + // Write the contents of this descriptor in a human-readable form. Output + // will be suitable for re-parsing. + std::string DebugString() const; + + // Similar to DebugString(), but additionally takes options (e.g., + // include original user comments in output). + std::string DebugStringWithOptions(const DebugStringOptions& options) const; + + // Returns true if this is a placeholder for an unknown type. This will + // only be the case if this descriptor comes from a DescriptorPool + // with AllowUnknownDependencies() set. + bool is_placeholder() const; + + enum WellKnownType { + WELLKNOWNTYPE_UNSPECIFIED, // Not a well-known type. + + // Wrapper types. + WELLKNOWNTYPE_DOUBLEVALUE, // google.protobuf.DoubleValue + WELLKNOWNTYPE_FLOATVALUE, // google.protobuf.FloatValue + WELLKNOWNTYPE_INT64VALUE, // google.protobuf.Int64Value + WELLKNOWNTYPE_UINT64VALUE, // google.protobuf.UInt64Value + WELLKNOWNTYPE_INT32VALUE, // google.protobuf.Int32Value + WELLKNOWNTYPE_UINT32VALUE, // google.protobuf.UInt32Value + WELLKNOWNTYPE_STRINGVALUE, // google.protobuf.StringValue + WELLKNOWNTYPE_BYTESVALUE, // google.protobuf.BytesValue + WELLKNOWNTYPE_BOOLVALUE, // google.protobuf.BoolValue + + // Other well known types. + WELLKNOWNTYPE_ANY, // google.protobuf.Any + WELLKNOWNTYPE_FIELDMASK, // google.protobuf.FieldMask + WELLKNOWNTYPE_DURATION, // google.protobuf.Duration + WELLKNOWNTYPE_TIMESTAMP, // google.protobuf.Timestamp + WELLKNOWNTYPE_VALUE, // google.protobuf.Value + WELLKNOWNTYPE_LISTVALUE, // google.protobuf.ListValue + WELLKNOWNTYPE_STRUCT, // google.protobuf.Struct + + // New well-known types may be added in the future. + // Please make sure any switch() statements have a 'default' case. + __WELLKNOWNTYPE__DO_NOT_USE__ADD_DEFAULT_INSTEAD__, + }; + + WellKnownType well_known_type() const; + + // Field stuff ----------------------------------------------------- + + // The number of fields in this message type. + int field_count() const; + // Gets a field by index, where 0 <= index < field_count(). + // These are returned in the order they were defined in the .proto file. + const FieldDescriptor* field(int index) const; + + // Looks up a field by declared tag number. Returns nullptr if no such field + // exists. + const FieldDescriptor* FindFieldByNumber(int number) const; + // Looks up a field by name. Returns nullptr if no such field exists. + const FieldDescriptor* FindFieldByName(ConstStringParam name) const; + + // Looks up a field by lowercased name (as returned by lowercase_name()). + // This lookup may be ambiguous if multiple field names differ only by case, + // in which case the field returned is chosen arbitrarily from the matches. + const FieldDescriptor* FindFieldByLowercaseName( + ConstStringParam lowercase_name) const; + + // Looks up a field by camel-case name (as returned by camelcase_name()). + // This lookup may be ambiguous if multiple field names differ in a way that + // leads them to have identical camel-case names, in which case the field + // returned is chosen arbitrarily from the matches. + const FieldDescriptor* FindFieldByCamelcaseName( + ConstStringParam camelcase_name) const; + + // The number of oneofs in this message type. + int oneof_decl_count() const; + // The number of oneofs in this message type, excluding synthetic oneofs. + // Real oneofs always come first, so iterating up to real_oneof_decl_cout() + // will yield all real oneofs. + int real_oneof_decl_count() const; + // Get a oneof by index, where 0 <= index < oneof_decl_count(). + // These are returned in the order they were defined in the .proto file. + const OneofDescriptor* oneof_decl(int index) const; + + // Looks up a oneof by name. Returns nullptr if no such oneof exists. + const OneofDescriptor* FindOneofByName(ConstStringParam name) const; + + // Nested type stuff ----------------------------------------------- + + // The number of nested types in this message type. + int nested_type_count() const; + // Gets a nested type by index, where 0 <= index < nested_type_count(). + // These are returned in the order they were defined in the .proto file. + const Descriptor* nested_type(int index) const; + + // Looks up a nested type by name. Returns nullptr if no such nested type + // exists. + const Descriptor* FindNestedTypeByName(ConstStringParam name) const; + + // Enum stuff ------------------------------------------------------ + + // The number of enum types in this message type. + int enum_type_count() const; + // Gets an enum type by index, where 0 <= index < enum_type_count(). + // These are returned in the order they were defined in the .proto file. + const EnumDescriptor* enum_type(int index) const; + + // Looks up an enum type by name. Returns nullptr if no such enum type + // exists. + const EnumDescriptor* FindEnumTypeByName(ConstStringParam name) const; + + // Looks up an enum value by name, among all enum types in this message. + // Returns nullptr if no such value exists. + const EnumValueDescriptor* FindEnumValueByName(ConstStringParam name) const; + + // Extensions ------------------------------------------------------ + + // A range of field numbers which are designated for third-party + // extensions. + struct ExtensionRange { + typedef DescriptorProto_ExtensionRange Proto; + + typedef ExtensionRangeOptions OptionsType; + + // See Descriptor::CopyTo(). + void CopyTo(DescriptorProto_ExtensionRange* proto) const; + + int start; // inclusive + int end; // exclusive + + const ExtensionRangeOptions* options_; + }; + + // The number of extension ranges in this message type. + int extension_range_count() const; + // Gets an extension range by index, where 0 <= index < + // extension_range_count(). These are returned in the order they were defined + // in the .proto file. + const ExtensionRange* extension_range(int index) const; + + // Returns true if the number is in one of the extension ranges. + bool IsExtensionNumber(int number) const; + + // Returns nullptr if no extension range contains the given number. + const ExtensionRange* FindExtensionRangeContainingNumber(int number) const; + + // The number of extensions defined nested within this message type's scope. + // See doc: + // https://developers.google.com/protocol-buffers/docs/proto#nested-extensions + // + // Note that the extensions may be extending *other* messages. + // + // For example: + // message M1 { + // extensions 1 to max; + // } + // + // message M2 { + // extend M1 { + // optional int32 foo = 1; + // } + // } + // + // In this case, + // DescriptorPool::generated_pool() + // ->FindMessageTypeByName("M2") + // ->extension(0) + // will return "foo", even though "foo" is an extension of M1. + // To find all known extensions of a given message, instead use + // DescriptorPool::FindAllExtensions. + int extension_count() const; + // Get an extension by index, where 0 <= index < extension_count(). + // These are returned in the order they were defined in the .proto file. + const FieldDescriptor* extension(int index) const; + + // Looks up a named extension (which extends some *other* message type) + // defined within this message type's scope. + const FieldDescriptor* FindExtensionByName(ConstStringParam name) const; + + // Similar to FindFieldByLowercaseName(), but finds extensions defined within + // this message type's scope. + const FieldDescriptor* FindExtensionByLowercaseName( + ConstStringParam name) const; + + // Similar to FindFieldByCamelcaseName(), but finds extensions defined within + // this message type's scope. + const FieldDescriptor* FindExtensionByCamelcaseName( + ConstStringParam name) const; + + // Reserved fields ------------------------------------------------- + + // A range of reserved field numbers. + struct ReservedRange { + int start; // inclusive + int end; // exclusive + }; + + // The number of reserved ranges in this message type. + int reserved_range_count() const; + // Gets an reserved range by index, where 0 <= index < + // reserved_range_count(). These are returned in the order they were defined + // in the .proto file. + const ReservedRange* reserved_range(int index) const; + + // Returns true if the number is in one of the reserved ranges. + bool IsReservedNumber(int number) const; + + // Returns nullptr if no reserved range contains the given number. + const ReservedRange* FindReservedRangeContainingNumber(int number) const; + + // The number of reserved field names in this message type. + int reserved_name_count() const; + + // Gets a reserved name by index, where 0 <= index < reserved_name_count(). + const std::string& reserved_name(int index) const; + + // Returns true if the field name is reserved. + bool IsReservedName(ConstStringParam name) const; + + // Source Location --------------------------------------------------- + + // Updates |*out_location| to the source location of the complete + // extent of this message declaration. Returns false and leaves + // |*out_location| unchanged iff location information was not available. + bool GetSourceLocation(SourceLocation* out_location) const; + + // Maps -------------------------------------------------------------- + + // Returns the FieldDescriptor for the "key" field. If this isn't a map entry + // field, returns nullptr. + const FieldDescriptor* map_key() const; + + // Returns the FieldDescriptor for the "value" field. If this isn't a map + // entry field, returns nullptr. + const FieldDescriptor* map_value() const; + + private: + friend class Symbol; + typedef MessageOptions OptionsType; + + // Allows tests to test CopyTo(proto, true). + friend class descriptor_unittest::DescriptorTest; + + // Allows access to GetLocationPath for annotations. + friend class io::Printer; + friend class compiler::cpp::Formatter; + + // Fill the json_name field of FieldDescriptorProto. + void CopyJsonNameTo(DescriptorProto* proto) const; + + // Internal version of DebugString; controls the level of indenting for + // correct depth. Takes |options| to control debug-string options, and + // |include_opening_clause| to indicate whether the "message ... " part of the + // clause has already been generated (this varies depending on context). + void DebugString(int depth, std::string* contents, + const DebugStringOptions& options, + bool include_opening_clause) const; + + // Walks up the descriptor tree to generate the source location path + // to this descriptor from the file root. + void GetLocationPath(std::vector<int>* output) const; + + // True if this is a placeholder for an unknown type. + bool is_placeholder_ : 1; + // True if this is a placeholder and the type name wasn't fully-qualified. + bool is_unqualified_placeholder_ : 1; + // Well known type. Stored like this to conserve space. + uint8_t well_known_type_ : 5; + + // This points to the last field _number_ that is part of the sequence + // starting at 1, where + // `desc->field(i)->number() == i + 1` + // A value of `0` means no field matches. That is, there are no fields or the + // first field is not field `1`. + // Uses 16-bit to avoid extra padding. Unlikely to have more than 2^16 + // sequentially numbered fields in a message. + uint16_t sequential_field_limit_; + + int field_count_; + + // all_names_ = [name, full_name] + const std::string* all_names_; + const FileDescriptor* file_; + const Descriptor* containing_type_; + const MessageOptions* options_; + + // These arrays are separated from their sizes to minimize padding on 64-bit. + FieldDescriptor* fields_; + OneofDescriptor* oneof_decls_; + Descriptor* nested_types_; + EnumDescriptor* enum_types_; + ExtensionRange* extension_ranges_; + FieldDescriptor* extensions_; + ReservedRange* reserved_ranges_; + const std::string** reserved_names_; + + int oneof_decl_count_; + int real_oneof_decl_count_; + int nested_type_count_; + int enum_type_count_; + int extension_range_count_; + int extension_count_; + int reserved_range_count_; + int reserved_name_count_; + + // IMPORTANT: If you add a new field, make sure to search for all instances + // of Allocate<Descriptor>() and AllocateArray<Descriptor>() in descriptor.cc + // and update them to initialize the field. + + // Must be constructed using DescriptorPool. + Descriptor() {} + friend class DescriptorBuilder; + friend class DescriptorPool; + friend class EnumDescriptor; + friend class FieldDescriptor; + friend class FileDescriptorTables; + friend class OneofDescriptor; + friend class MethodDescriptor; + friend class FileDescriptor; + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Descriptor); +}; + +PROTOBUF_INTERNAL_CHECK_CLASS_SIZE(Descriptor, 136); + +// Describes a single field of a message. To get the descriptor for a given +// field, first get the Descriptor for the message in which it is defined, +// then call Descriptor::FindFieldByName(). To get a FieldDescriptor for +// an extension, do one of the following: +// - Get the Descriptor or FileDescriptor for its containing scope, then +// call Descriptor::FindExtensionByName() or +// FileDescriptor::FindExtensionByName(). +// - Given a DescriptorPool, call DescriptorPool::FindExtensionByNumber() or +// DescriptorPool::FindExtensionByPrintableName(). +// Use DescriptorPool to construct your own descriptors. +class PROTOBUF_EXPORT FieldDescriptor : private internal::SymbolBase { + public: + typedef FieldDescriptorProto Proto; + + // Identifies a field type. 0 is reserved for errors. The order is weird + // for historical reasons. Types 12 and up are new in proto2. + enum Type { + TYPE_DOUBLE = 1, // double, exactly eight bytes on the wire. + TYPE_FLOAT = 2, // float, exactly four bytes on the wire. + TYPE_INT64 = 3, // int64, varint on the wire. Negative numbers + // take 10 bytes. Use TYPE_SINT64 if negative + // values are likely. + TYPE_UINT64 = 4, // uint64, varint on the wire. + TYPE_INT32 = 5, // int32, varint on the wire. Negative numbers + // take 10 bytes. Use TYPE_SINT32 if negative + // values are likely. + TYPE_FIXED64 = 6, // uint64, exactly eight bytes on the wire. + TYPE_FIXED32 = 7, // uint32, exactly four bytes on the wire. + TYPE_BOOL = 8, // bool, varint on the wire. + TYPE_STRING = 9, // UTF-8 text. + TYPE_GROUP = 10, // Tag-delimited message. Deprecated. + TYPE_MESSAGE = 11, // Length-delimited message. + + TYPE_BYTES = 12, // Arbitrary byte array. + TYPE_UINT32 = 13, // uint32, varint on the wire + TYPE_ENUM = 14, // Enum, varint on the wire + TYPE_SFIXED32 = 15, // int32, exactly four bytes on the wire + TYPE_SFIXED64 = 16, // int64, exactly eight bytes on the wire + TYPE_SINT32 = 17, // int32, ZigZag-encoded varint on the wire + TYPE_SINT64 = 18, // int64, ZigZag-encoded varint on the wire + + MAX_TYPE = 18, // Constant useful for defining lookup tables + // indexed by Type. + }; + + // Specifies the C++ data type used to represent the field. There is a + // fixed mapping from Type to CppType where each Type maps to exactly one + // CppType. 0 is reserved for errors. + enum CppType { + CPPTYPE_INT32 = 1, // TYPE_INT32, TYPE_SINT32, TYPE_SFIXED32 + CPPTYPE_INT64 = 2, // TYPE_INT64, TYPE_SINT64, TYPE_SFIXED64 + CPPTYPE_UINT32 = 3, // TYPE_UINT32, TYPE_FIXED32 + CPPTYPE_UINT64 = 4, // TYPE_UINT64, TYPE_FIXED64 + CPPTYPE_DOUBLE = 5, // TYPE_DOUBLE + CPPTYPE_FLOAT = 6, // TYPE_FLOAT + CPPTYPE_BOOL = 7, // TYPE_BOOL + CPPTYPE_ENUM = 8, // TYPE_ENUM + CPPTYPE_STRING = 9, // TYPE_STRING, TYPE_BYTES + CPPTYPE_MESSAGE = 10, // TYPE_MESSAGE, TYPE_GROUP + + MAX_CPPTYPE = 10, // Constant useful for defining lookup tables + // indexed by CppType. + }; + + // Identifies whether the field is optional, required, or repeated. 0 is + // reserved for errors. + enum Label { + LABEL_OPTIONAL = 1, // optional + LABEL_REQUIRED = 2, // required + LABEL_REPEATED = 3, // repeated + + MAX_LABEL = 3, // Constant useful for defining lookup tables + // indexed by Label. + }; + + // Valid field numbers are positive integers up to kMaxNumber. + static const int kMaxNumber = (1 << 29) - 1; + + // First field number reserved for the protocol buffer library implementation. + // Users may not declare fields that use reserved numbers. + static const int kFirstReservedNumber = 19000; + // Last field number reserved for the protocol buffer library implementation. + // Users may not declare fields that use reserved numbers. + static const int kLastReservedNumber = 19999; + + const std::string& name() const; // Name of this field within the message. + const std::string& full_name() const; // Fully-qualified name of the field. + const std::string& json_name() const; // JSON name of this field. + const FileDescriptor* file() const; // File in which this field was defined. + bool is_extension() const; // Is this an extension field? + int number() const; // Declared tag number. + + // Same as name() except converted to lower-case. This (and especially the + // FindFieldByLowercaseName() method) can be useful when parsing formats + // which prefer to use lowercase naming style. (Although, technically + // field names should be lowercased anyway according to the protobuf style + // guide, so this only makes a difference when dealing with old .proto files + // which do not follow the guide.) + const std::string& lowercase_name() const; + + // Same as name() except converted to camel-case. In this conversion, any + // time an underscore appears in the name, it is removed and the next + // letter is capitalized. Furthermore, the first letter of the name is + // lower-cased. Examples: + // FooBar -> fooBar + // foo_bar -> fooBar + // fooBar -> fooBar + // This (and especially the FindFieldByCamelcaseName() method) can be useful + // when parsing formats which prefer to use camel-case naming style. + const std::string& camelcase_name() const; + + Type type() const; // Declared type of this field. + const char* type_name() const; // Name of the declared type. + CppType cpp_type() const; // C++ type of this field. + const char* cpp_type_name() const; // Name of the C++ type. + Label label() const; // optional/required/repeated + + bool is_required() const; // shorthand for label() == LABEL_REQUIRED + bool is_optional() const; // shorthand for label() == LABEL_OPTIONAL + bool is_repeated() const; // shorthand for label() == LABEL_REPEATED + bool is_packable() const; // shorthand for is_repeated() && + // IsTypePackable(type()) + bool is_packed() const; // shorthand for is_packable() && + // options().packed() + bool is_map() const; // shorthand for type() == TYPE_MESSAGE && + // message_type()->options().map_entry() + + // Returns true if this field was syntactically written with "optional" in the + // .proto file. Excludes singular proto3 fields that do not have a label. + bool has_optional_keyword() const; + + // Returns true if this field tracks presence, ie. does the field + // distinguish between "unset" and "present with default value." + // This includes required, optional, and oneof fields. It excludes maps, + // repeated fields, and singular proto3 fields without "optional". + // + // For fields where has_presence() == true, the return value of + // Reflection::HasField() is semantically meaningful. + bool has_presence() const; + + // Index of this field within the message's field array, or the file or + // extension scope's extensions array. + int index() const; + + // Does this field have an explicitly-declared default value? + bool has_default_value() const; + + // Whether the user has specified the json_name field option in the .proto + // file. + bool has_json_name() const; + + // Get the field default value if cpp_type() == CPPTYPE_INT32. If no + // explicit default was defined, the default is 0. + int32_t default_value_int32_t() const; + int32_t default_value_int32() const { return default_value_int32_t(); } + // Get the field default value if cpp_type() == CPPTYPE_INT64. If no + // explicit default was defined, the default is 0. + int64_t default_value_int64_t() const; + int64_t default_value_int64() const { return default_value_int64_t(); } + // Get the field default value if cpp_type() == CPPTYPE_UINT32. If no + // explicit default was defined, the default is 0. + uint32_t default_value_uint32_t() const; + uint32_t default_value_uint32() const { return default_value_uint32_t(); } + // Get the field default value if cpp_type() == CPPTYPE_UINT64. If no + // explicit default was defined, the default is 0. + uint64_t default_value_uint64_t() const; + uint64_t default_value_uint64() const { return default_value_uint64_t(); } + // Get the field default value if cpp_type() == CPPTYPE_FLOAT. If no + // explicit default was defined, the default is 0.0. + float default_value_float() const; + // Get the field default value if cpp_type() == CPPTYPE_DOUBLE. If no + // explicit default was defined, the default is 0.0. + double default_value_double() const; + // Get the field default value if cpp_type() == CPPTYPE_BOOL. If no + // explicit default was defined, the default is false. + bool default_value_bool() const; + // Get the field default value if cpp_type() == CPPTYPE_ENUM. If no + // explicit default was defined, the default is the first value defined + // in the enum type (all enum types are required to have at least one value). + // This never returns nullptr. + const EnumValueDescriptor* default_value_enum() const; + // Get the field default value if cpp_type() == CPPTYPE_STRING. If no + // explicit default was defined, the default is the empty string. + const std::string& default_value_string() const; + + // The Descriptor for the message of which this is a field. For extensions, + // this is the extended type. Never nullptr. + const Descriptor* containing_type() const; + + // If the field is a member of a oneof, this is the one, otherwise this is + // nullptr. + const OneofDescriptor* containing_oneof() const; + + // If the field is a member of a non-synthetic oneof, returns the descriptor + // for the oneof, otherwise returns nullptr. + const OneofDescriptor* real_containing_oneof() const; + + // If the field is a member of a oneof, returns the index in that oneof. + int index_in_oneof() const; + + // An extension may be declared within the scope of another message. If this + // field is an extension (is_extension() is true), then extension_scope() + // returns that message, or nullptr if the extension was declared at global + // scope. If this is not an extension, extension_scope() is undefined (may + // assert-fail). + const Descriptor* extension_scope() const; + + // If type is TYPE_MESSAGE or TYPE_GROUP, returns a descriptor for the + // message or the group type. Otherwise, returns null. + const Descriptor* message_type() const; + // If type is TYPE_ENUM, returns a descriptor for the enum. Otherwise, + // returns null. + const EnumDescriptor* enum_type() const; + + // Get the FieldOptions for this field. This includes things listed in + // square brackets after the field definition. E.g., the field: + // optional string text = 1 [ctype=CORD]; + // has the "ctype" option set. Allowed options are defined by FieldOptions in + // descriptor.proto, and any available extensions of that message. + const FieldOptions& options() const; + + // See Descriptor::CopyTo(). + void CopyTo(FieldDescriptorProto* proto) const; + + // See Descriptor::DebugString(). + std::string DebugString() const; + + // See Descriptor::DebugStringWithOptions(). + std::string DebugStringWithOptions(const DebugStringOptions& options) const; + + // Helper method to get the CppType for a particular Type. + static CppType TypeToCppType(Type type); + + // Helper method to get the name of a Type. + static const char* TypeName(Type type); + + // Helper method to get the name of a CppType. + static const char* CppTypeName(CppType cpp_type); + + // Return true iff [packed = true] is valid for fields of this type. + static inline bool IsTypePackable(Type field_type); + + // Returns full_name() except if the field is a MessageSet extension, + // in which case it returns the full_name() of the containing message type + // for backwards compatibility with proto1. + // + // A MessageSet extension is defined as an optional message extension + // whose containing type has the message_set_wire_format option set. + // This should be true of extensions of google.protobuf.bridge.MessageSet; + // by convention, such extensions are named "message_set_extension". + // + // The opposite operation (looking up an extension's FieldDescriptor given + // its printable name) can be accomplished with + // message->file()->pool()->FindExtensionByPrintableName(message, name) + // where the extension extends "message". + const std::string& PrintableNameForExtension() const; + + // Source Location --------------------------------------------------- + + // Updates |*out_location| to the source location of the complete + // extent of this field declaration. Returns false and leaves + // |*out_location| unchanged iff location information was not available. + bool GetSourceLocation(SourceLocation* out_location) const; + + private: + friend class Symbol; + typedef FieldOptions OptionsType; + + // Allows access to GetLocationPath for annotations. + friend class io::Printer; + friend class compiler::cpp::Formatter; + friend class Reflection; + + // Fill the json_name field of FieldDescriptorProto. + void CopyJsonNameTo(FieldDescriptorProto* proto) const; + + // See Descriptor::DebugString(). + void DebugString(int depth, std::string* contents, + const DebugStringOptions& options) const; + + // formats the default value appropriately and returns it as a string. + // Must have a default value to call this. If quote_string_type is true, then + // types of CPPTYPE_STRING whill be surrounded by quotes and CEscaped. + std::string DefaultValueAsString(bool quote_string_type) const; + + // Helper function that returns the field type name for DebugString. + std::string FieldTypeNameDebugString() const; + + // Walks up the descriptor tree to generate the source location path + // to this descriptor from the file root. + void GetLocationPath(std::vector<int>* output) const; + + // Returns true if this is a map message type. + bool is_map_message_type() const; + + bool has_default_value_ : 1; + bool proto3_optional_ : 1; + // Whether the user has specified the json_name field option in the .proto + // file. + bool has_json_name_ : 1; + bool is_extension_ : 1; + bool is_oneof_ : 1; + + // Actually a `Label` but stored as uint8_t to save space. + uint8_t label_ : 2; + + // Actually a `Type`, but stored as uint8_t to save space. + mutable uint8_t type_; + + // Logically: + // all_names_ = [name, full_name, lower, camel, json] + // However: + // duplicates will be omitted, so lower/camel/json might be in the same + // position. + // We store the true offset for each name here, and the bit width must be + // large enough to account for the worst case where all names are present. + uint8_t lowercase_name_index_ : 2; + uint8_t camelcase_name_index_ : 2; + uint8_t json_name_index_ : 3; + // Sadly, `number_` located here to reduce padding. Unrelated to all_names_ + // and its indices above. + int number_; + const std::string* all_names_; + const FileDescriptor* file_; + + // The once_flag is followed by a NUL terminated string for the type name and + // enum default value (or empty string if no default enum). + internal::once_flag* type_once_; + static void TypeOnceInit(const FieldDescriptor* to_init); + void InternalTypeOnceInit() const; + const Descriptor* containing_type_; + union { + const OneofDescriptor* containing_oneof; + const Descriptor* extension_scope; + } scope_; + union { + mutable const Descriptor* message_type; + mutable const EnumDescriptor* enum_type; + } type_descriptor_; + const FieldOptions* options_; + // IMPORTANT: If you add a new field, make sure to search for all instances + // of Allocate<FieldDescriptor>() and AllocateArray<FieldDescriptor>() in + // descriptor.cc and update them to initialize the field. + + union { + int32_t default_value_int32_t_; + int64_t default_value_int64_t_; + uint32_t default_value_uint32_t_; + uint64_t default_value_uint64_t_; + float default_value_float_; + double default_value_double_; + bool default_value_bool_; + + mutable const EnumValueDescriptor* default_value_enum_; + const std::string* default_value_string_; + mutable std::atomic<const Message*> default_generated_instance_; + }; + + static const CppType kTypeToCppTypeMap[MAX_TYPE + 1]; + + static const char* const kTypeToName[MAX_TYPE + 1]; + + static const char* const kCppTypeToName[MAX_CPPTYPE + 1]; + + static const char* const kLabelToName[MAX_LABEL + 1]; + + // Must be constructed using DescriptorPool. + FieldDescriptor() {} + friend class DescriptorBuilder; + friend class FileDescriptor; + friend class Descriptor; + friend class OneofDescriptor; + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FieldDescriptor); +}; + +PROTOBUF_INTERNAL_CHECK_CLASS_SIZE(FieldDescriptor, 72); + +// Describes a oneof defined in a message type. +class PROTOBUF_EXPORT OneofDescriptor : private internal::SymbolBase { + public: + typedef OneofDescriptorProto Proto; + + const std::string& name() const; // Name of this oneof. + const std::string& full_name() const; // Fully-qualified name of the oneof. + + // Index of this oneof within the message's oneof array. + int index() const; + + // Returns whether this oneof was inserted by the compiler to wrap a proto3 + // optional field. If this returns true, code generators should *not* emit it. + bool is_synthetic() const; + + // The .proto file in which this oneof was defined. Never nullptr. + const FileDescriptor* file() const; + // The Descriptor for the message containing this oneof. + const Descriptor* containing_type() const; + + // The number of (non-extension) fields which are members of this oneof. + int field_count() const; + // Get a member of this oneof, in the order in which they were declared in the + // .proto file. Does not include extensions. + const FieldDescriptor* field(int index) const; + + const OneofOptions& options() const; + + // See Descriptor::CopyTo(). + void CopyTo(OneofDescriptorProto* proto) const; + + // See Descriptor::DebugString(). + std::string DebugString() const; + + // See Descriptor::DebugStringWithOptions(). + std::string DebugStringWithOptions(const DebugStringOptions& options) const; + + // Source Location --------------------------------------------------- + + // Updates |*out_location| to the source location of the complete + // extent of this oneof declaration. Returns false and leaves + // |*out_location| unchanged iff location information was not available. + bool GetSourceLocation(SourceLocation* out_location) const; + + private: + friend class Symbol; + typedef OneofOptions OptionsType; + + // Allows access to GetLocationPath for annotations. + friend class io::Printer; + friend class compiler::cpp::Formatter; + + // See Descriptor::DebugString(). + void DebugString(int depth, std::string* contents, + const DebugStringOptions& options) const; + + // Walks up the descriptor tree to generate the source location path + // to this descriptor from the file root. + void GetLocationPath(std::vector<int>* output) const; + + int field_count_; + + // all_names_ = [name, full_name] + const std::string* all_names_; + const Descriptor* containing_type_; + const OneofOptions* options_; + const FieldDescriptor* fields_; + + // IMPORTANT: If you add a new field, make sure to search for all instances + // of Allocate<OneofDescriptor>() and AllocateArray<OneofDescriptor>() + // in descriptor.cc and update them to initialize the field. + + // Must be constructed using DescriptorPool. + OneofDescriptor() {} + friend class DescriptorBuilder; + friend class Descriptor; + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(OneofDescriptor); +}; + +PROTOBUF_INTERNAL_CHECK_CLASS_SIZE(OneofDescriptor, 40); + +// Describes an enum type defined in a .proto file. To get the EnumDescriptor +// for a generated enum type, call TypeName_descriptor(). Use DescriptorPool +// to construct your own descriptors. +class PROTOBUF_EXPORT EnumDescriptor : private internal::SymbolBase { + public: + typedef EnumDescriptorProto Proto; + + // The name of this enum type in the containing scope. + const std::string& name() const; + + // The fully-qualified name of the enum type, scope delimited by periods. + const std::string& full_name() const; + + // Index of this enum within the file or containing message's enum array. + int index() const; + + // The .proto file in which this enum type was defined. Never nullptr. + const FileDescriptor* file() const; + + // The number of values for this EnumDescriptor. Guaranteed to be greater + // than zero. + int value_count() const; + // Gets a value by index, where 0 <= index < value_count(). + // These are returned in the order they were defined in the .proto file. + const EnumValueDescriptor* value(int index) const; + + // Looks up a value by name. Returns nullptr if no such value exists. + const EnumValueDescriptor* FindValueByName(ConstStringParam name) const; + // Looks up a value by number. Returns nullptr if no such value exists. If + // multiple values have this number, the first one defined is returned. + const EnumValueDescriptor* FindValueByNumber(int number) const; + + // If this enum type is nested in a message type, this is that message type. + // Otherwise, nullptr. + const Descriptor* containing_type() const; + + // Get options for this enum type. These are specified in the .proto file by + // placing lines like "option foo = 1234;" in the enum definition. Allowed + // options are defined by EnumOptions in descriptor.proto, and any available + // extensions of that message. + const EnumOptions& options() const; + + // See Descriptor::CopyTo(). + void CopyTo(EnumDescriptorProto* proto) const; + + // See Descriptor::DebugString(). + std::string DebugString() const; + + // See Descriptor::DebugStringWithOptions(). + std::string DebugStringWithOptions(const DebugStringOptions& options) const; + + // Returns true if this is a placeholder for an unknown enum. This will + // only be the case if this descriptor comes from a DescriptorPool + // with AllowUnknownDependencies() set. + bool is_placeholder() const; + + // Reserved fields ------------------------------------------------- + + // A range of reserved field numbers. + struct ReservedRange { + int start; // inclusive + int end; // inclusive + }; + + // The number of reserved ranges in this message type. + int reserved_range_count() const; + // Gets an reserved range by index, where 0 <= index < + // reserved_range_count(). These are returned in the order they were defined + // in the .proto file. + const EnumDescriptor::ReservedRange* reserved_range(int index) const; + + // Returns true if the number is in one of the reserved ranges. + bool IsReservedNumber(int number) const; + + // Returns nullptr if no reserved range contains the given number. + const EnumDescriptor::ReservedRange* FindReservedRangeContainingNumber( + int number) const; + + // The number of reserved field names in this message type. + int reserved_name_count() const; + + // Gets a reserved name by index, where 0 <= index < reserved_name_count(). + const std::string& reserved_name(int index) const; + + // Returns true if the field name is reserved. + bool IsReservedName(ConstStringParam name) const; + + // Source Location --------------------------------------------------- + + // Updates |*out_location| to the source location of the complete + // extent of this enum declaration. Returns false and leaves + // |*out_location| unchanged iff location information was not available. + bool GetSourceLocation(SourceLocation* out_location) const; + + private: + friend class Symbol; + typedef EnumOptions OptionsType; + + // Allows access to GetLocationPath for annotations. + friend class io::Printer; + friend class compiler::cpp::Formatter; + + // Allow access to FindValueByNumberCreatingIfUnknown. + friend class descriptor_unittest::DescriptorTest; + + // Looks up a value by number. If the value does not exist, dynamically + // creates a new EnumValueDescriptor for that value, assuming that it was + // unknown. If a new descriptor is created, this is done in a thread-safe way, + // and future calls will return the same value descriptor pointer. + // + // This is private but is used by Reflection (which is friended below) to + // return a valid EnumValueDescriptor from GetEnum() when this feature is + // enabled. + const EnumValueDescriptor* FindValueByNumberCreatingIfUnknown( + int number) const; + + // See Descriptor::DebugString(). + void DebugString(int depth, std::string* contents, + const DebugStringOptions& options) const; + + // Walks up the descriptor tree to generate the source location path + // to this descriptor from the file root. + void GetLocationPath(std::vector<int>* output) const; + + // True if this is a placeholder for an unknown type. + bool is_placeholder_ : 1; + // True if this is a placeholder and the type name wasn't fully-qualified. + bool is_unqualified_placeholder_ : 1; + + // This points to the last value _index_ that is part of the sequence starting + // with the first label, where + // `enum->value(i)->number() == enum->value(0)->number() + i` + // We measure relative to the first label to adapt to enum labels starting at + // 0 or 1. + // Uses 16-bit to avoid extra padding. Unlikely to have more than 2^15 + // sequentially numbered labels in an enum. + int16_t sequential_value_limit_; + + int value_count_; + + // all_names_ = [name, full_name] + const std::string* all_names_; + const FileDescriptor* file_; + const Descriptor* containing_type_; + const EnumOptions* options_; + EnumValueDescriptor* values_; + + int reserved_range_count_; + int reserved_name_count_; + EnumDescriptor::ReservedRange* reserved_ranges_; + const std::string** reserved_names_; + + // IMPORTANT: If you add a new field, make sure to search for all instances + // of Allocate<EnumDescriptor>() and AllocateArray<EnumDescriptor>() in + // descriptor.cc and update them to initialize the field. + + // Must be constructed using DescriptorPool. + EnumDescriptor() {} + friend class DescriptorBuilder; + friend class Descriptor; + friend class FieldDescriptor; + friend class FileDescriptorTables; + friend class EnumValueDescriptor; + friend class FileDescriptor; + friend class DescriptorPool; + friend class Reflection; + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(EnumDescriptor); +}; + +PROTOBUF_INTERNAL_CHECK_CLASS_SIZE(EnumDescriptor, 72); + +// Describes an individual enum constant of a particular type. To get the +// EnumValueDescriptor for a given enum value, first get the EnumDescriptor +// for its type, then use EnumDescriptor::FindValueByName() or +// EnumDescriptor::FindValueByNumber(). Use DescriptorPool to construct +// your own descriptors. +class PROTOBUF_EXPORT EnumValueDescriptor : private internal::SymbolBaseN<0>, + private internal::SymbolBaseN<1> { + public: + typedef EnumValueDescriptorProto Proto; + + const std::string& name() const; // Name of this enum constant. + int index() const; // Index within the enums's Descriptor. + int number() const; // Numeric value of this enum constant. + + // The full_name of an enum value is a sibling symbol of the enum type. + // e.g. the full name of FieldDescriptorProto::TYPE_INT32 is actually + // "google.protobuf.FieldDescriptorProto.TYPE_INT32", NOT + // "google.protobuf.FieldDescriptorProto.Type.TYPE_INT32". This is to conform + // with C++ scoping rules for enums. + const std::string& full_name() const; + + // The .proto file in which this value was defined. Never nullptr. + const FileDescriptor* file() const; + // The type of this value. Never nullptr. + const EnumDescriptor* type() const; + + // Get options for this enum value. These are specified in the .proto file by + // adding text like "[foo = 1234]" after an enum value definition. Allowed + // options are defined by EnumValueOptions in descriptor.proto, and any + // available extensions of that message. + const EnumValueOptions& options() const; + + // See Descriptor::CopyTo(). + void CopyTo(EnumValueDescriptorProto* proto) const; + + // See Descriptor::DebugString(). + std::string DebugString() const; + + // See Descriptor::DebugStringWithOptions(). + std::string DebugStringWithOptions(const DebugStringOptions& options) const; + + // Source Location --------------------------------------------------- + + // Updates |*out_location| to the source location of the complete + // extent of this enum value declaration. Returns false and leaves + // |*out_location| unchanged iff location information was not available. + bool GetSourceLocation(SourceLocation* out_location) const; + + private: + friend class Symbol; + typedef EnumValueOptions OptionsType; + + // Allows access to GetLocationPath for annotations. + friend class io::Printer; + friend class compiler::cpp::Formatter; + + // See Descriptor::DebugString(). + void DebugString(int depth, std::string* contents, + const DebugStringOptions& options) const; + + // Walks up the descriptor tree to generate the source location path + // to this descriptor from the file root. + void GetLocationPath(std::vector<int>* output) const; + + int number_; + // all_names_ = [name, full_name] + const std::string* all_names_; + const EnumDescriptor* type_; + const EnumValueOptions* options_; + // IMPORTANT: If you add a new field, make sure to search for all instances + // of Allocate<EnumValueDescriptor>() and AllocateArray<EnumValueDescriptor>() + // in descriptor.cc and update them to initialize the field. + + // Must be constructed using DescriptorPool. + EnumValueDescriptor() {} + friend class DescriptorBuilder; + friend class EnumDescriptor; + friend class DescriptorPool; + friend class FileDescriptorTables; + friend class Reflection; + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(EnumValueDescriptor); +}; + +PROTOBUF_INTERNAL_CHECK_CLASS_SIZE(EnumValueDescriptor, 32); + +// Describes an RPC service. Use DescriptorPool to construct your own +// descriptors. +class PROTOBUF_EXPORT ServiceDescriptor : private internal::SymbolBase { + public: + typedef ServiceDescriptorProto Proto; + + // The name of the service, not including its containing scope. + const std::string& name() const; + // The fully-qualified name of the service, scope delimited by periods. + const std::string& full_name() const; + // Index of this service within the file's services array. + int index() const; + + // The .proto file in which this service was defined. Never nullptr. + const FileDescriptor* file() const; + + // Get options for this service type. These are specified in the .proto file + // by placing lines like "option foo = 1234;" in the service definition. + // Allowed options are defined by ServiceOptions in descriptor.proto, and any + // available extensions of that message. + const ServiceOptions& options() const; + + // The number of methods this service defines. + int method_count() const; + // Gets a MethodDescriptor by index, where 0 <= index < method_count(). + // These are returned in the order they were defined in the .proto file. + const MethodDescriptor* method(int index) const; + + // Look up a MethodDescriptor by name. + const MethodDescriptor* FindMethodByName(ConstStringParam name) const; + + // See Descriptor::CopyTo(). + void CopyTo(ServiceDescriptorProto* proto) const; + + // See Descriptor::DebugString(). + std::string DebugString() const; + + // See Descriptor::DebugStringWithOptions(). + std::string DebugStringWithOptions(const DebugStringOptions& options) const; + + // Source Location --------------------------------------------------- + + // Updates |*out_location| to the source location of the complete + // extent of this service declaration. Returns false and leaves + // |*out_location| unchanged iff location information was not available. + bool GetSourceLocation(SourceLocation* out_location) const; + + private: + friend class Symbol; + typedef ServiceOptions OptionsType; + + // Allows access to GetLocationPath for annotations. + friend class io::Printer; + friend class compiler::cpp::Formatter; + + // See Descriptor::DebugString(). + void DebugString(std::string* contents, + const DebugStringOptions& options) const; + + // Walks up the descriptor tree to generate the source location path + // to this descriptor from the file root. + void GetLocationPath(std::vector<int>* output) const; + + // all_names_ = [name, full_name] + const std::string* all_names_; + const FileDescriptor* file_; + const ServiceOptions* options_; + MethodDescriptor* methods_; + int method_count_; + // IMPORTANT: If you add a new field, make sure to search for all instances + // of Allocate<ServiceDescriptor>() and AllocateArray<ServiceDescriptor>() in + // descriptor.cc and update them to initialize the field. + + // Must be constructed using DescriptorPool. + ServiceDescriptor() {} + friend class DescriptorBuilder; + friend class FileDescriptor; + friend class MethodDescriptor; + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ServiceDescriptor); +}; + +PROTOBUF_INTERNAL_CHECK_CLASS_SIZE(ServiceDescriptor, 48); + +// Describes an individual service method. To obtain a MethodDescriptor given +// a service, first get its ServiceDescriptor, then call +// ServiceDescriptor::FindMethodByName(). Use DescriptorPool to construct your +// own descriptors. +class PROTOBUF_EXPORT MethodDescriptor : private internal::SymbolBase { + public: + typedef MethodDescriptorProto Proto; + + // Name of this method, not including containing scope. + const std::string& name() const; + // The fully-qualified name of the method, scope delimited by periods. + const std::string& full_name() const; + // Index within the service's Descriptor. + int index() const; + + // The .proto file in which this method was defined. Never nullptr. + const FileDescriptor* file() const; + // Gets the service to which this method belongs. Never nullptr. + const ServiceDescriptor* service() const; + + // Gets the type of protocol message which this method accepts as input. + const Descriptor* input_type() const; + // Gets the type of protocol message which this message produces as output. + const Descriptor* output_type() const; + + // Gets whether the client streams multiple requests. + bool client_streaming() const; + // Gets whether the server streams multiple responses. + bool server_streaming() const; + + // Get options for this method. These are specified in the .proto file by + // placing lines like "option foo = 1234;" in curly-braces after a method + // declaration. Allowed options are defined by MethodOptions in + // descriptor.proto, and any available extensions of that message. + const MethodOptions& options() const; + + // See Descriptor::CopyTo(). + void CopyTo(MethodDescriptorProto* proto) const; + + // See Descriptor::DebugString(). + std::string DebugString() const; + + // See Descriptor::DebugStringWithOptions(). + std::string DebugStringWithOptions(const DebugStringOptions& options) const; + + // Source Location --------------------------------------------------- + + // Updates |*out_location| to the source location of the complete + // extent of this method declaration. Returns false and leaves + // |*out_location| unchanged iff location information was not available. + bool GetSourceLocation(SourceLocation* out_location) const; + + private: + friend class Symbol; + typedef MethodOptions OptionsType; + + // Allows access to GetLocationPath for annotations. + friend class io::Printer; + friend class compiler::cpp::Formatter; + + // See Descriptor::DebugString(). + void DebugString(int depth, std::string* contents, + const DebugStringOptions& options) const; + + // Walks up the descriptor tree to generate the source location path + // to this descriptor from the file root. + void GetLocationPath(std::vector<int>* output) const; + + bool client_streaming_; + bool server_streaming_; + // all_names_ = [name, full_name] + const std::string* all_names_; + const ServiceDescriptor* service_; + mutable internal::LazyDescriptor input_type_; + mutable internal::LazyDescriptor output_type_; + const MethodOptions* options_; + // IMPORTANT: If you add a new field, make sure to search for all instances + // of Allocate<MethodDescriptor>() and AllocateArray<MethodDescriptor>() in + // descriptor.cc and update them to initialize the field. + + // Must be constructed using DescriptorPool. + MethodDescriptor() {} + friend class DescriptorBuilder; + friend class ServiceDescriptor; + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MethodDescriptor); +}; + +PROTOBUF_INTERNAL_CHECK_CLASS_SIZE(MethodDescriptor, 64); + +// Describes a whole .proto file. To get the FileDescriptor for a compiled-in +// file, get the descriptor for something defined in that file and call +// descriptor->file(). Use DescriptorPool to construct your own descriptors. +class PROTOBUF_EXPORT FileDescriptor : private internal::SymbolBase { + public: + typedef FileDescriptorProto Proto; + + // The filename, relative to the source tree. + // e.g. "foo/bar/baz.proto" + const std::string& name() const; + + // The package, e.g. "google.protobuf.compiler". + const std::string& package() const; + + // The DescriptorPool in which this FileDescriptor and all its contents were + // allocated. Never nullptr. + const DescriptorPool* pool() const; + + // The number of files imported by this one. + int dependency_count() const; + // Gets an imported file by index, where 0 <= index < dependency_count(). + // These are returned in the order they were defined in the .proto file. + const FileDescriptor* dependency(int index) const; + + // The number of files public imported by this one. + // The public dependency list is a subset of the dependency list. + int public_dependency_count() const; + // Gets a public imported file by index, where 0 <= index < + // public_dependency_count(). + // These are returned in the order they were defined in the .proto file. + const FileDescriptor* public_dependency(int index) const; + + // The number of files that are imported for weak fields. + // The weak dependency list is a subset of the dependency list. + int weak_dependency_count() const; + // Gets a weak imported file by index, where 0 <= index < + // weak_dependency_count(). + // These are returned in the order they were defined in the .proto file. + const FileDescriptor* weak_dependency(int index) const; + + // Number of top-level message types defined in this file. (This does not + // include nested types.) + int message_type_count() const; + // Gets a top-level message type, where 0 <= index < message_type_count(). + // These are returned in the order they were defined in the .proto file. + const Descriptor* message_type(int index) const; + + // Number of top-level enum types defined in this file. (This does not + // include nested types.) + int enum_type_count() const; + // Gets a top-level enum type, where 0 <= index < enum_type_count(). + // These are returned in the order they were defined in the .proto file. + const EnumDescriptor* enum_type(int index) const; + + // Number of services defined in this file. + int service_count() const; + // Gets a service, where 0 <= index < service_count(). + // These are returned in the order they were defined in the .proto file. + const ServiceDescriptor* service(int index) const; + + // Number of extensions defined at file scope. (This does not include + // extensions nested within message types.) + int extension_count() const; + // Gets an extension's descriptor, where 0 <= index < extension_count(). + // These are returned in the order they were defined in the .proto file. + const FieldDescriptor* extension(int index) const; + + // Get options for this file. These are specified in the .proto file by + // placing lines like "option foo = 1234;" at the top level, outside of any + // other definitions. Allowed options are defined by FileOptions in + // descriptor.proto, and any available extensions of that message. + const FileOptions& options() const; + + // Syntax of this file. + enum Syntax { + SYNTAX_UNKNOWN = 0, + SYNTAX_PROTO2 = 2, + SYNTAX_PROTO3 = 3, + }; + Syntax syntax() const; + static const char* SyntaxName(Syntax syntax); + + // Find a top-level message type by name (not full_name). Returns nullptr if + // not found. + const Descriptor* FindMessageTypeByName(ConstStringParam name) const; + // Find a top-level enum type by name. Returns nullptr if not found. + const EnumDescriptor* FindEnumTypeByName(ConstStringParam name) const; + // Find an enum value defined in any top-level enum by name. Returns nullptr + // if not found. + const EnumValueDescriptor* FindEnumValueByName(ConstStringParam name) const; + // Find a service definition by name. Returns nullptr if not found. + const ServiceDescriptor* FindServiceByName(ConstStringParam name) const; + // Find a top-level extension definition by name. Returns nullptr if not + // found. + const FieldDescriptor* FindExtensionByName(ConstStringParam name) const; + // Similar to FindExtensionByName(), but searches by lowercased-name. See + // Descriptor::FindFieldByLowercaseName(). + const FieldDescriptor* FindExtensionByLowercaseName( + ConstStringParam name) const; + // Similar to FindExtensionByName(), but searches by camelcased-name. See + // Descriptor::FindFieldByCamelcaseName(). + const FieldDescriptor* FindExtensionByCamelcaseName( + ConstStringParam name) const; + + // See Descriptor::CopyTo(). + // Notes: + // - This method does NOT copy source code information since it is relatively + // large and rarely needed. See CopySourceCodeInfoTo() below. + void CopyTo(FileDescriptorProto* proto) const; + // Write the source code information of this FileDescriptor into the given + // FileDescriptorProto. See CopyTo() above. + void CopySourceCodeInfoTo(FileDescriptorProto* proto) const; + // Fill the json_name field of FieldDescriptorProto for all fields. Can only + // be called after CopyTo(). + void CopyJsonNameTo(FileDescriptorProto* proto) const; + + // See Descriptor::DebugString(). + std::string DebugString() const; + + // See Descriptor::DebugStringWithOptions(). + std::string DebugStringWithOptions(const DebugStringOptions& options) const; + + // Returns true if this is a placeholder for an unknown file. This will + // only be the case if this descriptor comes from a DescriptorPool + // with AllowUnknownDependencies() set. + bool is_placeholder() const; + + // Updates |*out_location| to the source location of the complete extent of + // this file declaration (namely, the empty path). + bool GetSourceLocation(SourceLocation* out_location) const; + + // Updates |*out_location| to the source location of the complete + // extent of the declaration or declaration-part denoted by |path|. + // Returns false and leaves |*out_location| unchanged iff location + // information was not available. (See SourceCodeInfo for + // description of path encoding.) + bool GetSourceLocation(const std::vector<int>& path, + SourceLocation* out_location) const; + + private: + friend class Symbol; + typedef FileOptions OptionsType; + + bool is_placeholder_; + // Indicates the FileDescriptor is completed building. Used to verify + // that type accessor functions that can possibly build a dependent file + // aren't called during the process of building the file. + bool finished_building_; + // Actually a `Syntax` but stored as uint8_t to save space. + uint8_t syntax_; + // This one is here to fill the padding. + int extension_count_; + + const std::string* name_; + const std::string* package_; + const DescriptorPool* pool_; + + // dependencies_once_ contain a once_flag followed by N NUL terminated + // strings. Dependencies that do not need to be loaded will be empty. ie just + // {'\0'} + internal::once_flag* dependencies_once_; + static void DependenciesOnceInit(const FileDescriptor* to_init); + void InternalDependenciesOnceInit() const; + + // These are arranged to minimize padding on 64-bit. + int dependency_count_; + int public_dependency_count_; + int weak_dependency_count_; + int message_type_count_; + int enum_type_count_; + int service_count_; + + mutable const FileDescriptor** dependencies_; + int* public_dependencies_; + int* weak_dependencies_; + Descriptor* message_types_; + EnumDescriptor* enum_types_; + ServiceDescriptor* services_; + FieldDescriptor* extensions_; + const FileOptions* options_; + + const FileDescriptorTables* tables_; + const SourceCodeInfo* source_code_info_; + + // IMPORTANT: If you add a new field, make sure to search for all instances + // of Allocate<FileDescriptor>() and AllocateArray<FileDescriptor>() in + // descriptor.cc and update them to initialize the field. + + FileDescriptor() {} + friend class DescriptorBuilder; + friend class DescriptorPool; + friend class Descriptor; + friend class FieldDescriptor; + friend class internal::LazyDescriptor; + friend class OneofDescriptor; + friend class EnumDescriptor; + friend class EnumValueDescriptor; + friend class MethodDescriptor; + friend class ServiceDescriptor; + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FileDescriptor); +}; + +PROTOBUF_INTERNAL_CHECK_CLASS_SIZE(FileDescriptor, 144); + +// =================================================================== + +// Used to construct descriptors. +// +// Normally you won't want to build your own descriptors. Message classes +// constructed by the protocol compiler will provide them for you. However, +// if you are implementing Message on your own, or if you are writing a +// program which can operate on totally arbitrary types and needs to load +// them from some sort of database, you might need to. +// +// Since Descriptors are composed of a whole lot of cross-linked bits of +// data that would be a pain to put together manually, the +// DescriptorPool class is provided to make the process easier. It can +// take a FileDescriptorProto (defined in descriptor.proto), validate it, +// and convert it to a set of nicely cross-linked Descriptors. +// +// DescriptorPool also helps with memory management. Descriptors are +// composed of many objects containing static data and pointers to each +// other. In all likelihood, when it comes time to delete this data, +// you'll want to delete it all at once. In fact, it is not uncommon to +// have a whole pool of descriptors all cross-linked with each other which +// you wish to delete all at once. This class represents such a pool, and +// handles the memory management for you. +// +// You can also search for descriptors within a DescriptorPool by name, and +// extensions by number. +class PROTOBUF_EXPORT DescriptorPool { + public: + // Create a normal, empty DescriptorPool. + DescriptorPool(); + + // Constructs a DescriptorPool that, when it can't find something among the + // descriptors already in the pool, looks for it in the given + // DescriptorDatabase. + // Notes: + // - If a DescriptorPool is constructed this way, its BuildFile*() methods + // must not be called (they will assert-fail). The only way to populate + // the pool with descriptors is to call the Find*By*() methods. + // - The Find*By*() methods may block the calling thread if the + // DescriptorDatabase blocks. This in turn means that parsing messages + // may block if they need to look up extensions. + // - The Find*By*() methods will use mutexes for thread-safety, thus making + // them slower even when they don't have to fall back to the database. + // In fact, even the Find*By*() methods of descriptor objects owned by + // this pool will be slower, since they will have to obtain locks too. + // - An ErrorCollector may optionally be given to collect validation errors + // in files loaded from the database. If not given, errors will be printed + // to GOOGLE_LOG(ERROR). Remember that files are built on-demand, so this + // ErrorCollector may be called from any thread that calls one of the + // Find*By*() methods. + // - The DescriptorDatabase must not be mutated during the lifetime of + // the DescriptorPool. Even if the client takes care to avoid data races, + // changes to the content of the DescriptorDatabase may not be reflected + // in subsequent lookups in the DescriptorPool. + class ErrorCollector; + explicit DescriptorPool(DescriptorDatabase* fallback_database, + ErrorCollector* error_collector = nullptr); + + ~DescriptorPool(); + + // Get a pointer to the generated pool. Generated protocol message classes + // which are compiled into the binary will allocate their descriptors in + // this pool. Do not add your own descriptors to this pool. + static const DescriptorPool* generated_pool(); + + + // Find a FileDescriptor in the pool by file name. Returns nullptr if not + // found. + const FileDescriptor* FindFileByName(ConstStringParam name) const; + + // Find the FileDescriptor in the pool which defines the given symbol. + // If any of the Find*ByName() methods below would succeed, then this is + // equivalent to calling that method and calling the result's file() method. + // Otherwise this returns nullptr. + const FileDescriptor* FindFileContainingSymbol( + ConstStringParam symbol_name) const; + + // Looking up descriptors ------------------------------------------ + // These find descriptors by fully-qualified name. These will find both + // top-level descriptors and nested descriptors. They return nullptr if not + // found. + + const Descriptor* FindMessageTypeByName(ConstStringParam name) const; + const FieldDescriptor* FindFieldByName(ConstStringParam name) const; + const FieldDescriptor* FindExtensionByName(ConstStringParam name) const; + const OneofDescriptor* FindOneofByName(ConstStringParam name) const; + const EnumDescriptor* FindEnumTypeByName(ConstStringParam name) const; + const EnumValueDescriptor* FindEnumValueByName(ConstStringParam name) const; + const ServiceDescriptor* FindServiceByName(ConstStringParam name) const; + const MethodDescriptor* FindMethodByName(ConstStringParam name) const; + + // Finds an extension of the given type by number. The extendee must be + // a member of this DescriptorPool or one of its underlays. + const FieldDescriptor* FindExtensionByNumber(const Descriptor* extendee, + int number) const; + + // Finds an extension of the given type by its printable name. + // See comments above PrintableNameForExtension() for the definition of + // "printable name". The extendee must be a member of this DescriptorPool + // or one of its underlays. Returns nullptr if there is no known message + // extension with the given printable name. + const FieldDescriptor* FindExtensionByPrintableName( + const Descriptor* extendee, ConstStringParam printable_name) const; + + // Finds extensions of extendee. The extensions will be appended to + // out in an undefined order. Only extensions defined directly in + // this DescriptorPool or one of its underlays are guaranteed to be + // found: extensions defined in the fallback database might not be found + // depending on the database implementation. + void FindAllExtensions(const Descriptor* extendee, + std::vector<const FieldDescriptor*>* out) const; + + // Building descriptors -------------------------------------------- + + // When converting a FileDescriptorProto to a FileDescriptor, various + // errors might be detected in the input. The caller may handle these + // programmatically by implementing an ErrorCollector. + class PROTOBUF_EXPORT ErrorCollector { + public: + inline ErrorCollector() {} + virtual ~ErrorCollector(); + + // These constants specify what exact part of the construct is broken. + // This is useful e.g. for mapping the error back to an exact location + // in a .proto file. + enum ErrorLocation { + NAME, // the symbol name, or the package name for files + NUMBER, // field or extension range number + TYPE, // field type + EXTENDEE, // field extendee + DEFAULT_VALUE, // field default value + INPUT_TYPE, // method input type + OUTPUT_TYPE, // method output type + OPTION_NAME, // name in assignment + OPTION_VALUE, // value in option assignment + IMPORT, // import error + OTHER // some other problem + }; + + // Reports an error in the FileDescriptorProto. Use this function if the + // problem occurred should interrupt building the FileDescriptorProto. + virtual void AddError( + const std::string& filename, // File name in which the error occurred. + const std::string& element_name, // Full name of the erroneous element. + const Message* descriptor, // Descriptor of the erroneous element. + ErrorLocation location, // One of the location constants, above. + const std::string& message // Human-readable error message. + ) = 0; + + // Reports a warning in the FileDescriptorProto. Use this function if the + // problem occurred should NOT interrupt building the FileDescriptorProto. + virtual void AddWarning( + const std::string& /*filename*/, // File name in which the error + // occurred. + const std::string& /*element_name*/, // Full name of the erroneous + // element. + const Message* /*descriptor*/, // Descriptor of the erroneous element. + ErrorLocation /*location*/, // One of the location constants, above. + const std::string& /*message*/ // Human-readable error message. + ) {} + + private: + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ErrorCollector); + }; + + // Convert the FileDescriptorProto to real descriptors and place them in + // this DescriptorPool. All dependencies of the file must already be in + // the pool. Returns the resulting FileDescriptor, or nullptr if there were + // problems with the input (e.g. the message was invalid, or dependencies + // were missing). Details about the errors are written to GOOGLE_LOG(ERROR). + const FileDescriptor* BuildFile(const FileDescriptorProto& proto); + + // Same as BuildFile() except errors are sent to the given ErrorCollector. + const FileDescriptor* BuildFileCollectingErrors( + const FileDescriptorProto& proto, ErrorCollector* error_collector); + + // By default, it is an error if a FileDescriptorProto contains references + // to types or other files that are not found in the DescriptorPool (or its + // backing DescriptorDatabase, if any). If you call + // AllowUnknownDependencies(), however, then unknown types and files + // will be replaced by placeholder descriptors (which can be identified by + // the is_placeholder() method). This can allow you to + // perform some useful operations with a .proto file even if you do not + // have access to other .proto files on which it depends. However, some + // heuristics must be used to fill in the gaps in information, and these + // can lead to descriptors which are inaccurate. For example, the + // DescriptorPool may be forced to guess whether an unknown type is a message + // or an enum, as well as what package it resides in. Furthermore, + // placeholder types will not be discoverable via FindMessageTypeByName() + // and similar methods, which could confuse some descriptor-based algorithms. + // Generally, the results of this option should be handled with extreme care. + void AllowUnknownDependencies() { allow_unknown_ = true; } + + // By default, weak imports are allowed to be missing, in which case we will + // use a placeholder for the dependency and convert the field to be an Empty + // message field. If you call EnforceWeakDependencies(true), however, the + // DescriptorPool will report a import not found error. + void EnforceWeakDependencies(bool enforce) { enforce_weak_ = enforce; } + + // Internal stuff -------------------------------------------------- + // These methods MUST NOT be called from outside the proto2 library. + // These methods may contain hidden pitfalls and may be removed in a + // future library version. + + // Create a DescriptorPool which is overlaid on top of some other pool. + // If you search for a descriptor in the overlay and it is not found, the + // underlay will be searched as a backup. If the underlay has its own + // underlay, that will be searched next, and so on. This also means that + // files built in the overlay will be cross-linked with the underlay's + // descriptors if necessary. The underlay remains property of the caller; + // it must remain valid for the lifetime of the newly-constructed pool. + // + // Example: Say you want to parse a .proto file at runtime in order to use + // its type with a DynamicMessage. Say this .proto file has dependencies, + // but you know that all the dependencies will be things that are already + // compiled into the binary. For ease of use, you'd like to load the types + // right out of generated_pool() rather than have to parse redundant copies + // of all these .protos and runtime. But, you don't want to add the parsed + // types directly into generated_pool(): this is not allowed, and would be + // bad design anyway. So, instead, you could use generated_pool() as an + // underlay for a new DescriptorPool in which you add only the new file. + // + // WARNING: Use of underlays can lead to many subtle gotchas. Instead, + // try to formulate what you want to do in terms of DescriptorDatabases. + explicit DescriptorPool(const DescriptorPool* underlay); + + // Called by generated classes at init time to add their descriptors to + // generated_pool. Do NOT call this in your own code! filename must be a + // permanent string (e.g. a string literal). + static void InternalAddGeneratedFile(const void* encoded_file_descriptor, + int size); + + // Disallow [enforce_utf8 = false] in .proto files. + void DisallowEnforceUtf8() { disallow_enforce_utf8_ = true; } + + + // For internal use only: Gets a non-const pointer to the generated pool. + // This is called at static-initialization time only, so thread-safety is + // not a concern. If both an underlay and a fallback database are present, + // the underlay takes precedence. + static DescriptorPool* internal_generated_pool(); + + // For internal use only: Gets a non-const pointer to the generated + // descriptor database. + // Only used for testing. + static DescriptorDatabase* internal_generated_database(); + + // For internal use only: Changes the behavior of BuildFile() such that it + // allows the file to make reference to message types declared in other files + // which it did not officially declare as dependencies. + void InternalDontEnforceDependencies(); + + // For internal use only: Enables lazy building of dependencies of a file. + // Delay the building of dependencies of a file descriptor until absolutely + // necessary, like when message_type() is called on a field that is defined + // in that dependency's file. This will cause functional issues if a proto + // or one of its dependencies has errors. Should only be enabled for the + // generated_pool_ (because no descriptor build errors are guaranteed by + // the compilation generation process), testing, or if a lack of descriptor + // build errors can be guaranteed for a pool. + void InternalSetLazilyBuildDependencies() { + lazily_build_dependencies_ = true; + // This needs to be set when lazily building dependencies, as it breaks + // dependency checking. + InternalDontEnforceDependencies(); + } + + // For internal use only. + void internal_set_underlay(const DescriptorPool* underlay) { + underlay_ = underlay; + } + + // For internal (unit test) use only: Returns true if a FileDescriptor has + // been constructed for the given file, false otherwise. Useful for testing + // lazy descriptor initialization behavior. + bool InternalIsFileLoaded(ConstStringParam filename) const; + + // Add a file to unused_import_track_files_. DescriptorBuilder will log + // warnings or errors for those files if there is any unused import. + void AddUnusedImportTrackFile(ConstStringParam file_name, + bool is_error = false); + void ClearUnusedImportTrackFiles(); + + private: + friend class Descriptor; + friend class internal::LazyDescriptor; + friend class FieldDescriptor; + friend class EnumDescriptor; + friend class ServiceDescriptor; + friend class MethodDescriptor; + friend class FileDescriptor; + friend class DescriptorBuilder; + friend class FileDescriptorTables; + + // Return true if the given name is a sub-symbol of any non-package + // descriptor that already exists in the descriptor pool. (The full + // definition of such types is already known.) + bool IsSubSymbolOfBuiltType(StringPiece name) const; + + // Tries to find something in the fallback database and link in the + // corresponding proto file. Returns true if successful, in which case + // the caller should search for the thing again. These are declared + // const because they are called by (semantically) const methods. + bool TryFindFileInFallbackDatabase(StringPiece name) const; + bool TryFindSymbolInFallbackDatabase(StringPiece name) const; + bool TryFindExtensionInFallbackDatabase(const Descriptor* containing_type, + int field_number) const; + + // This internal find extension method only check with its table and underlay + // descriptor_pool's table. It does not check with fallback DB and no + // additional proto file will be build in this method. + const FieldDescriptor* InternalFindExtensionByNumberNoLock( + const Descriptor* extendee, int number) const; + + // Like BuildFile() but called internally when the file has been loaded from + // fallback_database_. Declared const because it is called by (semantically) + // const methods. + const FileDescriptor* BuildFileFromDatabase( + const FileDescriptorProto& proto) const; + + // Helper for when lazily_build_dependencies_ is set, can look up a symbol + // after the file's descriptor is built, and can build the file where that + // symbol is defined if necessary. Will create a placeholder if the type + // doesn't exist in the fallback database, or the file doesn't build + // successfully. + Symbol CrossLinkOnDemandHelper(StringPiece name, + bool expecting_enum) const; + + // Create a placeholder FileDescriptor of the specified name + FileDescriptor* NewPlaceholderFile(StringPiece name) const; + FileDescriptor* NewPlaceholderFileWithMutexHeld( + StringPiece name, internal::FlatAllocator& alloc) const; + + enum PlaceholderType { + PLACEHOLDER_MESSAGE, + PLACEHOLDER_ENUM, + PLACEHOLDER_EXTENDABLE_MESSAGE + }; + // Create a placeholder Descriptor of the specified name + Symbol NewPlaceholder(StringPiece name, + PlaceholderType placeholder_type) const; + Symbol NewPlaceholderWithMutexHeld(StringPiece name, + PlaceholderType placeholder_type) const; + + // If fallback_database_ is nullptr, this is nullptr. Otherwise, this is a + // mutex which must be locked while accessing tables_. + internal::WrappedMutex* mutex_; + + // See constructor. + DescriptorDatabase* fallback_database_; + ErrorCollector* default_error_collector_; + const DescriptorPool* underlay_; + + // This class contains a lot of hash maps with complicated types that + // we'd like to keep out of the header. + class Tables; + std::unique_ptr<Tables> tables_; + + bool enforce_dependencies_; + bool lazily_build_dependencies_; + bool allow_unknown_; + bool enforce_weak_; + bool disallow_enforce_utf8_; + + // Set of files to track for unused imports. The bool value when true means + // unused imports are treated as errors (and as warnings when false). + std::map<std::string, bool> unused_import_track_files_; + + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(DescriptorPool); +}; + + +// inline methods ==================================================== + +// These macros makes this repetitive code more readable. +#define PROTOBUF_DEFINE_ACCESSOR(CLASS, FIELD, TYPE) \ + inline TYPE CLASS::FIELD() const { return FIELD##_; } + +// Strings fields are stored as pointers but returned as const references. +#define PROTOBUF_DEFINE_STRING_ACCESSOR(CLASS, FIELD) \ + inline const std::string& CLASS::FIELD() const { return *FIELD##_; } + +// Name and full name are stored in a single array to save space. +#define PROTOBUF_DEFINE_NAME_ACCESSOR(CLASS) \ + inline const std::string& CLASS::name() const { return all_names_[0]; } \ + inline const std::string& CLASS::full_name() const { return all_names_[1]; } + +// Arrays take an index parameter, obviously. +#define PROTOBUF_DEFINE_ARRAY_ACCESSOR(CLASS, FIELD, TYPE) \ + inline TYPE CLASS::FIELD(int index) const { return FIELD##s_ + index; } + +#define PROTOBUF_DEFINE_OPTIONS_ACCESSOR(CLASS, TYPE) \ + inline const TYPE& CLASS::options() const { return *options_; } + +PROTOBUF_DEFINE_NAME_ACCESSOR(Descriptor) +PROTOBUF_DEFINE_ACCESSOR(Descriptor, file, const FileDescriptor*) +PROTOBUF_DEFINE_ACCESSOR(Descriptor, containing_type, const Descriptor*) + +PROTOBUF_DEFINE_ACCESSOR(Descriptor, field_count, int) +PROTOBUF_DEFINE_ACCESSOR(Descriptor, oneof_decl_count, int) +PROTOBUF_DEFINE_ACCESSOR(Descriptor, real_oneof_decl_count, int) +PROTOBUF_DEFINE_ACCESSOR(Descriptor, nested_type_count, int) +PROTOBUF_DEFINE_ACCESSOR(Descriptor, enum_type_count, int) + +PROTOBUF_DEFINE_ARRAY_ACCESSOR(Descriptor, field, const FieldDescriptor*) +PROTOBUF_DEFINE_ARRAY_ACCESSOR(Descriptor, oneof_decl, const OneofDescriptor*) +PROTOBUF_DEFINE_ARRAY_ACCESSOR(Descriptor, nested_type, const Descriptor*) +PROTOBUF_DEFINE_ARRAY_ACCESSOR(Descriptor, enum_type, const EnumDescriptor*) + +PROTOBUF_DEFINE_ACCESSOR(Descriptor, extension_range_count, int) +PROTOBUF_DEFINE_ACCESSOR(Descriptor, extension_count, int) +PROTOBUF_DEFINE_ARRAY_ACCESSOR(Descriptor, extension_range, + const Descriptor::ExtensionRange*) +PROTOBUF_DEFINE_ARRAY_ACCESSOR(Descriptor, extension, const FieldDescriptor*) + +PROTOBUF_DEFINE_ACCESSOR(Descriptor, reserved_range_count, int) +PROTOBUF_DEFINE_ARRAY_ACCESSOR(Descriptor, reserved_range, + const Descriptor::ReservedRange*) +PROTOBUF_DEFINE_ACCESSOR(Descriptor, reserved_name_count, int) + +PROTOBUF_DEFINE_OPTIONS_ACCESSOR(Descriptor, MessageOptions) +PROTOBUF_DEFINE_ACCESSOR(Descriptor, is_placeholder, bool) + +PROTOBUF_DEFINE_NAME_ACCESSOR(FieldDescriptor) +PROTOBUF_DEFINE_ACCESSOR(FieldDescriptor, file, const FileDescriptor*) +PROTOBUF_DEFINE_ACCESSOR(FieldDescriptor, number, int) +PROTOBUF_DEFINE_ACCESSOR(FieldDescriptor, is_extension, bool) +PROTOBUF_DEFINE_ACCESSOR(FieldDescriptor, containing_type, const Descriptor*) +PROTOBUF_DEFINE_OPTIONS_ACCESSOR(FieldDescriptor, FieldOptions) +PROTOBUF_DEFINE_ACCESSOR(FieldDescriptor, has_default_value, bool) +PROTOBUF_DEFINE_ACCESSOR(FieldDescriptor, has_json_name, bool) +PROTOBUF_DEFINE_ACCESSOR(FieldDescriptor, default_value_int32_t, int32_t) +PROTOBUF_DEFINE_ACCESSOR(FieldDescriptor, default_value_int64_t, int64_t) +PROTOBUF_DEFINE_ACCESSOR(FieldDescriptor, default_value_uint32_t, uint32_t) +PROTOBUF_DEFINE_ACCESSOR(FieldDescriptor, default_value_uint64_t, uint64_t) +PROTOBUF_DEFINE_ACCESSOR(FieldDescriptor, default_value_float, float) +PROTOBUF_DEFINE_ACCESSOR(FieldDescriptor, default_value_double, double) +PROTOBUF_DEFINE_ACCESSOR(FieldDescriptor, default_value_bool, bool) +PROTOBUF_DEFINE_STRING_ACCESSOR(FieldDescriptor, default_value_string) + +PROTOBUF_DEFINE_NAME_ACCESSOR(OneofDescriptor) +PROTOBUF_DEFINE_ACCESSOR(OneofDescriptor, containing_type, const Descriptor*) +PROTOBUF_DEFINE_ACCESSOR(OneofDescriptor, field_count, int) +PROTOBUF_DEFINE_ARRAY_ACCESSOR(OneofDescriptor, field, const FieldDescriptor*) +PROTOBUF_DEFINE_OPTIONS_ACCESSOR(OneofDescriptor, OneofOptions) + +PROTOBUF_DEFINE_NAME_ACCESSOR(EnumDescriptor) +PROTOBUF_DEFINE_ACCESSOR(EnumDescriptor, file, const FileDescriptor*) +PROTOBUF_DEFINE_ACCESSOR(EnumDescriptor, containing_type, const Descriptor*) +PROTOBUF_DEFINE_ACCESSOR(EnumDescriptor, value_count, int) +PROTOBUF_DEFINE_ARRAY_ACCESSOR(EnumDescriptor, value, + const EnumValueDescriptor*) +PROTOBUF_DEFINE_OPTIONS_ACCESSOR(EnumDescriptor, EnumOptions) +PROTOBUF_DEFINE_ACCESSOR(EnumDescriptor, is_placeholder, bool) +PROTOBUF_DEFINE_ACCESSOR(EnumDescriptor, reserved_range_count, int) +PROTOBUF_DEFINE_ARRAY_ACCESSOR(EnumDescriptor, reserved_range, + const EnumDescriptor::ReservedRange*) +PROTOBUF_DEFINE_ACCESSOR(EnumDescriptor, reserved_name_count, int) + +PROTOBUF_DEFINE_NAME_ACCESSOR(EnumValueDescriptor) +PROTOBUF_DEFINE_ACCESSOR(EnumValueDescriptor, number, int) +PROTOBUF_DEFINE_ACCESSOR(EnumValueDescriptor, type, const EnumDescriptor*) +PROTOBUF_DEFINE_OPTIONS_ACCESSOR(EnumValueDescriptor, EnumValueOptions) + +PROTOBUF_DEFINE_NAME_ACCESSOR(ServiceDescriptor) +PROTOBUF_DEFINE_ACCESSOR(ServiceDescriptor, file, const FileDescriptor*) +PROTOBUF_DEFINE_ACCESSOR(ServiceDescriptor, method_count, int) +PROTOBUF_DEFINE_ARRAY_ACCESSOR(ServiceDescriptor, method, + const MethodDescriptor*) +PROTOBUF_DEFINE_OPTIONS_ACCESSOR(ServiceDescriptor, ServiceOptions) + +PROTOBUF_DEFINE_NAME_ACCESSOR(MethodDescriptor) +PROTOBUF_DEFINE_ACCESSOR(MethodDescriptor, service, const ServiceDescriptor*) +PROTOBUF_DEFINE_OPTIONS_ACCESSOR(MethodDescriptor, MethodOptions) +PROTOBUF_DEFINE_ACCESSOR(MethodDescriptor, client_streaming, bool) +PROTOBUF_DEFINE_ACCESSOR(MethodDescriptor, server_streaming, bool) + +PROTOBUF_DEFINE_STRING_ACCESSOR(FileDescriptor, name) +PROTOBUF_DEFINE_STRING_ACCESSOR(FileDescriptor, package) +PROTOBUF_DEFINE_ACCESSOR(FileDescriptor, pool, const DescriptorPool*) +PROTOBUF_DEFINE_ACCESSOR(FileDescriptor, dependency_count, int) +PROTOBUF_DEFINE_ACCESSOR(FileDescriptor, public_dependency_count, int) +PROTOBUF_DEFINE_ACCESSOR(FileDescriptor, weak_dependency_count, int) +PROTOBUF_DEFINE_ACCESSOR(FileDescriptor, message_type_count, int) +PROTOBUF_DEFINE_ACCESSOR(FileDescriptor, enum_type_count, int) +PROTOBUF_DEFINE_ACCESSOR(FileDescriptor, service_count, int) +PROTOBUF_DEFINE_ACCESSOR(FileDescriptor, extension_count, int) +PROTOBUF_DEFINE_OPTIONS_ACCESSOR(FileDescriptor, FileOptions) +PROTOBUF_DEFINE_ACCESSOR(FileDescriptor, is_placeholder, bool) + +PROTOBUF_DEFINE_ARRAY_ACCESSOR(FileDescriptor, message_type, const Descriptor*) +PROTOBUF_DEFINE_ARRAY_ACCESSOR(FileDescriptor, enum_type, const EnumDescriptor*) +PROTOBUF_DEFINE_ARRAY_ACCESSOR(FileDescriptor, service, + const ServiceDescriptor*) +PROTOBUF_DEFINE_ARRAY_ACCESSOR(FileDescriptor, extension, + const FieldDescriptor*) + +#undef PROTOBUF_DEFINE_ACCESSOR +#undef PROTOBUF_DEFINE_STRING_ACCESSOR +#undef PROTOBUF_DEFINE_ARRAY_ACCESSOR + +// A few accessors differ from the macros... + +inline Descriptor::WellKnownType Descriptor::well_known_type() const { + return static_cast<Descriptor::WellKnownType>(well_known_type_); +} + +inline bool Descriptor::IsExtensionNumber(int number) const { + return FindExtensionRangeContainingNumber(number) != nullptr; +} + +inline bool Descriptor::IsReservedNumber(int number) const { + return FindReservedRangeContainingNumber(number) != nullptr; +} + +inline bool Descriptor::IsReservedName(ConstStringParam name) const { + for (int i = 0; i < reserved_name_count(); i++) { + if (name == static_cast<ConstStringParam>(reserved_name(i))) { + return true; + } + } + return false; +} + +// Can't use PROTOBUF_DEFINE_ARRAY_ACCESSOR because reserved_names_ is actually +// an array of pointers rather than the usual array of objects. +inline const std::string& Descriptor::reserved_name(int index) const { + return *reserved_names_[index]; +} + +inline bool EnumDescriptor::IsReservedNumber(int number) const { + return FindReservedRangeContainingNumber(number) != nullptr; +} + +inline bool EnumDescriptor::IsReservedName(ConstStringParam name) const { + for (int i = 0; i < reserved_name_count(); i++) { + if (name == static_cast<ConstStringParam>(reserved_name(i))) { + return true; + } + } + return false; +} + +// Can't use PROTOBUF_DEFINE_ARRAY_ACCESSOR because reserved_names_ is actually +// an array of pointers rather than the usual array of objects. +inline const std::string& EnumDescriptor::reserved_name(int index) const { + return *reserved_names_[index]; +} + +inline const std::string& FieldDescriptor::lowercase_name() const { + return all_names_[lowercase_name_index_]; +} + +inline const std::string& FieldDescriptor::camelcase_name() const { + return all_names_[camelcase_name_index_]; +} + +inline const std::string& FieldDescriptor::json_name() const { + return all_names_[json_name_index_]; +} + +inline const OneofDescriptor* FieldDescriptor::containing_oneof() const { + return is_oneof_ ? scope_.containing_oneof : nullptr; +} + +inline int FieldDescriptor::index_in_oneof() const { + GOOGLE_DCHECK(is_oneof_); + return static_cast<int>(this - scope_.containing_oneof->field(0)); +} + +inline const Descriptor* FieldDescriptor::extension_scope() const { + GOOGLE_CHECK(is_extension_); + return scope_.extension_scope; +} + +inline FieldDescriptor::Label FieldDescriptor::label() const { + return static_cast<Label>(label_); +} + +inline FieldDescriptor::Type FieldDescriptor::type() const { + if (type_once_) { + internal::call_once(*type_once_, &FieldDescriptor::TypeOnceInit, this); + } + return static_cast<Type>(type_); +} + +inline bool FieldDescriptor::is_required() const { + return label() == LABEL_REQUIRED; +} + +inline bool FieldDescriptor::is_optional() const { + return label() == LABEL_OPTIONAL; +} + +inline bool FieldDescriptor::is_repeated() const { + return label() == LABEL_REPEATED; +} + +inline bool FieldDescriptor::is_packable() const { + return is_repeated() && IsTypePackable(type()); +} + +inline bool FieldDescriptor::is_map() const { + return type() == TYPE_MESSAGE && is_map_message_type(); +} + +inline bool FieldDescriptor::has_optional_keyword() const { + return proto3_optional_ || + (file()->syntax() == FileDescriptor::SYNTAX_PROTO2 && is_optional() && + !containing_oneof()); +} + +inline const OneofDescriptor* FieldDescriptor::real_containing_oneof() const { + auto* oneof = containing_oneof(); + return oneof && !oneof->is_synthetic() ? oneof : nullptr; +} + +inline bool FieldDescriptor::has_presence() const { + if (is_repeated()) return false; + return cpp_type() == CPPTYPE_MESSAGE || containing_oneof() || + file()->syntax() == FileDescriptor::SYNTAX_PROTO2; +} + +// To save space, index() is computed by looking at the descriptor's position +// in the parent's array of children. +inline int FieldDescriptor::index() const { + if (!is_extension_) { + return static_cast<int>(this - containing_type()->fields_); + } else if (extension_scope() != nullptr) { + return static_cast<int>(this - extension_scope()->extensions_); + } else { + return static_cast<int>(this - file_->extensions_); + } +} + +inline int Descriptor::index() const { + if (containing_type_ == nullptr) { + return static_cast<int>(this - file_->message_types_); + } else { + return static_cast<int>(this - containing_type_->nested_types_); + } +} + +inline const FileDescriptor* OneofDescriptor::file() const { + return containing_type()->file(); +} + +inline int OneofDescriptor::index() const { + return static_cast<int>(this - containing_type_->oneof_decls_); +} + +inline bool OneofDescriptor::is_synthetic() const { + return field_count() == 1 && field(0)->proto3_optional_; +} + +inline int EnumDescriptor::index() const { + if (containing_type_ == nullptr) { + return static_cast<int>(this - file_->enum_types_); + } else { + return static_cast<int>(this - containing_type_->enum_types_); + } +} + +inline const FileDescriptor* EnumValueDescriptor::file() const { + return type()->file(); +} + +inline int EnumValueDescriptor::index() const { + return static_cast<int>(this - type_->values_); +} + +inline int ServiceDescriptor::index() const { + return static_cast<int>(this - file_->services_); +} + +inline const FileDescriptor* MethodDescriptor::file() const { + return service()->file(); +} + +inline int MethodDescriptor::index() const { + return static_cast<int>(this - service_->methods_); +} + +inline const char* FieldDescriptor::type_name() const { + return kTypeToName[type()]; +} + +inline FieldDescriptor::CppType FieldDescriptor::cpp_type() const { + return kTypeToCppTypeMap[type()]; +} + +inline const char* FieldDescriptor::cpp_type_name() const { + return kCppTypeToName[kTypeToCppTypeMap[type()]]; +} + +inline FieldDescriptor::CppType FieldDescriptor::TypeToCppType(Type type) { + return kTypeToCppTypeMap[type]; +} + +inline const char* FieldDescriptor::TypeName(Type type) { + return kTypeToName[type]; +} + +inline const char* FieldDescriptor::CppTypeName(CppType cpp_type) { + return kCppTypeToName[cpp_type]; +} + +inline bool FieldDescriptor::IsTypePackable(Type field_type) { + return (field_type != FieldDescriptor::TYPE_STRING && + field_type != FieldDescriptor::TYPE_GROUP && + field_type != FieldDescriptor::TYPE_MESSAGE && + field_type != FieldDescriptor::TYPE_BYTES); +} + +inline const FileDescriptor* FileDescriptor::public_dependency( + int index) const { + return dependency(public_dependencies_[index]); +} + +inline const FileDescriptor* FileDescriptor::weak_dependency(int index) const { + return dependency(weak_dependencies_[index]); +} + +inline FileDescriptor::Syntax FileDescriptor::syntax() const { + return static_cast<Syntax>(syntax_); +} + +} // namespace protobuf +} // namespace google + +#undef PROTOBUF_INTERNAL_CHECK_CLASS_SIZE +#include <google/protobuf/port_undef.inc> + +#endif // GOOGLE_PROTOBUF_DESCRIPTOR_H__ diff --git a/toolkit/components/protobuf/src/google/protobuf/descriptor.pb.cc b/toolkit/components/protobuf/src/google/protobuf/descriptor.pb.cc new file mode 100644 index 0000000000..d3bfb461ea --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/descriptor.pb.cc @@ -0,0 +1,11351 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: google/protobuf/descriptor.proto + +#include <google/protobuf/descriptor.pb.h> + +#include <algorithm> + +#include <google/protobuf/io/coded_stream.h> +#include <google/protobuf/extension_set.h> +#include <google/protobuf/wire_format_lite.h> +#include <google/protobuf/descriptor.h> +#include <google/protobuf/generated_message_reflection.h> +#include <google/protobuf/reflection_ops.h> +#include <google/protobuf/wire_format.h> +// @@protoc_insertion_point(includes) +#include <google/protobuf/port_def.inc> + +PROTOBUF_PRAGMA_INIT_SEG + +namespace _pb = ::PROTOBUF_NAMESPACE_ID; +namespace _pbi = _pb::internal; + +PROTOBUF_NAMESPACE_OPEN +PROTOBUF_CONSTEXPR FileDescriptorSet::FileDescriptorSet( + ::_pbi::ConstantInitialized): _impl_{ + /*decltype(_impl_.file_)*/{} + , /*decltype(_impl_._cached_size_)*/{}} {} +struct FileDescriptorSetDefaultTypeInternal { + PROTOBUF_CONSTEXPR FileDescriptorSetDefaultTypeInternal() + : _instance(::_pbi::ConstantInitialized{}) {} + ~FileDescriptorSetDefaultTypeInternal() {} + union { + FileDescriptorSet _instance; + }; +}; +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 FileDescriptorSetDefaultTypeInternal _FileDescriptorSet_default_instance_; +PROTOBUF_CONSTEXPR FileDescriptorProto::FileDescriptorProto( + ::_pbi::ConstantInitialized): _impl_{ + /*decltype(_impl_._has_bits_)*/{} + , /*decltype(_impl_._cached_size_)*/{} + , /*decltype(_impl_.dependency_)*/{} + , /*decltype(_impl_.message_type_)*/{} + , /*decltype(_impl_.enum_type_)*/{} + , /*decltype(_impl_.service_)*/{} + , /*decltype(_impl_.extension_)*/{} + , /*decltype(_impl_.public_dependency_)*/{} + , /*decltype(_impl_.weak_dependency_)*/{} + , /*decltype(_impl_.name_)*/{&::_pbi::fixed_address_empty_string, ::_pbi::ConstantInitialized{}} + , /*decltype(_impl_.package_)*/{&::_pbi::fixed_address_empty_string, ::_pbi::ConstantInitialized{}} + , /*decltype(_impl_.syntax_)*/{&::_pbi::fixed_address_empty_string, ::_pbi::ConstantInitialized{}} + , /*decltype(_impl_.options_)*/nullptr + , /*decltype(_impl_.source_code_info_)*/nullptr} {} +struct FileDescriptorProtoDefaultTypeInternal { + PROTOBUF_CONSTEXPR FileDescriptorProtoDefaultTypeInternal() + : _instance(::_pbi::ConstantInitialized{}) {} + ~FileDescriptorProtoDefaultTypeInternal() {} + union { + FileDescriptorProto _instance; + }; +}; +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 FileDescriptorProtoDefaultTypeInternal _FileDescriptorProto_default_instance_; +PROTOBUF_CONSTEXPR DescriptorProto_ExtensionRange::DescriptorProto_ExtensionRange( + ::_pbi::ConstantInitialized): _impl_{ + /*decltype(_impl_._has_bits_)*/{} + , /*decltype(_impl_._cached_size_)*/{} + , /*decltype(_impl_.options_)*/nullptr + , /*decltype(_impl_.start_)*/0 + , /*decltype(_impl_.end_)*/0} {} +struct DescriptorProto_ExtensionRangeDefaultTypeInternal { + PROTOBUF_CONSTEXPR DescriptorProto_ExtensionRangeDefaultTypeInternal() + : _instance(::_pbi::ConstantInitialized{}) {} + ~DescriptorProto_ExtensionRangeDefaultTypeInternal() {} + union { + DescriptorProto_ExtensionRange _instance; + }; +}; +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 DescriptorProto_ExtensionRangeDefaultTypeInternal _DescriptorProto_ExtensionRange_default_instance_; +PROTOBUF_CONSTEXPR DescriptorProto_ReservedRange::DescriptorProto_ReservedRange( + ::_pbi::ConstantInitialized): _impl_{ + /*decltype(_impl_._has_bits_)*/{} + , /*decltype(_impl_._cached_size_)*/{} + , /*decltype(_impl_.start_)*/0 + , /*decltype(_impl_.end_)*/0} {} +struct DescriptorProto_ReservedRangeDefaultTypeInternal { + PROTOBUF_CONSTEXPR DescriptorProto_ReservedRangeDefaultTypeInternal() + : _instance(::_pbi::ConstantInitialized{}) {} + ~DescriptorProto_ReservedRangeDefaultTypeInternal() {} + union { + DescriptorProto_ReservedRange _instance; + }; +}; +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 DescriptorProto_ReservedRangeDefaultTypeInternal _DescriptorProto_ReservedRange_default_instance_; +PROTOBUF_CONSTEXPR DescriptorProto::DescriptorProto( + ::_pbi::ConstantInitialized): _impl_{ + /*decltype(_impl_._has_bits_)*/{} + , /*decltype(_impl_._cached_size_)*/{} + , /*decltype(_impl_.field_)*/{} + , /*decltype(_impl_.nested_type_)*/{} + , /*decltype(_impl_.enum_type_)*/{} + , /*decltype(_impl_.extension_range_)*/{} + , /*decltype(_impl_.extension_)*/{} + , /*decltype(_impl_.oneof_decl_)*/{} + , /*decltype(_impl_.reserved_range_)*/{} + , /*decltype(_impl_.reserved_name_)*/{} + , /*decltype(_impl_.name_)*/{&::_pbi::fixed_address_empty_string, ::_pbi::ConstantInitialized{}} + , /*decltype(_impl_.options_)*/nullptr} {} +struct DescriptorProtoDefaultTypeInternal { + PROTOBUF_CONSTEXPR DescriptorProtoDefaultTypeInternal() + : _instance(::_pbi::ConstantInitialized{}) {} + ~DescriptorProtoDefaultTypeInternal() {} + union { + DescriptorProto _instance; + }; +}; +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 DescriptorProtoDefaultTypeInternal _DescriptorProto_default_instance_; +PROTOBUF_CONSTEXPR ExtensionRangeOptions::ExtensionRangeOptions( + ::_pbi::ConstantInitialized): _impl_{ + /*decltype(_impl_._extensions_)*/{} + , /*decltype(_impl_.uninterpreted_option_)*/{} + , /*decltype(_impl_._cached_size_)*/{}} {} +struct ExtensionRangeOptionsDefaultTypeInternal { + PROTOBUF_CONSTEXPR ExtensionRangeOptionsDefaultTypeInternal() + : _instance(::_pbi::ConstantInitialized{}) {} + ~ExtensionRangeOptionsDefaultTypeInternal() {} + union { + ExtensionRangeOptions _instance; + }; +}; +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 ExtensionRangeOptionsDefaultTypeInternal _ExtensionRangeOptions_default_instance_; +PROTOBUF_CONSTEXPR FieldDescriptorProto::FieldDescriptorProto( + ::_pbi::ConstantInitialized): _impl_{ + /*decltype(_impl_._has_bits_)*/{} + , /*decltype(_impl_._cached_size_)*/{} + , /*decltype(_impl_.name_)*/{&::_pbi::fixed_address_empty_string, ::_pbi::ConstantInitialized{}} + , /*decltype(_impl_.extendee_)*/{&::_pbi::fixed_address_empty_string, ::_pbi::ConstantInitialized{}} + , /*decltype(_impl_.type_name_)*/{&::_pbi::fixed_address_empty_string, ::_pbi::ConstantInitialized{}} + , /*decltype(_impl_.default_value_)*/{&::_pbi::fixed_address_empty_string, ::_pbi::ConstantInitialized{}} + , /*decltype(_impl_.json_name_)*/{&::_pbi::fixed_address_empty_string, ::_pbi::ConstantInitialized{}} + , /*decltype(_impl_.options_)*/nullptr + , /*decltype(_impl_.number_)*/0 + , /*decltype(_impl_.oneof_index_)*/0 + , /*decltype(_impl_.proto3_optional_)*/false + , /*decltype(_impl_.label_)*/1 + , /*decltype(_impl_.type_)*/1} {} +struct FieldDescriptorProtoDefaultTypeInternal { + PROTOBUF_CONSTEXPR FieldDescriptorProtoDefaultTypeInternal() + : _instance(::_pbi::ConstantInitialized{}) {} + ~FieldDescriptorProtoDefaultTypeInternal() {} + union { + FieldDescriptorProto _instance; + }; +}; +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 FieldDescriptorProtoDefaultTypeInternal _FieldDescriptorProto_default_instance_; +PROTOBUF_CONSTEXPR OneofDescriptorProto::OneofDescriptorProto( + ::_pbi::ConstantInitialized): _impl_{ + /*decltype(_impl_._has_bits_)*/{} + , /*decltype(_impl_._cached_size_)*/{} + , /*decltype(_impl_.name_)*/{&::_pbi::fixed_address_empty_string, ::_pbi::ConstantInitialized{}} + , /*decltype(_impl_.options_)*/nullptr} {} +struct OneofDescriptorProtoDefaultTypeInternal { + PROTOBUF_CONSTEXPR OneofDescriptorProtoDefaultTypeInternal() + : _instance(::_pbi::ConstantInitialized{}) {} + ~OneofDescriptorProtoDefaultTypeInternal() {} + union { + OneofDescriptorProto _instance; + }; +}; +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 OneofDescriptorProtoDefaultTypeInternal _OneofDescriptorProto_default_instance_; +PROTOBUF_CONSTEXPR EnumDescriptorProto_EnumReservedRange::EnumDescriptorProto_EnumReservedRange( + ::_pbi::ConstantInitialized): _impl_{ + /*decltype(_impl_._has_bits_)*/{} + , /*decltype(_impl_._cached_size_)*/{} + , /*decltype(_impl_.start_)*/0 + , /*decltype(_impl_.end_)*/0} {} +struct EnumDescriptorProto_EnumReservedRangeDefaultTypeInternal { + PROTOBUF_CONSTEXPR EnumDescriptorProto_EnumReservedRangeDefaultTypeInternal() + : _instance(::_pbi::ConstantInitialized{}) {} + ~EnumDescriptorProto_EnumReservedRangeDefaultTypeInternal() {} + union { + EnumDescriptorProto_EnumReservedRange _instance; + }; +}; +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 EnumDescriptorProto_EnumReservedRangeDefaultTypeInternal _EnumDescriptorProto_EnumReservedRange_default_instance_; +PROTOBUF_CONSTEXPR EnumDescriptorProto::EnumDescriptorProto( + ::_pbi::ConstantInitialized): _impl_{ + /*decltype(_impl_._has_bits_)*/{} + , /*decltype(_impl_._cached_size_)*/{} + , /*decltype(_impl_.value_)*/{} + , /*decltype(_impl_.reserved_range_)*/{} + , /*decltype(_impl_.reserved_name_)*/{} + , /*decltype(_impl_.name_)*/{&::_pbi::fixed_address_empty_string, ::_pbi::ConstantInitialized{}} + , /*decltype(_impl_.options_)*/nullptr} {} +struct EnumDescriptorProtoDefaultTypeInternal { + PROTOBUF_CONSTEXPR EnumDescriptorProtoDefaultTypeInternal() + : _instance(::_pbi::ConstantInitialized{}) {} + ~EnumDescriptorProtoDefaultTypeInternal() {} + union { + EnumDescriptorProto _instance; + }; +}; +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 EnumDescriptorProtoDefaultTypeInternal _EnumDescriptorProto_default_instance_; +PROTOBUF_CONSTEXPR EnumValueDescriptorProto::EnumValueDescriptorProto( + ::_pbi::ConstantInitialized): _impl_{ + /*decltype(_impl_._has_bits_)*/{} + , /*decltype(_impl_._cached_size_)*/{} + , /*decltype(_impl_.name_)*/{&::_pbi::fixed_address_empty_string, ::_pbi::ConstantInitialized{}} + , /*decltype(_impl_.options_)*/nullptr + , /*decltype(_impl_.number_)*/0} {} +struct EnumValueDescriptorProtoDefaultTypeInternal { + PROTOBUF_CONSTEXPR EnumValueDescriptorProtoDefaultTypeInternal() + : _instance(::_pbi::ConstantInitialized{}) {} + ~EnumValueDescriptorProtoDefaultTypeInternal() {} + union { + EnumValueDescriptorProto _instance; + }; +}; +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 EnumValueDescriptorProtoDefaultTypeInternal _EnumValueDescriptorProto_default_instance_; +PROTOBUF_CONSTEXPR ServiceDescriptorProto::ServiceDescriptorProto( + ::_pbi::ConstantInitialized): _impl_{ + /*decltype(_impl_._has_bits_)*/{} + , /*decltype(_impl_._cached_size_)*/{} + , /*decltype(_impl_.method_)*/{} + , /*decltype(_impl_.name_)*/{&::_pbi::fixed_address_empty_string, ::_pbi::ConstantInitialized{}} + , /*decltype(_impl_.options_)*/nullptr} {} +struct ServiceDescriptorProtoDefaultTypeInternal { + PROTOBUF_CONSTEXPR ServiceDescriptorProtoDefaultTypeInternal() + : _instance(::_pbi::ConstantInitialized{}) {} + ~ServiceDescriptorProtoDefaultTypeInternal() {} + union { + ServiceDescriptorProto _instance; + }; +}; +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 ServiceDescriptorProtoDefaultTypeInternal _ServiceDescriptorProto_default_instance_; +PROTOBUF_CONSTEXPR MethodDescriptorProto::MethodDescriptorProto( + ::_pbi::ConstantInitialized): _impl_{ + /*decltype(_impl_._has_bits_)*/{} + , /*decltype(_impl_._cached_size_)*/{} + , /*decltype(_impl_.name_)*/{&::_pbi::fixed_address_empty_string, ::_pbi::ConstantInitialized{}} + , /*decltype(_impl_.input_type_)*/{&::_pbi::fixed_address_empty_string, ::_pbi::ConstantInitialized{}} + , /*decltype(_impl_.output_type_)*/{&::_pbi::fixed_address_empty_string, ::_pbi::ConstantInitialized{}} + , /*decltype(_impl_.options_)*/nullptr + , /*decltype(_impl_.client_streaming_)*/false + , /*decltype(_impl_.server_streaming_)*/false} {} +struct MethodDescriptorProtoDefaultTypeInternal { + PROTOBUF_CONSTEXPR MethodDescriptorProtoDefaultTypeInternal() + : _instance(::_pbi::ConstantInitialized{}) {} + ~MethodDescriptorProtoDefaultTypeInternal() {} + union { + MethodDescriptorProto _instance; + }; +}; +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 MethodDescriptorProtoDefaultTypeInternal _MethodDescriptorProto_default_instance_; +PROTOBUF_CONSTEXPR FileOptions::FileOptions( + ::_pbi::ConstantInitialized): _impl_{ + /*decltype(_impl_._extensions_)*/{} + , /*decltype(_impl_._has_bits_)*/{} + , /*decltype(_impl_._cached_size_)*/{} + , /*decltype(_impl_.uninterpreted_option_)*/{} + , /*decltype(_impl_.java_package_)*/{&::_pbi::fixed_address_empty_string, ::_pbi::ConstantInitialized{}} + , /*decltype(_impl_.java_outer_classname_)*/{&::_pbi::fixed_address_empty_string, ::_pbi::ConstantInitialized{}} + , /*decltype(_impl_.go_package_)*/{&::_pbi::fixed_address_empty_string, ::_pbi::ConstantInitialized{}} + , /*decltype(_impl_.objc_class_prefix_)*/{&::_pbi::fixed_address_empty_string, ::_pbi::ConstantInitialized{}} + , /*decltype(_impl_.csharp_namespace_)*/{&::_pbi::fixed_address_empty_string, ::_pbi::ConstantInitialized{}} + , /*decltype(_impl_.swift_prefix_)*/{&::_pbi::fixed_address_empty_string, ::_pbi::ConstantInitialized{}} + , /*decltype(_impl_.php_class_prefix_)*/{&::_pbi::fixed_address_empty_string, ::_pbi::ConstantInitialized{}} + , /*decltype(_impl_.php_namespace_)*/{&::_pbi::fixed_address_empty_string, ::_pbi::ConstantInitialized{}} + , /*decltype(_impl_.php_metadata_namespace_)*/{&::_pbi::fixed_address_empty_string, ::_pbi::ConstantInitialized{}} + , /*decltype(_impl_.ruby_package_)*/{&::_pbi::fixed_address_empty_string, ::_pbi::ConstantInitialized{}} + , /*decltype(_impl_.java_multiple_files_)*/false + , /*decltype(_impl_.java_generate_equals_and_hash_)*/false + , /*decltype(_impl_.java_string_check_utf8_)*/false + , /*decltype(_impl_.cc_generic_services_)*/false + , /*decltype(_impl_.java_generic_services_)*/false + , /*decltype(_impl_.py_generic_services_)*/false + , /*decltype(_impl_.php_generic_services_)*/false + , /*decltype(_impl_.deprecated_)*/false + , /*decltype(_impl_.optimize_for_)*/1 + , /*decltype(_impl_.cc_enable_arenas_)*/true} {} +struct FileOptionsDefaultTypeInternal { + PROTOBUF_CONSTEXPR FileOptionsDefaultTypeInternal() + : _instance(::_pbi::ConstantInitialized{}) {} + ~FileOptionsDefaultTypeInternal() {} + union { + FileOptions _instance; + }; +}; +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 FileOptionsDefaultTypeInternal _FileOptions_default_instance_; +PROTOBUF_CONSTEXPR MessageOptions::MessageOptions( + ::_pbi::ConstantInitialized): _impl_{ + /*decltype(_impl_._extensions_)*/{} + , /*decltype(_impl_._has_bits_)*/{} + , /*decltype(_impl_._cached_size_)*/{} + , /*decltype(_impl_.uninterpreted_option_)*/{} + , /*decltype(_impl_.message_set_wire_format_)*/false + , /*decltype(_impl_.no_standard_descriptor_accessor_)*/false + , /*decltype(_impl_.deprecated_)*/false + , /*decltype(_impl_.map_entry_)*/false} {} +struct MessageOptionsDefaultTypeInternal { + PROTOBUF_CONSTEXPR MessageOptionsDefaultTypeInternal() + : _instance(::_pbi::ConstantInitialized{}) {} + ~MessageOptionsDefaultTypeInternal() {} + union { + MessageOptions _instance; + }; +}; +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 MessageOptionsDefaultTypeInternal _MessageOptions_default_instance_; +PROTOBUF_CONSTEXPR FieldOptions::FieldOptions( + ::_pbi::ConstantInitialized): _impl_{ + /*decltype(_impl_._extensions_)*/{} + , /*decltype(_impl_._has_bits_)*/{} + , /*decltype(_impl_._cached_size_)*/{} + , /*decltype(_impl_.uninterpreted_option_)*/{} + , /*decltype(_impl_.ctype_)*/0 + , /*decltype(_impl_.jstype_)*/0 + , /*decltype(_impl_.packed_)*/false + , /*decltype(_impl_.lazy_)*/false + , /*decltype(_impl_.unverified_lazy_)*/false + , /*decltype(_impl_.deprecated_)*/false + , /*decltype(_impl_.weak_)*/false} {} +struct FieldOptionsDefaultTypeInternal { + PROTOBUF_CONSTEXPR FieldOptionsDefaultTypeInternal() + : _instance(::_pbi::ConstantInitialized{}) {} + ~FieldOptionsDefaultTypeInternal() {} + union { + FieldOptions _instance; + }; +}; +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 FieldOptionsDefaultTypeInternal _FieldOptions_default_instance_; +PROTOBUF_CONSTEXPR OneofOptions::OneofOptions( + ::_pbi::ConstantInitialized): _impl_{ + /*decltype(_impl_._extensions_)*/{} + , /*decltype(_impl_.uninterpreted_option_)*/{} + , /*decltype(_impl_._cached_size_)*/{}} {} +struct OneofOptionsDefaultTypeInternal { + PROTOBUF_CONSTEXPR OneofOptionsDefaultTypeInternal() + : _instance(::_pbi::ConstantInitialized{}) {} + ~OneofOptionsDefaultTypeInternal() {} + union { + OneofOptions _instance; + }; +}; +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 OneofOptionsDefaultTypeInternal _OneofOptions_default_instance_; +PROTOBUF_CONSTEXPR EnumOptions::EnumOptions( + ::_pbi::ConstantInitialized): _impl_{ + /*decltype(_impl_._extensions_)*/{} + , /*decltype(_impl_._has_bits_)*/{} + , /*decltype(_impl_._cached_size_)*/{} + , /*decltype(_impl_.uninterpreted_option_)*/{} + , /*decltype(_impl_.allow_alias_)*/false + , /*decltype(_impl_.deprecated_)*/false} {} +struct EnumOptionsDefaultTypeInternal { + PROTOBUF_CONSTEXPR EnumOptionsDefaultTypeInternal() + : _instance(::_pbi::ConstantInitialized{}) {} + ~EnumOptionsDefaultTypeInternal() {} + union { + EnumOptions _instance; + }; +}; +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 EnumOptionsDefaultTypeInternal _EnumOptions_default_instance_; +PROTOBUF_CONSTEXPR EnumValueOptions::EnumValueOptions( + ::_pbi::ConstantInitialized): _impl_{ + /*decltype(_impl_._extensions_)*/{} + , /*decltype(_impl_._has_bits_)*/{} + , /*decltype(_impl_._cached_size_)*/{} + , /*decltype(_impl_.uninterpreted_option_)*/{} + , /*decltype(_impl_.deprecated_)*/false} {} +struct EnumValueOptionsDefaultTypeInternal { + PROTOBUF_CONSTEXPR EnumValueOptionsDefaultTypeInternal() + : _instance(::_pbi::ConstantInitialized{}) {} + ~EnumValueOptionsDefaultTypeInternal() {} + union { + EnumValueOptions _instance; + }; +}; +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 EnumValueOptionsDefaultTypeInternal _EnumValueOptions_default_instance_; +PROTOBUF_CONSTEXPR ServiceOptions::ServiceOptions( + ::_pbi::ConstantInitialized): _impl_{ + /*decltype(_impl_._extensions_)*/{} + , /*decltype(_impl_._has_bits_)*/{} + , /*decltype(_impl_._cached_size_)*/{} + , /*decltype(_impl_.uninterpreted_option_)*/{} + , /*decltype(_impl_.deprecated_)*/false} {} +struct ServiceOptionsDefaultTypeInternal { + PROTOBUF_CONSTEXPR ServiceOptionsDefaultTypeInternal() + : _instance(::_pbi::ConstantInitialized{}) {} + ~ServiceOptionsDefaultTypeInternal() {} + union { + ServiceOptions _instance; + }; +}; +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 ServiceOptionsDefaultTypeInternal _ServiceOptions_default_instance_; +PROTOBUF_CONSTEXPR MethodOptions::MethodOptions( + ::_pbi::ConstantInitialized): _impl_{ + /*decltype(_impl_._extensions_)*/{} + , /*decltype(_impl_._has_bits_)*/{} + , /*decltype(_impl_._cached_size_)*/{} + , /*decltype(_impl_.uninterpreted_option_)*/{} + , /*decltype(_impl_.deprecated_)*/false + , /*decltype(_impl_.idempotency_level_)*/0} {} +struct MethodOptionsDefaultTypeInternal { + PROTOBUF_CONSTEXPR MethodOptionsDefaultTypeInternal() + : _instance(::_pbi::ConstantInitialized{}) {} + ~MethodOptionsDefaultTypeInternal() {} + union { + MethodOptions _instance; + }; +}; +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 MethodOptionsDefaultTypeInternal _MethodOptions_default_instance_; +PROTOBUF_CONSTEXPR UninterpretedOption_NamePart::UninterpretedOption_NamePart( + ::_pbi::ConstantInitialized): _impl_{ + /*decltype(_impl_._has_bits_)*/{} + , /*decltype(_impl_._cached_size_)*/{} + , /*decltype(_impl_.name_part_)*/{&::_pbi::fixed_address_empty_string, ::_pbi::ConstantInitialized{}} + , /*decltype(_impl_.is_extension_)*/false} {} +struct UninterpretedOption_NamePartDefaultTypeInternal { + PROTOBUF_CONSTEXPR UninterpretedOption_NamePartDefaultTypeInternal() + : _instance(::_pbi::ConstantInitialized{}) {} + ~UninterpretedOption_NamePartDefaultTypeInternal() {} + union { + UninterpretedOption_NamePart _instance; + }; +}; +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 UninterpretedOption_NamePartDefaultTypeInternal _UninterpretedOption_NamePart_default_instance_; +PROTOBUF_CONSTEXPR UninterpretedOption::UninterpretedOption( + ::_pbi::ConstantInitialized): _impl_{ + /*decltype(_impl_._has_bits_)*/{} + , /*decltype(_impl_._cached_size_)*/{} + , /*decltype(_impl_.name_)*/{} + , /*decltype(_impl_.identifier_value_)*/{&::_pbi::fixed_address_empty_string, ::_pbi::ConstantInitialized{}} + , /*decltype(_impl_.string_value_)*/{&::_pbi::fixed_address_empty_string, ::_pbi::ConstantInitialized{}} + , /*decltype(_impl_.aggregate_value_)*/{&::_pbi::fixed_address_empty_string, ::_pbi::ConstantInitialized{}} + , /*decltype(_impl_.positive_int_value_)*/uint64_t{0u} + , /*decltype(_impl_.negative_int_value_)*/int64_t{0} + , /*decltype(_impl_.double_value_)*/0} {} +struct UninterpretedOptionDefaultTypeInternal { + PROTOBUF_CONSTEXPR UninterpretedOptionDefaultTypeInternal() + : _instance(::_pbi::ConstantInitialized{}) {} + ~UninterpretedOptionDefaultTypeInternal() {} + union { + UninterpretedOption _instance; + }; +}; +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 UninterpretedOptionDefaultTypeInternal _UninterpretedOption_default_instance_; +PROTOBUF_CONSTEXPR SourceCodeInfo_Location::SourceCodeInfo_Location( + ::_pbi::ConstantInitialized): _impl_{ + /*decltype(_impl_._has_bits_)*/{} + , /*decltype(_impl_._cached_size_)*/{} + , /*decltype(_impl_.path_)*/{} + , /*decltype(_impl_._path_cached_byte_size_)*/{0} + , /*decltype(_impl_.span_)*/{} + , /*decltype(_impl_._span_cached_byte_size_)*/{0} + , /*decltype(_impl_.leading_detached_comments_)*/{} + , /*decltype(_impl_.leading_comments_)*/{&::_pbi::fixed_address_empty_string, ::_pbi::ConstantInitialized{}} + , /*decltype(_impl_.trailing_comments_)*/{&::_pbi::fixed_address_empty_string, ::_pbi::ConstantInitialized{}}} {} +struct SourceCodeInfo_LocationDefaultTypeInternal { + PROTOBUF_CONSTEXPR SourceCodeInfo_LocationDefaultTypeInternal() + : _instance(::_pbi::ConstantInitialized{}) {} + ~SourceCodeInfo_LocationDefaultTypeInternal() {} + union { + SourceCodeInfo_Location _instance; + }; +}; +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 SourceCodeInfo_LocationDefaultTypeInternal _SourceCodeInfo_Location_default_instance_; +PROTOBUF_CONSTEXPR SourceCodeInfo::SourceCodeInfo( + ::_pbi::ConstantInitialized): _impl_{ + /*decltype(_impl_.location_)*/{} + , /*decltype(_impl_._cached_size_)*/{}} {} +struct SourceCodeInfoDefaultTypeInternal { + PROTOBUF_CONSTEXPR SourceCodeInfoDefaultTypeInternal() + : _instance(::_pbi::ConstantInitialized{}) {} + ~SourceCodeInfoDefaultTypeInternal() {} + union { + SourceCodeInfo _instance; + }; +}; +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 SourceCodeInfoDefaultTypeInternal _SourceCodeInfo_default_instance_; +PROTOBUF_CONSTEXPR GeneratedCodeInfo_Annotation::GeneratedCodeInfo_Annotation( + ::_pbi::ConstantInitialized): _impl_{ + /*decltype(_impl_._has_bits_)*/{} + , /*decltype(_impl_._cached_size_)*/{} + , /*decltype(_impl_.path_)*/{} + , /*decltype(_impl_._path_cached_byte_size_)*/{0} + , /*decltype(_impl_.source_file_)*/{&::_pbi::fixed_address_empty_string, ::_pbi::ConstantInitialized{}} + , /*decltype(_impl_.begin_)*/0 + , /*decltype(_impl_.end_)*/0} {} +struct GeneratedCodeInfo_AnnotationDefaultTypeInternal { + PROTOBUF_CONSTEXPR GeneratedCodeInfo_AnnotationDefaultTypeInternal() + : _instance(::_pbi::ConstantInitialized{}) {} + ~GeneratedCodeInfo_AnnotationDefaultTypeInternal() {} + union { + GeneratedCodeInfo_Annotation _instance; + }; +}; +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 GeneratedCodeInfo_AnnotationDefaultTypeInternal _GeneratedCodeInfo_Annotation_default_instance_; +PROTOBUF_CONSTEXPR GeneratedCodeInfo::GeneratedCodeInfo( + ::_pbi::ConstantInitialized): _impl_{ + /*decltype(_impl_.annotation_)*/{} + , /*decltype(_impl_._cached_size_)*/{}} {} +struct GeneratedCodeInfoDefaultTypeInternal { + PROTOBUF_CONSTEXPR GeneratedCodeInfoDefaultTypeInternal() + : _instance(::_pbi::ConstantInitialized{}) {} + ~GeneratedCodeInfoDefaultTypeInternal() {} + union { + GeneratedCodeInfo _instance; + }; +}; +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 GeneratedCodeInfoDefaultTypeInternal _GeneratedCodeInfo_default_instance_; +PROTOBUF_NAMESPACE_CLOSE +static ::_pb::Metadata file_level_metadata_google_2fprotobuf_2fdescriptor_2eproto[27]; +static const ::_pb::EnumDescriptor* file_level_enum_descriptors_google_2fprotobuf_2fdescriptor_2eproto[6]; +static constexpr ::_pb::ServiceDescriptor const** file_level_service_descriptors_google_2fprotobuf_2fdescriptor_2eproto = nullptr; + +const uint32_t TableStruct_google_2fprotobuf_2fdescriptor_2eproto::offsets[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = { + ~0u, // no _has_bits_ + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::FileDescriptorSet, _internal_metadata_), + ~0u, // no _extensions_ + ~0u, // no _oneof_case_ + ~0u, // no _weak_field_map_ + ~0u, // no _inlined_string_donated_ + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::FileDescriptorSet, _impl_.file_), + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::FileDescriptorProto, _impl_._has_bits_), + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::FileDescriptorProto, _internal_metadata_), + ~0u, // no _extensions_ + ~0u, // no _oneof_case_ + ~0u, // no _weak_field_map_ + ~0u, // no _inlined_string_donated_ + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::FileDescriptorProto, _impl_.name_), + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::FileDescriptorProto, _impl_.package_), + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::FileDescriptorProto, _impl_.dependency_), + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::FileDescriptorProto, _impl_.public_dependency_), + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::FileDescriptorProto, _impl_.weak_dependency_), + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::FileDescriptorProto, _impl_.message_type_), + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::FileDescriptorProto, _impl_.enum_type_), + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::FileDescriptorProto, _impl_.service_), + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::FileDescriptorProto, _impl_.extension_), + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::FileDescriptorProto, _impl_.options_), + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::FileDescriptorProto, _impl_.source_code_info_), + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::FileDescriptorProto, _impl_.syntax_), + 0, + 1, + ~0u, + ~0u, + ~0u, + ~0u, + ~0u, + ~0u, + ~0u, + 3, + 4, + 2, + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::DescriptorProto_ExtensionRange, _impl_._has_bits_), + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::DescriptorProto_ExtensionRange, _internal_metadata_), + ~0u, // no _extensions_ + ~0u, // no _oneof_case_ + ~0u, // no _weak_field_map_ + ~0u, // no _inlined_string_donated_ + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::DescriptorProto_ExtensionRange, _impl_.start_), + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::DescriptorProto_ExtensionRange, _impl_.end_), + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::DescriptorProto_ExtensionRange, _impl_.options_), + 1, + 2, + 0, + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::DescriptorProto_ReservedRange, _impl_._has_bits_), + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::DescriptorProto_ReservedRange, _internal_metadata_), + ~0u, // no _extensions_ + ~0u, // no _oneof_case_ + ~0u, // no _weak_field_map_ + ~0u, // no _inlined_string_donated_ + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::DescriptorProto_ReservedRange, _impl_.start_), + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::DescriptorProto_ReservedRange, _impl_.end_), + 0, + 1, + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::DescriptorProto, _impl_._has_bits_), + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::DescriptorProto, _internal_metadata_), + ~0u, // no _extensions_ + ~0u, // no _oneof_case_ + ~0u, // no _weak_field_map_ + ~0u, // no _inlined_string_donated_ + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::DescriptorProto, _impl_.name_), + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::DescriptorProto, _impl_.field_), + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::DescriptorProto, _impl_.extension_), + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::DescriptorProto, _impl_.nested_type_), + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::DescriptorProto, _impl_.enum_type_), + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::DescriptorProto, _impl_.extension_range_), + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::DescriptorProto, _impl_.oneof_decl_), + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::DescriptorProto, _impl_.options_), + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::DescriptorProto, _impl_.reserved_range_), + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::DescriptorProto, _impl_.reserved_name_), + 0, + ~0u, + ~0u, + ~0u, + ~0u, + ~0u, + ~0u, + 1, + ~0u, + ~0u, + ~0u, // no _has_bits_ + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::ExtensionRangeOptions, _internal_metadata_), + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::ExtensionRangeOptions, _impl_._extensions_), + ~0u, // no _oneof_case_ + ~0u, // no _weak_field_map_ + ~0u, // no _inlined_string_donated_ + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::ExtensionRangeOptions, _impl_.uninterpreted_option_), + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::FieldDescriptorProto, _impl_._has_bits_), + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::FieldDescriptorProto, _internal_metadata_), + ~0u, // no _extensions_ + ~0u, // no _oneof_case_ + ~0u, // no _weak_field_map_ + ~0u, // no _inlined_string_donated_ + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::FieldDescriptorProto, _impl_.name_), + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::FieldDescriptorProto, _impl_.number_), + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::FieldDescriptorProto, _impl_.label_), + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::FieldDescriptorProto, _impl_.type_), + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::FieldDescriptorProto, _impl_.type_name_), + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::FieldDescriptorProto, _impl_.extendee_), + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::FieldDescriptorProto, _impl_.default_value_), + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::FieldDescriptorProto, _impl_.oneof_index_), + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::FieldDescriptorProto, _impl_.json_name_), + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::FieldDescriptorProto, _impl_.options_), + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::FieldDescriptorProto, _impl_.proto3_optional_), + 0, + 6, + 9, + 10, + 2, + 1, + 3, + 7, + 4, + 5, + 8, + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::OneofDescriptorProto, _impl_._has_bits_), + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::OneofDescriptorProto, _internal_metadata_), + ~0u, // no _extensions_ + ~0u, // no _oneof_case_ + ~0u, // no _weak_field_map_ + ~0u, // no _inlined_string_donated_ + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::OneofDescriptorProto, _impl_.name_), + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::OneofDescriptorProto, _impl_.options_), + 0, + 1, + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::EnumDescriptorProto_EnumReservedRange, _impl_._has_bits_), + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::EnumDescriptorProto_EnumReservedRange, _internal_metadata_), + ~0u, // no _extensions_ + ~0u, // no _oneof_case_ + ~0u, // no _weak_field_map_ + ~0u, // no _inlined_string_donated_ + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::EnumDescriptorProto_EnumReservedRange, _impl_.start_), + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::EnumDescriptorProto_EnumReservedRange, _impl_.end_), + 0, + 1, + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::EnumDescriptorProto, _impl_._has_bits_), + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::EnumDescriptorProto, _internal_metadata_), + ~0u, // no _extensions_ + ~0u, // no _oneof_case_ + ~0u, // no _weak_field_map_ + ~0u, // no _inlined_string_donated_ + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::EnumDescriptorProto, _impl_.name_), + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::EnumDescriptorProto, _impl_.value_), + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::EnumDescriptorProto, _impl_.options_), + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::EnumDescriptorProto, _impl_.reserved_range_), + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::EnumDescriptorProto, _impl_.reserved_name_), + 0, + ~0u, + 1, + ~0u, + ~0u, + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::EnumValueDescriptorProto, _impl_._has_bits_), + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::EnumValueDescriptorProto, _internal_metadata_), + ~0u, // no _extensions_ + ~0u, // no _oneof_case_ + ~0u, // no _weak_field_map_ + ~0u, // no _inlined_string_donated_ + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::EnumValueDescriptorProto, _impl_.name_), + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::EnumValueDescriptorProto, _impl_.number_), + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::EnumValueDescriptorProto, _impl_.options_), + 0, + 2, + 1, + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::ServiceDescriptorProto, _impl_._has_bits_), + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::ServiceDescriptorProto, _internal_metadata_), + ~0u, // no _extensions_ + ~0u, // no _oneof_case_ + ~0u, // no _weak_field_map_ + ~0u, // no _inlined_string_donated_ + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::ServiceDescriptorProto, _impl_.name_), + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::ServiceDescriptorProto, _impl_.method_), + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::ServiceDescriptorProto, _impl_.options_), + 0, + ~0u, + 1, + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::MethodDescriptorProto, _impl_._has_bits_), + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::MethodDescriptorProto, _internal_metadata_), + ~0u, // no _extensions_ + ~0u, // no _oneof_case_ + ~0u, // no _weak_field_map_ + ~0u, // no _inlined_string_donated_ + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::MethodDescriptorProto, _impl_.name_), + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::MethodDescriptorProto, _impl_.input_type_), + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::MethodDescriptorProto, _impl_.output_type_), + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::MethodDescriptorProto, _impl_.options_), + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::MethodDescriptorProto, _impl_.client_streaming_), + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::MethodDescriptorProto, _impl_.server_streaming_), + 0, + 1, + 2, + 3, + 4, + 5, + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::FileOptions, _impl_._has_bits_), + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::FileOptions, _internal_metadata_), + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::FileOptions, _impl_._extensions_), + ~0u, // no _oneof_case_ + ~0u, // no _weak_field_map_ + ~0u, // no _inlined_string_donated_ + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::FileOptions, _impl_.java_package_), + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::FileOptions, _impl_.java_outer_classname_), + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::FileOptions, _impl_.java_multiple_files_), + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::FileOptions, _impl_.java_generate_equals_and_hash_), + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::FileOptions, _impl_.java_string_check_utf8_), + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::FileOptions, _impl_.optimize_for_), + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::FileOptions, _impl_.go_package_), + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::FileOptions, _impl_.cc_generic_services_), + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::FileOptions, _impl_.java_generic_services_), + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::FileOptions, _impl_.py_generic_services_), + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::FileOptions, _impl_.php_generic_services_), + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::FileOptions, _impl_.deprecated_), + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::FileOptions, _impl_.cc_enable_arenas_), + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::FileOptions, _impl_.objc_class_prefix_), + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::FileOptions, _impl_.csharp_namespace_), + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::FileOptions, _impl_.swift_prefix_), + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::FileOptions, _impl_.php_class_prefix_), + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::FileOptions, _impl_.php_namespace_), + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::FileOptions, _impl_.php_metadata_namespace_), + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::FileOptions, _impl_.ruby_package_), + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::FileOptions, _impl_.uninterpreted_option_), + 0, + 1, + 10, + 11, + 12, + 18, + 2, + 13, + 14, + 15, + 16, + 17, + 19, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + ~0u, + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::MessageOptions, _impl_._has_bits_), + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::MessageOptions, _internal_metadata_), + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::MessageOptions, _impl_._extensions_), + ~0u, // no _oneof_case_ + ~0u, // no _weak_field_map_ + ~0u, // no _inlined_string_donated_ + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::MessageOptions, _impl_.message_set_wire_format_), + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::MessageOptions, _impl_.no_standard_descriptor_accessor_), + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::MessageOptions, _impl_.deprecated_), + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::MessageOptions, _impl_.map_entry_), + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::MessageOptions, _impl_.uninterpreted_option_), + 0, + 1, + 2, + 3, + ~0u, + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::FieldOptions, _impl_._has_bits_), + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::FieldOptions, _internal_metadata_), + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::FieldOptions, _impl_._extensions_), + ~0u, // no _oneof_case_ + ~0u, // no _weak_field_map_ + ~0u, // no _inlined_string_donated_ + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::FieldOptions, _impl_.ctype_), + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::FieldOptions, _impl_.packed_), + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::FieldOptions, _impl_.jstype_), + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::FieldOptions, _impl_.lazy_), + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::FieldOptions, _impl_.unverified_lazy_), + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::FieldOptions, _impl_.deprecated_), + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::FieldOptions, _impl_.weak_), + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::FieldOptions, _impl_.uninterpreted_option_), + 0, + 2, + 1, + 3, + 4, + 5, + 6, + ~0u, + ~0u, // no _has_bits_ + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::OneofOptions, _internal_metadata_), + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::OneofOptions, _impl_._extensions_), + ~0u, // no _oneof_case_ + ~0u, // no _weak_field_map_ + ~0u, // no _inlined_string_donated_ + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::OneofOptions, _impl_.uninterpreted_option_), + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::EnumOptions, _impl_._has_bits_), + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::EnumOptions, _internal_metadata_), + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::EnumOptions, _impl_._extensions_), + ~0u, // no _oneof_case_ + ~0u, // no _weak_field_map_ + ~0u, // no _inlined_string_donated_ + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::EnumOptions, _impl_.allow_alias_), + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::EnumOptions, _impl_.deprecated_), + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::EnumOptions, _impl_.uninterpreted_option_), + 0, + 1, + ~0u, + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::EnumValueOptions, _impl_._has_bits_), + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::EnumValueOptions, _internal_metadata_), + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::EnumValueOptions, _impl_._extensions_), + ~0u, // no _oneof_case_ + ~0u, // no _weak_field_map_ + ~0u, // no _inlined_string_donated_ + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::EnumValueOptions, _impl_.deprecated_), + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::EnumValueOptions, _impl_.uninterpreted_option_), + 0, + ~0u, + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::ServiceOptions, _impl_._has_bits_), + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::ServiceOptions, _internal_metadata_), + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::ServiceOptions, _impl_._extensions_), + ~0u, // no _oneof_case_ + ~0u, // no _weak_field_map_ + ~0u, // no _inlined_string_donated_ + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::ServiceOptions, _impl_.deprecated_), + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::ServiceOptions, _impl_.uninterpreted_option_), + 0, + ~0u, + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::MethodOptions, _impl_._has_bits_), + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::MethodOptions, _internal_metadata_), + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::MethodOptions, _impl_._extensions_), + ~0u, // no _oneof_case_ + ~0u, // no _weak_field_map_ + ~0u, // no _inlined_string_donated_ + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::MethodOptions, _impl_.deprecated_), + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::MethodOptions, _impl_.idempotency_level_), + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::MethodOptions, _impl_.uninterpreted_option_), + 0, + 1, + ~0u, + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::UninterpretedOption_NamePart, _impl_._has_bits_), + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::UninterpretedOption_NamePart, _internal_metadata_), + ~0u, // no _extensions_ + ~0u, // no _oneof_case_ + ~0u, // no _weak_field_map_ + ~0u, // no _inlined_string_donated_ + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::UninterpretedOption_NamePart, _impl_.name_part_), + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::UninterpretedOption_NamePart, _impl_.is_extension_), + 0, + 1, + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::UninterpretedOption, _impl_._has_bits_), + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::UninterpretedOption, _internal_metadata_), + ~0u, // no _extensions_ + ~0u, // no _oneof_case_ + ~0u, // no _weak_field_map_ + ~0u, // no _inlined_string_donated_ + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::UninterpretedOption, _impl_.name_), + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::UninterpretedOption, _impl_.identifier_value_), + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::UninterpretedOption, _impl_.positive_int_value_), + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::UninterpretedOption, _impl_.negative_int_value_), + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::UninterpretedOption, _impl_.double_value_), + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::UninterpretedOption, _impl_.string_value_), + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::UninterpretedOption, _impl_.aggregate_value_), + ~0u, + 0, + 3, + 4, + 5, + 1, + 2, + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::SourceCodeInfo_Location, _impl_._has_bits_), + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::SourceCodeInfo_Location, _internal_metadata_), + ~0u, // no _extensions_ + ~0u, // no _oneof_case_ + ~0u, // no _weak_field_map_ + ~0u, // no _inlined_string_donated_ + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::SourceCodeInfo_Location, _impl_.path_), + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::SourceCodeInfo_Location, _impl_.span_), + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::SourceCodeInfo_Location, _impl_.leading_comments_), + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::SourceCodeInfo_Location, _impl_.trailing_comments_), + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::SourceCodeInfo_Location, _impl_.leading_detached_comments_), + ~0u, + ~0u, + 0, + 1, + ~0u, + ~0u, // no _has_bits_ + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::SourceCodeInfo, _internal_metadata_), + ~0u, // no _extensions_ + ~0u, // no _oneof_case_ + ~0u, // no _weak_field_map_ + ~0u, // no _inlined_string_donated_ + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::SourceCodeInfo, _impl_.location_), + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo_Annotation, _impl_._has_bits_), + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo_Annotation, _internal_metadata_), + ~0u, // no _extensions_ + ~0u, // no _oneof_case_ + ~0u, // no _weak_field_map_ + ~0u, // no _inlined_string_donated_ + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo_Annotation, _impl_.path_), + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo_Annotation, _impl_.source_file_), + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo_Annotation, _impl_.begin_), + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo_Annotation, _impl_.end_), + ~0u, + 0, + 1, + 2, + ~0u, // no _has_bits_ + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo, _internal_metadata_), + ~0u, // no _extensions_ + ~0u, // no _oneof_case_ + ~0u, // no _weak_field_map_ + ~0u, // no _inlined_string_donated_ + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo, _impl_.annotation_), +}; +static const ::_pbi::MigrationSchema schemas[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = { + { 0, -1, -1, sizeof(::PROTOBUF_NAMESPACE_ID::FileDescriptorSet)}, + { 7, 25, -1, sizeof(::PROTOBUF_NAMESPACE_ID::FileDescriptorProto)}, + { 37, 46, -1, sizeof(::PROTOBUF_NAMESPACE_ID::DescriptorProto_ExtensionRange)}, + { 49, 57, -1, sizeof(::PROTOBUF_NAMESPACE_ID::DescriptorProto_ReservedRange)}, + { 59, 75, -1, sizeof(::PROTOBUF_NAMESPACE_ID::DescriptorProto)}, + { 85, -1, -1, sizeof(::PROTOBUF_NAMESPACE_ID::ExtensionRangeOptions)}, + { 92, 109, -1, sizeof(::PROTOBUF_NAMESPACE_ID::FieldDescriptorProto)}, + { 120, 128, -1, sizeof(::PROTOBUF_NAMESPACE_ID::OneofDescriptorProto)}, + { 130, 138, -1, sizeof(::PROTOBUF_NAMESPACE_ID::EnumDescriptorProto_EnumReservedRange)}, + { 140, 151, -1, sizeof(::PROTOBUF_NAMESPACE_ID::EnumDescriptorProto)}, + { 156, 165, -1, sizeof(::PROTOBUF_NAMESPACE_ID::EnumValueDescriptorProto)}, + { 168, 177, -1, sizeof(::PROTOBUF_NAMESPACE_ID::ServiceDescriptorProto)}, + { 180, 192, -1, sizeof(::PROTOBUF_NAMESPACE_ID::MethodDescriptorProto)}, + { 198, 225, -1, sizeof(::PROTOBUF_NAMESPACE_ID::FileOptions)}, + { 246, 257, -1, sizeof(::PROTOBUF_NAMESPACE_ID::MessageOptions)}, + { 262, 276, -1, sizeof(::PROTOBUF_NAMESPACE_ID::FieldOptions)}, + { 284, -1, -1, sizeof(::PROTOBUF_NAMESPACE_ID::OneofOptions)}, + { 291, 300, -1, sizeof(::PROTOBUF_NAMESPACE_ID::EnumOptions)}, + { 303, 311, -1, sizeof(::PROTOBUF_NAMESPACE_ID::EnumValueOptions)}, + { 313, 321, -1, sizeof(::PROTOBUF_NAMESPACE_ID::ServiceOptions)}, + { 323, 332, -1, sizeof(::PROTOBUF_NAMESPACE_ID::MethodOptions)}, + { 335, 343, -1, sizeof(::PROTOBUF_NAMESPACE_ID::UninterpretedOption_NamePart)}, + { 345, 358, -1, sizeof(::PROTOBUF_NAMESPACE_ID::UninterpretedOption)}, + { 365, 376, -1, sizeof(::PROTOBUF_NAMESPACE_ID::SourceCodeInfo_Location)}, + { 381, -1, -1, sizeof(::PROTOBUF_NAMESPACE_ID::SourceCodeInfo)}, + { 388, 398, -1, sizeof(::PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo_Annotation)}, + { 402, -1, -1, sizeof(::PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo)}, +}; + +static const ::_pb::Message* const file_default_instances[] = { + &::PROTOBUF_NAMESPACE_ID::_FileDescriptorSet_default_instance_._instance, + &::PROTOBUF_NAMESPACE_ID::_FileDescriptorProto_default_instance_._instance, + &::PROTOBUF_NAMESPACE_ID::_DescriptorProto_ExtensionRange_default_instance_._instance, + &::PROTOBUF_NAMESPACE_ID::_DescriptorProto_ReservedRange_default_instance_._instance, + &::PROTOBUF_NAMESPACE_ID::_DescriptorProto_default_instance_._instance, + &::PROTOBUF_NAMESPACE_ID::_ExtensionRangeOptions_default_instance_._instance, + &::PROTOBUF_NAMESPACE_ID::_FieldDescriptorProto_default_instance_._instance, + &::PROTOBUF_NAMESPACE_ID::_OneofDescriptorProto_default_instance_._instance, + &::PROTOBUF_NAMESPACE_ID::_EnumDescriptorProto_EnumReservedRange_default_instance_._instance, + &::PROTOBUF_NAMESPACE_ID::_EnumDescriptorProto_default_instance_._instance, + &::PROTOBUF_NAMESPACE_ID::_EnumValueDescriptorProto_default_instance_._instance, + &::PROTOBUF_NAMESPACE_ID::_ServiceDescriptorProto_default_instance_._instance, + &::PROTOBUF_NAMESPACE_ID::_MethodDescriptorProto_default_instance_._instance, + &::PROTOBUF_NAMESPACE_ID::_FileOptions_default_instance_._instance, + &::PROTOBUF_NAMESPACE_ID::_MessageOptions_default_instance_._instance, + &::PROTOBUF_NAMESPACE_ID::_FieldOptions_default_instance_._instance, + &::PROTOBUF_NAMESPACE_ID::_OneofOptions_default_instance_._instance, + &::PROTOBUF_NAMESPACE_ID::_EnumOptions_default_instance_._instance, + &::PROTOBUF_NAMESPACE_ID::_EnumValueOptions_default_instance_._instance, + &::PROTOBUF_NAMESPACE_ID::_ServiceOptions_default_instance_._instance, + &::PROTOBUF_NAMESPACE_ID::_MethodOptions_default_instance_._instance, + &::PROTOBUF_NAMESPACE_ID::_UninterpretedOption_NamePart_default_instance_._instance, + &::PROTOBUF_NAMESPACE_ID::_UninterpretedOption_default_instance_._instance, + &::PROTOBUF_NAMESPACE_ID::_SourceCodeInfo_Location_default_instance_._instance, + &::PROTOBUF_NAMESPACE_ID::_SourceCodeInfo_default_instance_._instance, + &::PROTOBUF_NAMESPACE_ID::_GeneratedCodeInfo_Annotation_default_instance_._instance, + &::PROTOBUF_NAMESPACE_ID::_GeneratedCodeInfo_default_instance_._instance, +}; + +const char descriptor_table_protodef_google_2fprotobuf_2fdescriptor_2eproto[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = + "\n google/protobuf/descriptor.proto\022\017goog" + "le.protobuf\"G\n\021FileDescriptorSet\0222\n\004file" + "\030\001 \003(\0132$.google.protobuf.FileDescriptorP" + "roto\"\333\003\n\023FileDescriptorProto\022\014\n\004name\030\001 \001" + "(\t\022\017\n\007package\030\002 \001(\t\022\022\n\ndependency\030\003 \003(\t\022" + "\031\n\021public_dependency\030\n \003(\005\022\027\n\017weak_depen" + "dency\030\013 \003(\005\0226\n\014message_type\030\004 \003(\0132 .goog" + "le.protobuf.DescriptorProto\0227\n\tenum_type" + "\030\005 \003(\0132$.google.protobuf.EnumDescriptorP" + "roto\0228\n\007service\030\006 \003(\0132\'.google.protobuf." + "ServiceDescriptorProto\0228\n\textension\030\007 \003(" + "\0132%.google.protobuf.FieldDescriptorProto" + "\022-\n\007options\030\010 \001(\0132\034.google.protobuf.File" + "Options\0229\n\020source_code_info\030\t \001(\0132\037.goog" + "le.protobuf.SourceCodeInfo\022\016\n\006syntax\030\014 \001" + "(\t\"\251\005\n\017DescriptorProto\022\014\n\004name\030\001 \001(\t\0224\n\005" + "field\030\002 \003(\0132%.google.protobuf.FieldDescr" + "iptorProto\0228\n\textension\030\006 \003(\0132%.google.p" + "rotobuf.FieldDescriptorProto\0225\n\013nested_t" + "ype\030\003 \003(\0132 .google.protobuf.DescriptorPr" + "oto\0227\n\tenum_type\030\004 \003(\0132$.google.protobuf" + ".EnumDescriptorProto\022H\n\017extension_range\030" + "\005 \003(\0132/.google.protobuf.DescriptorProto." + "ExtensionRange\0229\n\noneof_decl\030\010 \003(\0132%.goo" + "gle.protobuf.OneofDescriptorProto\0220\n\007opt" + "ions\030\007 \001(\0132\037.google.protobuf.MessageOpti" + "ons\022F\n\016reserved_range\030\t \003(\0132..google.pro" + "tobuf.DescriptorProto.ReservedRange\022\025\n\rr" + "eserved_name\030\n \003(\t\032e\n\016ExtensionRange\022\r\n\005" + "start\030\001 \001(\005\022\013\n\003end\030\002 \001(\005\0227\n\007options\030\003 \001(" + "\0132&.google.protobuf.ExtensionRangeOption" + "s\032+\n\rReservedRange\022\r\n\005start\030\001 \001(\005\022\013\n\003end" + "\030\002 \001(\005\"g\n\025ExtensionRangeOptions\022C\n\024unint" + "erpreted_option\030\347\007 \003(\0132$.google.protobuf" + ".UninterpretedOption*\t\010\350\007\020\200\200\200\200\002\"\325\005\n\024Fiel" + "dDescriptorProto\022\014\n\004name\030\001 \001(\t\022\016\n\006number" + "\030\003 \001(\005\022:\n\005label\030\004 \001(\0162+.google.protobuf." + "FieldDescriptorProto.Label\0228\n\004type\030\005 \001(\016" + "2*.google.protobuf.FieldDescriptorProto." + "Type\022\021\n\ttype_name\030\006 \001(\t\022\020\n\010extendee\030\002 \001(" + "\t\022\025\n\rdefault_value\030\007 \001(\t\022\023\n\013oneof_index\030" + "\t \001(\005\022\021\n\tjson_name\030\n \001(\t\022.\n\007options\030\010 \001(" + "\0132\035.google.protobuf.FieldOptions\022\027\n\017prot" + "o3_optional\030\021 \001(\010\"\266\002\n\004Type\022\017\n\013TYPE_DOUBL" + "E\020\001\022\016\n\nTYPE_FLOAT\020\002\022\016\n\nTYPE_INT64\020\003\022\017\n\013T" + "YPE_UINT64\020\004\022\016\n\nTYPE_INT32\020\005\022\020\n\014TYPE_FIX" + "ED64\020\006\022\020\n\014TYPE_FIXED32\020\007\022\r\n\tTYPE_BOOL\020\010\022" + "\017\n\013TYPE_STRING\020\t\022\016\n\nTYPE_GROUP\020\n\022\020\n\014TYPE" + "_MESSAGE\020\013\022\016\n\nTYPE_BYTES\020\014\022\017\n\013TYPE_UINT3" + "2\020\r\022\r\n\tTYPE_ENUM\020\016\022\021\n\rTYPE_SFIXED32\020\017\022\021\n" + "\rTYPE_SFIXED64\020\020\022\017\n\013TYPE_SINT32\020\021\022\017\n\013TYP" + "E_SINT64\020\022\"C\n\005Label\022\022\n\016LABEL_OPTIONAL\020\001\022" + "\022\n\016LABEL_REQUIRED\020\002\022\022\n\016LABEL_REPEATED\020\003\"" + "T\n\024OneofDescriptorProto\022\014\n\004name\030\001 \001(\t\022.\n" + "\007options\030\002 \001(\0132\035.google.protobuf.OneofOp" + "tions\"\244\002\n\023EnumDescriptorProto\022\014\n\004name\030\001 " + "\001(\t\0228\n\005value\030\002 \003(\0132).google.protobuf.Enu" + "mValueDescriptorProto\022-\n\007options\030\003 \001(\0132\034" + ".google.protobuf.EnumOptions\022N\n\016reserved" + "_range\030\004 \003(\01326.google.protobuf.EnumDescr" + "iptorProto.EnumReservedRange\022\025\n\rreserved" + "_name\030\005 \003(\t\032/\n\021EnumReservedRange\022\r\n\005star" + "t\030\001 \001(\005\022\013\n\003end\030\002 \001(\005\"l\n\030EnumValueDescrip" + "torProto\022\014\n\004name\030\001 \001(\t\022\016\n\006number\030\002 \001(\005\0222" + "\n\007options\030\003 \001(\0132!.google.protobuf.EnumVa" + "lueOptions\"\220\001\n\026ServiceDescriptorProto\022\014\n" + "\004name\030\001 \001(\t\0226\n\006method\030\002 \003(\0132&.google.pro" + "tobuf.MethodDescriptorProto\0220\n\007options\030\003" + " \001(\0132\037.google.protobuf.ServiceOptions\"\301\001" + "\n\025MethodDescriptorProto\022\014\n\004name\030\001 \001(\t\022\022\n" + "\ninput_type\030\002 \001(\t\022\023\n\013output_type\030\003 \001(\t\022/" + "\n\007options\030\004 \001(\0132\036.google.protobuf.Method" + "Options\022\037\n\020client_streaming\030\005 \001(\010:\005false" + "\022\037\n\020server_streaming\030\006 \001(\010:\005false\"\245\006\n\013Fi" + "leOptions\022\024\n\014java_package\030\001 \001(\t\022\034\n\024java_" + "outer_classname\030\010 \001(\t\022\"\n\023java_multiple_f" + "iles\030\n \001(\010:\005false\022)\n\035java_generate_equal" + "s_and_hash\030\024 \001(\010B\002\030\001\022%\n\026java_string_chec" + "k_utf8\030\033 \001(\010:\005false\022F\n\014optimize_for\030\t \001(" + "\0162).google.protobuf.FileOptions.Optimize" + "Mode:\005SPEED\022\022\n\ngo_package\030\013 \001(\t\022\"\n\023cc_ge" + "neric_services\030\020 \001(\010:\005false\022$\n\025java_gene" + "ric_services\030\021 \001(\010:\005false\022\"\n\023py_generic_" + "services\030\022 \001(\010:\005false\022#\n\024php_generic_ser" + "vices\030* \001(\010:\005false\022\031\n\ndeprecated\030\027 \001(\010:\005" + "false\022\036\n\020cc_enable_arenas\030\037 \001(\010:\004true\022\031\n" + "\021objc_class_prefix\030$ \001(\t\022\030\n\020csharp_names" + "pace\030% \001(\t\022\024\n\014swift_prefix\030\' \001(\t\022\030\n\020php_" + "class_prefix\030( \001(\t\022\025\n\rphp_namespace\030) \001(" + "\t\022\036\n\026php_metadata_namespace\030, \001(\t\022\024\n\014rub" + "y_package\030- \001(\t\022C\n\024uninterpreted_option\030" + "\347\007 \003(\0132$.google.protobuf.UninterpretedOp" + "tion\":\n\014OptimizeMode\022\t\n\005SPEED\020\001\022\r\n\tCODE_" + "SIZE\020\002\022\020\n\014LITE_RUNTIME\020\003*\t\010\350\007\020\200\200\200\200\002J\004\010&\020" + "\'\"\204\002\n\016MessageOptions\022&\n\027message_set_wire" + "_format\030\001 \001(\010:\005false\022.\n\037no_standard_desc" + "riptor_accessor\030\002 \001(\010:\005false\022\031\n\ndeprecat" + "ed\030\003 \001(\010:\005false\022\021\n\tmap_entry\030\007 \001(\010\022C\n\024un" + "interpreted_option\030\347\007 \003(\0132$.google.proto" + "buf.UninterpretedOption*\t\010\350\007\020\200\200\200\200\002J\004\010\004\020\005" + "J\004\010\005\020\006J\004\010\006\020\007J\004\010\010\020\tJ\004\010\t\020\n\"\276\003\n\014FieldOption" + "s\022:\n\005ctype\030\001 \001(\0162#.google.protobuf.Field" + "Options.CType:\006STRING\022\016\n\006packed\030\002 \001(\010\022\?\n" + "\006jstype\030\006 \001(\0162$.google.protobuf.FieldOpt" + "ions.JSType:\tJS_NORMAL\022\023\n\004lazy\030\005 \001(\010:\005fa" + "lse\022\036\n\017unverified_lazy\030\017 \001(\010:\005false\022\031\n\nd" + "eprecated\030\003 \001(\010:\005false\022\023\n\004weak\030\n \001(\010:\005fa" + "lse\022C\n\024uninterpreted_option\030\347\007 \003(\0132$.goo" + "gle.protobuf.UninterpretedOption\"/\n\005CTyp" + "e\022\n\n\006STRING\020\000\022\010\n\004CORD\020\001\022\020\n\014STRING_PIECE\020" + "\002\"5\n\006JSType\022\r\n\tJS_NORMAL\020\000\022\r\n\tJS_STRING\020" + "\001\022\r\n\tJS_NUMBER\020\002*\t\010\350\007\020\200\200\200\200\002J\004\010\004\020\005\"^\n\014One" + "ofOptions\022C\n\024uninterpreted_option\030\347\007 \003(\013" + "2$.google.protobuf.UninterpretedOption*\t" + "\010\350\007\020\200\200\200\200\002\"\223\001\n\013EnumOptions\022\023\n\013allow_alias" + "\030\002 \001(\010\022\031\n\ndeprecated\030\003 \001(\010:\005false\022C\n\024uni" + "nterpreted_option\030\347\007 \003(\0132$.google.protob" + "uf.UninterpretedOption*\t\010\350\007\020\200\200\200\200\002J\004\010\005\020\006\"" + "}\n\020EnumValueOptions\022\031\n\ndeprecated\030\001 \001(\010:" + "\005false\022C\n\024uninterpreted_option\030\347\007 \003(\0132$." + "google.protobuf.UninterpretedOption*\t\010\350\007" + "\020\200\200\200\200\002\"{\n\016ServiceOptions\022\031\n\ndeprecated\030!" + " \001(\010:\005false\022C\n\024uninterpreted_option\030\347\007 \003" + "(\0132$.google.protobuf.UninterpretedOption" + "*\t\010\350\007\020\200\200\200\200\002\"\255\002\n\rMethodOptions\022\031\n\ndepreca" + "ted\030! \001(\010:\005false\022_\n\021idempotency_level\030\" " + "\001(\0162/.google.protobuf.MethodOptions.Idem" + "potencyLevel:\023IDEMPOTENCY_UNKNOWN\022C\n\024uni" + "nterpreted_option\030\347\007 \003(\0132$.google.protob" + "uf.UninterpretedOption\"P\n\020IdempotencyLev" + "el\022\027\n\023IDEMPOTENCY_UNKNOWN\020\000\022\023\n\017NO_SIDE_E" + "FFECTS\020\001\022\016\n\nIDEMPOTENT\020\002*\t\010\350\007\020\200\200\200\200\002\"\236\002\n\023" + "UninterpretedOption\022;\n\004name\030\002 \003(\0132-.goog" + "le.protobuf.UninterpretedOption.NamePart" + "\022\030\n\020identifier_value\030\003 \001(\t\022\032\n\022positive_i" + "nt_value\030\004 \001(\004\022\032\n\022negative_int_value\030\005 \001" + "(\003\022\024\n\014double_value\030\006 \001(\001\022\024\n\014string_value" + "\030\007 \001(\014\022\027\n\017aggregate_value\030\010 \001(\t\0323\n\010NameP" + "art\022\021\n\tname_part\030\001 \002(\t\022\024\n\014is_extension\030\002" + " \002(\010\"\325\001\n\016SourceCodeInfo\022:\n\010location\030\001 \003(" + "\0132(.google.protobuf.SourceCodeInfo.Locat" + "ion\032\206\001\n\010Location\022\020\n\004path\030\001 \003(\005B\002\020\001\022\020\n\004sp" + "an\030\002 \003(\005B\002\020\001\022\030\n\020leading_comments\030\003 \001(\t\022\031" + "\n\021trailing_comments\030\004 \001(\t\022!\n\031leading_det" + "ached_comments\030\006 \003(\t\"\247\001\n\021GeneratedCodeIn" + "fo\022A\n\nannotation\030\001 \003(\0132-.google.protobuf" + ".GeneratedCodeInfo.Annotation\032O\n\nAnnotat" + "ion\022\020\n\004path\030\001 \003(\005B\002\020\001\022\023\n\013source_file\030\002 \001" + "(\t\022\r\n\005begin\030\003 \001(\005\022\013\n\003end\030\004 \001(\005B~\n\023com.go" + "ogle.protobufB\020DescriptorProtosH\001Z-googl" + "e.golang.org/protobuf/types/descriptorpb" + "\370\001\001\242\002\003GPB\252\002\032Google.Protobuf.Reflection" + ; +static ::_pbi::once_flag descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_once; +const ::_pbi::DescriptorTable descriptor_table_google_2fprotobuf_2fdescriptor_2eproto = { + false, false, 6078, descriptor_table_protodef_google_2fprotobuf_2fdescriptor_2eproto, + "google/protobuf/descriptor.proto", + &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_once, nullptr, 0, 27, + schemas, file_default_instances, TableStruct_google_2fprotobuf_2fdescriptor_2eproto::offsets, + file_level_metadata_google_2fprotobuf_2fdescriptor_2eproto, file_level_enum_descriptors_google_2fprotobuf_2fdescriptor_2eproto, + file_level_service_descriptors_google_2fprotobuf_2fdescriptor_2eproto, +}; +PROTOBUF_ATTRIBUTE_WEAK const ::_pbi::DescriptorTable* descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_getter() { + return &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto; +} + +// Force running AddDescriptors() at dynamic initialization time. +PROTOBUF_ATTRIBUTE_INIT_PRIORITY2 static ::_pbi::AddDescriptorsRunner dynamic_init_dummy_google_2fprotobuf_2fdescriptor_2eproto(&descriptor_table_google_2fprotobuf_2fdescriptor_2eproto); +PROTOBUF_NAMESPACE_OPEN +const ::PROTOBUF_NAMESPACE_ID::EnumDescriptor* FieldDescriptorProto_Type_descriptor() { + ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&descriptor_table_google_2fprotobuf_2fdescriptor_2eproto); + return file_level_enum_descriptors_google_2fprotobuf_2fdescriptor_2eproto[0]; +} +bool FieldDescriptorProto_Type_IsValid(int value) { + switch (value) { + case 1: + case 2: + case 3: + case 4: + case 5: + case 6: + case 7: + case 8: + case 9: + case 10: + case 11: + case 12: + case 13: + case 14: + case 15: + case 16: + case 17: + case 18: + return true; + default: + return false; + } +} + +#if (__cplusplus < 201703) && (!defined(_MSC_VER) || (_MSC_VER >= 1900 && _MSC_VER < 1912)) +constexpr FieldDescriptorProto_Type FieldDescriptorProto::TYPE_DOUBLE; +constexpr FieldDescriptorProto_Type FieldDescriptorProto::TYPE_FLOAT; +constexpr FieldDescriptorProto_Type FieldDescriptorProto::TYPE_INT64; +constexpr FieldDescriptorProto_Type FieldDescriptorProto::TYPE_UINT64; +constexpr FieldDescriptorProto_Type FieldDescriptorProto::TYPE_INT32; +constexpr FieldDescriptorProto_Type FieldDescriptorProto::TYPE_FIXED64; +constexpr FieldDescriptorProto_Type FieldDescriptorProto::TYPE_FIXED32; +constexpr FieldDescriptorProto_Type FieldDescriptorProto::TYPE_BOOL; +constexpr FieldDescriptorProto_Type FieldDescriptorProto::TYPE_STRING; +constexpr FieldDescriptorProto_Type FieldDescriptorProto::TYPE_GROUP; +constexpr FieldDescriptorProto_Type FieldDescriptorProto::TYPE_MESSAGE; +constexpr FieldDescriptorProto_Type FieldDescriptorProto::TYPE_BYTES; +constexpr FieldDescriptorProto_Type FieldDescriptorProto::TYPE_UINT32; +constexpr FieldDescriptorProto_Type FieldDescriptorProto::TYPE_ENUM; +constexpr FieldDescriptorProto_Type FieldDescriptorProto::TYPE_SFIXED32; +constexpr FieldDescriptorProto_Type FieldDescriptorProto::TYPE_SFIXED64; +constexpr FieldDescriptorProto_Type FieldDescriptorProto::TYPE_SINT32; +constexpr FieldDescriptorProto_Type FieldDescriptorProto::TYPE_SINT64; +constexpr FieldDescriptorProto_Type FieldDescriptorProto::Type_MIN; +constexpr FieldDescriptorProto_Type FieldDescriptorProto::Type_MAX; +constexpr int FieldDescriptorProto::Type_ARRAYSIZE; +#endif // (__cplusplus < 201703) && (!defined(_MSC_VER) || (_MSC_VER >= 1900 && _MSC_VER < 1912)) +const ::PROTOBUF_NAMESPACE_ID::EnumDescriptor* FieldDescriptorProto_Label_descriptor() { + ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&descriptor_table_google_2fprotobuf_2fdescriptor_2eproto); + return file_level_enum_descriptors_google_2fprotobuf_2fdescriptor_2eproto[1]; +} +bool FieldDescriptorProto_Label_IsValid(int value) { + switch (value) { + case 1: + case 2: + case 3: + return true; + default: + return false; + } +} + +#if (__cplusplus < 201703) && (!defined(_MSC_VER) || (_MSC_VER >= 1900 && _MSC_VER < 1912)) +constexpr FieldDescriptorProto_Label FieldDescriptorProto::LABEL_OPTIONAL; +constexpr FieldDescriptorProto_Label FieldDescriptorProto::LABEL_REQUIRED; +constexpr FieldDescriptorProto_Label FieldDescriptorProto::LABEL_REPEATED; +constexpr FieldDescriptorProto_Label FieldDescriptorProto::Label_MIN; +constexpr FieldDescriptorProto_Label FieldDescriptorProto::Label_MAX; +constexpr int FieldDescriptorProto::Label_ARRAYSIZE; +#endif // (__cplusplus < 201703) && (!defined(_MSC_VER) || (_MSC_VER >= 1900 && _MSC_VER < 1912)) +const ::PROTOBUF_NAMESPACE_ID::EnumDescriptor* FileOptions_OptimizeMode_descriptor() { + ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&descriptor_table_google_2fprotobuf_2fdescriptor_2eproto); + return file_level_enum_descriptors_google_2fprotobuf_2fdescriptor_2eproto[2]; +} +bool FileOptions_OptimizeMode_IsValid(int value) { + switch (value) { + case 1: + case 2: + case 3: + return true; + default: + return false; + } +} + +#if (__cplusplus < 201703) && (!defined(_MSC_VER) || (_MSC_VER >= 1900 && _MSC_VER < 1912)) +constexpr FileOptions_OptimizeMode FileOptions::SPEED; +constexpr FileOptions_OptimizeMode FileOptions::CODE_SIZE; +constexpr FileOptions_OptimizeMode FileOptions::LITE_RUNTIME; +constexpr FileOptions_OptimizeMode FileOptions::OptimizeMode_MIN; +constexpr FileOptions_OptimizeMode FileOptions::OptimizeMode_MAX; +constexpr int FileOptions::OptimizeMode_ARRAYSIZE; +#endif // (__cplusplus < 201703) && (!defined(_MSC_VER) || (_MSC_VER >= 1900 && _MSC_VER < 1912)) +const ::PROTOBUF_NAMESPACE_ID::EnumDescriptor* FieldOptions_CType_descriptor() { + ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&descriptor_table_google_2fprotobuf_2fdescriptor_2eproto); + return file_level_enum_descriptors_google_2fprotobuf_2fdescriptor_2eproto[3]; +} +bool FieldOptions_CType_IsValid(int value) { + switch (value) { + case 0: + case 1: + case 2: + return true; + default: + return false; + } +} + +#if (__cplusplus < 201703) && (!defined(_MSC_VER) || (_MSC_VER >= 1900 && _MSC_VER < 1912)) +constexpr FieldOptions_CType FieldOptions::STRING; +constexpr FieldOptions_CType FieldOptions::CORD; +constexpr FieldOptions_CType FieldOptions::STRING_PIECE; +constexpr FieldOptions_CType FieldOptions::CType_MIN; +constexpr FieldOptions_CType FieldOptions::CType_MAX; +constexpr int FieldOptions::CType_ARRAYSIZE; +#endif // (__cplusplus < 201703) && (!defined(_MSC_VER) || (_MSC_VER >= 1900 && _MSC_VER < 1912)) +const ::PROTOBUF_NAMESPACE_ID::EnumDescriptor* FieldOptions_JSType_descriptor() { + ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&descriptor_table_google_2fprotobuf_2fdescriptor_2eproto); + return file_level_enum_descriptors_google_2fprotobuf_2fdescriptor_2eproto[4]; +} +bool FieldOptions_JSType_IsValid(int value) { + switch (value) { + case 0: + case 1: + case 2: + return true; + default: + return false; + } +} + +#if (__cplusplus < 201703) && (!defined(_MSC_VER) || (_MSC_VER >= 1900 && _MSC_VER < 1912)) +constexpr FieldOptions_JSType FieldOptions::JS_NORMAL; +constexpr FieldOptions_JSType FieldOptions::JS_STRING; +constexpr FieldOptions_JSType FieldOptions::JS_NUMBER; +constexpr FieldOptions_JSType FieldOptions::JSType_MIN; +constexpr FieldOptions_JSType FieldOptions::JSType_MAX; +constexpr int FieldOptions::JSType_ARRAYSIZE; +#endif // (__cplusplus < 201703) && (!defined(_MSC_VER) || (_MSC_VER >= 1900 && _MSC_VER < 1912)) +const ::PROTOBUF_NAMESPACE_ID::EnumDescriptor* MethodOptions_IdempotencyLevel_descriptor() { + ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&descriptor_table_google_2fprotobuf_2fdescriptor_2eproto); + return file_level_enum_descriptors_google_2fprotobuf_2fdescriptor_2eproto[5]; +} +bool MethodOptions_IdempotencyLevel_IsValid(int value) { + switch (value) { + case 0: + case 1: + case 2: + return true; + default: + return false; + } +} + +#if (__cplusplus < 201703) && (!defined(_MSC_VER) || (_MSC_VER >= 1900 && _MSC_VER < 1912)) +constexpr MethodOptions_IdempotencyLevel MethodOptions::IDEMPOTENCY_UNKNOWN; +constexpr MethodOptions_IdempotencyLevel MethodOptions::NO_SIDE_EFFECTS; +constexpr MethodOptions_IdempotencyLevel MethodOptions::IDEMPOTENT; +constexpr MethodOptions_IdempotencyLevel MethodOptions::IdempotencyLevel_MIN; +constexpr MethodOptions_IdempotencyLevel MethodOptions::IdempotencyLevel_MAX; +constexpr int MethodOptions::IdempotencyLevel_ARRAYSIZE; +#endif // (__cplusplus < 201703) && (!defined(_MSC_VER) || (_MSC_VER >= 1900 && _MSC_VER < 1912)) + +// =================================================================== + +class FileDescriptorSet::_Internal { + public: +}; + +FileDescriptorSet::FileDescriptorSet(::PROTOBUF_NAMESPACE_ID::Arena* arena, + bool is_message_owned) + : ::PROTOBUF_NAMESPACE_ID::Message(arena, is_message_owned) { + SharedCtor(arena, is_message_owned); + // @@protoc_insertion_point(arena_constructor:google.protobuf.FileDescriptorSet) +} +FileDescriptorSet::FileDescriptorSet(const FileDescriptorSet& from) + : ::PROTOBUF_NAMESPACE_ID::Message() { + FileDescriptorSet* const _this = this; (void)_this; + new (&_impl_) Impl_{ + decltype(_impl_.file_){from._impl_.file_} + , /*decltype(_impl_._cached_size_)*/{}}; + + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); + // @@protoc_insertion_point(copy_constructor:google.protobuf.FileDescriptorSet) +} + +inline void FileDescriptorSet::SharedCtor( + ::_pb::Arena* arena, bool is_message_owned) { + (void)arena; + (void)is_message_owned; + new (&_impl_) Impl_{ + decltype(_impl_.file_){arena} + , /*decltype(_impl_._cached_size_)*/{} + }; +} + +FileDescriptorSet::~FileDescriptorSet() { + // @@protoc_insertion_point(destructor:google.protobuf.FileDescriptorSet) + if (auto *arena = _internal_metadata_.DeleteReturnArena<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>()) { + (void)arena; + return; + } + SharedDtor(); +} + +inline void FileDescriptorSet::SharedDtor() { + GOOGLE_DCHECK(GetArenaForAllocation() == nullptr); + _impl_.file_.~RepeatedPtrField(); +} + +void FileDescriptorSet::SetCachedSize(int size) const { + _impl_._cached_size_.Set(size); +} + +void FileDescriptorSet::Clear() { +// @@protoc_insertion_point(message_clear_start:google.protobuf.FileDescriptorSet) + uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + _impl_.file_.Clear(); + _internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); +} + +const char* FileDescriptorSet::_InternalParse(const char* ptr, ::_pbi::ParseContext* ctx) { +#define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure + while (!ctx->Done(&ptr)) { + uint32_t tag; + ptr = ::_pbi::ReadTag(ptr, &tag); + switch (tag >> 3) { + // repeated .google.protobuf.FileDescriptorProto file = 1; + case 1: + if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 10)) { + ptr -= 1; + do { + ptr += 1; + ptr = ctx->ParseMessage(_internal_add_file(), ptr); + CHK_(ptr); + if (!ctx->DataAvailable(ptr)) break; + } while (::PROTOBUF_NAMESPACE_ID::internal::ExpectTag<10>(ptr)); + } else + goto handle_unusual; + continue; + default: + goto handle_unusual; + } // switch + handle_unusual: + if ((tag == 0) || ((tag & 7) == 4)) { + CHK_(ptr); + ctx->SetLastTag(tag); + goto message_done; + } + ptr = UnknownFieldParse( + tag, + _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(), + ptr, ctx); + CHK_(ptr != nullptr); + } // while +message_done: + return ptr; +failure: + ptr = nullptr; + goto message_done; +#undef CHK_ +} + +uint8_t* FileDescriptorSet::_InternalSerialize( + uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const { + // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.FileDescriptorSet) + uint32_t cached_has_bits = 0; + (void) cached_has_bits; + + // repeated .google.protobuf.FileDescriptorProto file = 1; + for (unsigned i = 0, + n = static_cast<unsigned>(this->_internal_file_size()); i < n; i++) { + const auto& repfield = this->_internal_file(i); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite:: + InternalWriteMessage(1, repfield, repfield.GetCachedSize(), target, stream); + } + + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + target = ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( + _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.FileDescriptorSet) + return target; +} + +size_t FileDescriptorSet::ByteSizeLong() const { +// @@protoc_insertion_point(message_byte_size_start:google.protobuf.FileDescriptorSet) + size_t total_size = 0; + + uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + // repeated .google.protobuf.FileDescriptorProto file = 1; + total_size += 1UL * this->_internal_file_size(); + for (const auto& msg : this->_impl_.file_) { + total_size += + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::MessageSize(msg); + } + + return MaybeComputeUnknownFieldsSize(total_size, &_impl_._cached_size_); +} + +const ::PROTOBUF_NAMESPACE_ID::Message::ClassData FileDescriptorSet::_class_data_ = { + ::PROTOBUF_NAMESPACE_ID::Message::CopyWithSourceCheck, + FileDescriptorSet::MergeImpl +}; +const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*FileDescriptorSet::GetClassData() const { return &_class_data_; } + + +void FileDescriptorSet::MergeImpl(::PROTOBUF_NAMESPACE_ID::Message& to_msg, const ::PROTOBUF_NAMESPACE_ID::Message& from_msg) { + auto* const _this = static_cast<FileDescriptorSet*>(&to_msg); + auto& from = static_cast<const FileDescriptorSet&>(from_msg); + // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.FileDescriptorSet) + GOOGLE_DCHECK_NE(&from, _this); + uint32_t cached_has_bits = 0; + (void) cached_has_bits; + + _this->_impl_.file_.MergeFrom(from._impl_.file_); + _this->_internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); +} + +void FileDescriptorSet::CopyFrom(const FileDescriptorSet& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.FileDescriptorSet) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool FileDescriptorSet::IsInitialized() const { + if (!::PROTOBUF_NAMESPACE_ID::internal::AllAreInitialized(_impl_.file_)) + return false; + return true; +} + +void FileDescriptorSet::InternalSwap(FileDescriptorSet* other) { + using std::swap; + _internal_metadata_.InternalSwap(&other->_internal_metadata_); + _impl_.file_.InternalSwap(&other->_impl_.file_); +} + +::PROTOBUF_NAMESPACE_ID::Metadata FileDescriptorSet::GetMetadata() const { + return ::_pbi::AssignDescriptors( + &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_getter, &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_once, + file_level_metadata_google_2fprotobuf_2fdescriptor_2eproto[0]); +} + +// =================================================================== + +class FileDescriptorProto::_Internal { + public: + using HasBits = decltype(std::declval<FileDescriptorProto>()._impl_._has_bits_); + static void set_has_name(HasBits* has_bits) { + (*has_bits)[0] |= 1u; + } + static void set_has_package(HasBits* has_bits) { + (*has_bits)[0] |= 2u; + } + static const ::PROTOBUF_NAMESPACE_ID::FileOptions& options(const FileDescriptorProto* msg); + static void set_has_options(HasBits* has_bits) { + (*has_bits)[0] |= 8u; + } + static const ::PROTOBUF_NAMESPACE_ID::SourceCodeInfo& source_code_info(const FileDescriptorProto* msg); + static void set_has_source_code_info(HasBits* has_bits) { + (*has_bits)[0] |= 16u; + } + static void set_has_syntax(HasBits* has_bits) { + (*has_bits)[0] |= 4u; + } +}; + +const ::PROTOBUF_NAMESPACE_ID::FileOptions& +FileDescriptorProto::_Internal::options(const FileDescriptorProto* msg) { + return *msg->_impl_.options_; +} +const ::PROTOBUF_NAMESPACE_ID::SourceCodeInfo& +FileDescriptorProto::_Internal::source_code_info(const FileDescriptorProto* msg) { + return *msg->_impl_.source_code_info_; +} +FileDescriptorProto::FileDescriptorProto(::PROTOBUF_NAMESPACE_ID::Arena* arena, + bool is_message_owned) + : ::PROTOBUF_NAMESPACE_ID::Message(arena, is_message_owned) { + SharedCtor(arena, is_message_owned); + // @@protoc_insertion_point(arena_constructor:google.protobuf.FileDescriptorProto) +} +FileDescriptorProto::FileDescriptorProto(const FileDescriptorProto& from) + : ::PROTOBUF_NAMESPACE_ID::Message() { + FileDescriptorProto* const _this = this; (void)_this; + new (&_impl_) Impl_{ + decltype(_impl_._has_bits_){from._impl_._has_bits_} + , /*decltype(_impl_._cached_size_)*/{} + , decltype(_impl_.dependency_){from._impl_.dependency_} + , decltype(_impl_.message_type_){from._impl_.message_type_} + , decltype(_impl_.enum_type_){from._impl_.enum_type_} + , decltype(_impl_.service_){from._impl_.service_} + , decltype(_impl_.extension_){from._impl_.extension_} + , decltype(_impl_.public_dependency_){from._impl_.public_dependency_} + , decltype(_impl_.weak_dependency_){from._impl_.weak_dependency_} + , decltype(_impl_.name_){} + , decltype(_impl_.package_){} + , decltype(_impl_.syntax_){} + , decltype(_impl_.options_){nullptr} + , decltype(_impl_.source_code_info_){nullptr}}; + + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); + _impl_.name_.InitDefault(); + #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + _impl_.name_.Set("", GetArenaForAllocation()); + #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (from._internal_has_name()) { + _this->_impl_.name_.Set(from._internal_name(), + _this->GetArenaForAllocation()); + } + _impl_.package_.InitDefault(); + #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + _impl_.package_.Set("", GetArenaForAllocation()); + #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (from._internal_has_package()) { + _this->_impl_.package_.Set(from._internal_package(), + _this->GetArenaForAllocation()); + } + _impl_.syntax_.InitDefault(); + #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + _impl_.syntax_.Set("", GetArenaForAllocation()); + #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (from._internal_has_syntax()) { + _this->_impl_.syntax_.Set(from._internal_syntax(), + _this->GetArenaForAllocation()); + } + if (from._internal_has_options()) { + _this->_impl_.options_ = new ::PROTOBUF_NAMESPACE_ID::FileOptions(*from._impl_.options_); + } + if (from._internal_has_source_code_info()) { + _this->_impl_.source_code_info_ = new ::PROTOBUF_NAMESPACE_ID::SourceCodeInfo(*from._impl_.source_code_info_); + } + // @@protoc_insertion_point(copy_constructor:google.protobuf.FileDescriptorProto) +} + +inline void FileDescriptorProto::SharedCtor( + ::_pb::Arena* arena, bool is_message_owned) { + (void)arena; + (void)is_message_owned; + new (&_impl_) Impl_{ + decltype(_impl_._has_bits_){} + , /*decltype(_impl_._cached_size_)*/{} + , decltype(_impl_.dependency_){arena} + , decltype(_impl_.message_type_){arena} + , decltype(_impl_.enum_type_){arena} + , decltype(_impl_.service_){arena} + , decltype(_impl_.extension_){arena} + , decltype(_impl_.public_dependency_){arena} + , decltype(_impl_.weak_dependency_){arena} + , decltype(_impl_.name_){} + , decltype(_impl_.package_){} + , decltype(_impl_.syntax_){} + , decltype(_impl_.options_){nullptr} + , decltype(_impl_.source_code_info_){nullptr} + }; + _impl_.name_.InitDefault(); + #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + _impl_.name_.Set("", GetArenaForAllocation()); + #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + _impl_.package_.InitDefault(); + #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + _impl_.package_.Set("", GetArenaForAllocation()); + #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + _impl_.syntax_.InitDefault(); + #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + _impl_.syntax_.Set("", GetArenaForAllocation()); + #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING +} + +FileDescriptorProto::~FileDescriptorProto() { + // @@protoc_insertion_point(destructor:google.protobuf.FileDescriptorProto) + if (auto *arena = _internal_metadata_.DeleteReturnArena<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>()) { + (void)arena; + return; + } + SharedDtor(); +} + +inline void FileDescriptorProto::SharedDtor() { + GOOGLE_DCHECK(GetArenaForAllocation() == nullptr); + _impl_.dependency_.~RepeatedPtrField(); + _impl_.message_type_.~RepeatedPtrField(); + _impl_.enum_type_.~RepeatedPtrField(); + _impl_.service_.~RepeatedPtrField(); + _impl_.extension_.~RepeatedPtrField(); + _impl_.public_dependency_.~RepeatedField(); + _impl_.weak_dependency_.~RepeatedField(); + _impl_.name_.Destroy(); + _impl_.package_.Destroy(); + _impl_.syntax_.Destroy(); + if (this != internal_default_instance()) delete _impl_.options_; + if (this != internal_default_instance()) delete _impl_.source_code_info_; +} + +void FileDescriptorProto::SetCachedSize(int size) const { + _impl_._cached_size_.Set(size); +} + +void FileDescriptorProto::Clear() { +// @@protoc_insertion_point(message_clear_start:google.protobuf.FileDescriptorProto) + uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + _impl_.dependency_.Clear(); + _impl_.message_type_.Clear(); + _impl_.enum_type_.Clear(); + _impl_.service_.Clear(); + _impl_.extension_.Clear(); + _impl_.public_dependency_.Clear(); + _impl_.weak_dependency_.Clear(); + cached_has_bits = _impl_._has_bits_[0]; + if (cached_has_bits & 0x0000001fu) { + if (cached_has_bits & 0x00000001u) { + _impl_.name_.ClearNonDefaultToEmpty(); + } + if (cached_has_bits & 0x00000002u) { + _impl_.package_.ClearNonDefaultToEmpty(); + } + if (cached_has_bits & 0x00000004u) { + _impl_.syntax_.ClearNonDefaultToEmpty(); + } + if (cached_has_bits & 0x00000008u) { + GOOGLE_DCHECK(_impl_.options_ != nullptr); + _impl_.options_->Clear(); + } + if (cached_has_bits & 0x00000010u) { + GOOGLE_DCHECK(_impl_.source_code_info_ != nullptr); + _impl_.source_code_info_->Clear(); + } + } + _impl_._has_bits_.Clear(); + _internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); +} + +const char* FileDescriptorProto::_InternalParse(const char* ptr, ::_pbi::ParseContext* ctx) { +#define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure + _Internal::HasBits has_bits{}; + while (!ctx->Done(&ptr)) { + uint32_t tag; + ptr = ::_pbi::ReadTag(ptr, &tag); + switch (tag >> 3) { + // optional string name = 1; + case 1: + if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 10)) { + auto str = _internal_mutable_name(); + ptr = ::_pbi::InlineGreedyStringParser(str, ptr, ctx); + CHK_(ptr); + #ifndef NDEBUG + ::_pbi::VerifyUTF8(str, "google.protobuf.FileDescriptorProto.name"); + #endif // !NDEBUG + } else + goto handle_unusual; + continue; + // optional string package = 2; + case 2: + if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 18)) { + auto str = _internal_mutable_package(); + ptr = ::_pbi::InlineGreedyStringParser(str, ptr, ctx); + CHK_(ptr); + #ifndef NDEBUG + ::_pbi::VerifyUTF8(str, "google.protobuf.FileDescriptorProto.package"); + #endif // !NDEBUG + } else + goto handle_unusual; + continue; + // repeated string dependency = 3; + case 3: + if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 26)) { + ptr -= 1; + do { + ptr += 1; + auto str = _internal_add_dependency(); + ptr = ::_pbi::InlineGreedyStringParser(str, ptr, ctx); + CHK_(ptr); + #ifndef NDEBUG + ::_pbi::VerifyUTF8(str, "google.protobuf.FileDescriptorProto.dependency"); + #endif // !NDEBUG + if (!ctx->DataAvailable(ptr)) break; + } while (::PROTOBUF_NAMESPACE_ID::internal::ExpectTag<26>(ptr)); + } else + goto handle_unusual; + continue; + // repeated .google.protobuf.DescriptorProto message_type = 4; + case 4: + if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 34)) { + ptr -= 1; + do { + ptr += 1; + ptr = ctx->ParseMessage(_internal_add_message_type(), ptr); + CHK_(ptr); + if (!ctx->DataAvailable(ptr)) break; + } while (::PROTOBUF_NAMESPACE_ID::internal::ExpectTag<34>(ptr)); + } else + goto handle_unusual; + continue; + // repeated .google.protobuf.EnumDescriptorProto enum_type = 5; + case 5: + if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 42)) { + ptr -= 1; + do { + ptr += 1; + ptr = ctx->ParseMessage(_internal_add_enum_type(), ptr); + CHK_(ptr); + if (!ctx->DataAvailable(ptr)) break; + } while (::PROTOBUF_NAMESPACE_ID::internal::ExpectTag<42>(ptr)); + } else + goto handle_unusual; + continue; + // repeated .google.protobuf.ServiceDescriptorProto service = 6; + case 6: + if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 50)) { + ptr -= 1; + do { + ptr += 1; + ptr = ctx->ParseMessage(_internal_add_service(), ptr); + CHK_(ptr); + if (!ctx->DataAvailable(ptr)) break; + } while (::PROTOBUF_NAMESPACE_ID::internal::ExpectTag<50>(ptr)); + } else + goto handle_unusual; + continue; + // repeated .google.protobuf.FieldDescriptorProto extension = 7; + case 7: + if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 58)) { + ptr -= 1; + do { + ptr += 1; + ptr = ctx->ParseMessage(_internal_add_extension(), ptr); + CHK_(ptr); + if (!ctx->DataAvailable(ptr)) break; + } while (::PROTOBUF_NAMESPACE_ID::internal::ExpectTag<58>(ptr)); + } else + goto handle_unusual; + continue; + // optional .google.protobuf.FileOptions options = 8; + case 8: + if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 66)) { + ptr = ctx->ParseMessage(_internal_mutable_options(), ptr); + CHK_(ptr); + } else + goto handle_unusual; + continue; + // optional .google.protobuf.SourceCodeInfo source_code_info = 9; + case 9: + if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 74)) { + ptr = ctx->ParseMessage(_internal_mutable_source_code_info(), ptr); + CHK_(ptr); + } else + goto handle_unusual; + continue; + // repeated int32 public_dependency = 10; + case 10: + if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 80)) { + ptr -= 1; + do { + ptr += 1; + _internal_add_public_dependency(::PROTOBUF_NAMESPACE_ID::internal::ReadVarint32(&ptr)); + CHK_(ptr); + if (!ctx->DataAvailable(ptr)) break; + } while (::PROTOBUF_NAMESPACE_ID::internal::ExpectTag<80>(ptr)); + } else if (static_cast<uint8_t>(tag) == 82) { + ptr = ::PROTOBUF_NAMESPACE_ID::internal::PackedInt32Parser(_internal_mutable_public_dependency(), ptr, ctx); + CHK_(ptr); + } else + goto handle_unusual; + continue; + // repeated int32 weak_dependency = 11; + case 11: + if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 88)) { + ptr -= 1; + do { + ptr += 1; + _internal_add_weak_dependency(::PROTOBUF_NAMESPACE_ID::internal::ReadVarint32(&ptr)); + CHK_(ptr); + if (!ctx->DataAvailable(ptr)) break; + } while (::PROTOBUF_NAMESPACE_ID::internal::ExpectTag<88>(ptr)); + } else if (static_cast<uint8_t>(tag) == 90) { + ptr = ::PROTOBUF_NAMESPACE_ID::internal::PackedInt32Parser(_internal_mutable_weak_dependency(), ptr, ctx); + CHK_(ptr); + } else + goto handle_unusual; + continue; + // optional string syntax = 12; + case 12: + if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 98)) { + auto str = _internal_mutable_syntax(); + ptr = ::_pbi::InlineGreedyStringParser(str, ptr, ctx); + CHK_(ptr); + #ifndef NDEBUG + ::_pbi::VerifyUTF8(str, "google.protobuf.FileDescriptorProto.syntax"); + #endif // !NDEBUG + } else + goto handle_unusual; + continue; + default: + goto handle_unusual; + } // switch + handle_unusual: + if ((tag == 0) || ((tag & 7) == 4)) { + CHK_(ptr); + ctx->SetLastTag(tag); + goto message_done; + } + ptr = UnknownFieldParse( + tag, + _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(), + ptr, ctx); + CHK_(ptr != nullptr); + } // while +message_done: + _impl_._has_bits_.Or(has_bits); + return ptr; +failure: + ptr = nullptr; + goto message_done; +#undef CHK_ +} + +uint8_t* FileDescriptorProto::_InternalSerialize( + uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const { + // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.FileDescriptorProto) + uint32_t cached_has_bits = 0; + (void) cached_has_bits; + + cached_has_bits = _impl_._has_bits_[0]; + // optional string name = 1; + if (cached_has_bits & 0x00000001u) { + ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::VerifyUTF8StringNamedField( + this->_internal_name().data(), static_cast<int>(this->_internal_name().length()), + ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::SERIALIZE, + "google.protobuf.FileDescriptorProto.name"); + target = stream->WriteStringMaybeAliased( + 1, this->_internal_name(), target); + } + + // optional string package = 2; + if (cached_has_bits & 0x00000002u) { + ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::VerifyUTF8StringNamedField( + this->_internal_package().data(), static_cast<int>(this->_internal_package().length()), + ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::SERIALIZE, + "google.protobuf.FileDescriptorProto.package"); + target = stream->WriteStringMaybeAliased( + 2, this->_internal_package(), target); + } + + // repeated string dependency = 3; + for (int i = 0, n = this->_internal_dependency_size(); i < n; i++) { + const auto& s = this->_internal_dependency(i); + ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::VerifyUTF8StringNamedField( + s.data(), static_cast<int>(s.length()), + ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::SERIALIZE, + "google.protobuf.FileDescriptorProto.dependency"); + target = stream->WriteString(3, s, target); + } + + // repeated .google.protobuf.DescriptorProto message_type = 4; + for (unsigned i = 0, + n = static_cast<unsigned>(this->_internal_message_type_size()); i < n; i++) { + const auto& repfield = this->_internal_message_type(i); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite:: + InternalWriteMessage(4, repfield, repfield.GetCachedSize(), target, stream); + } + + // repeated .google.protobuf.EnumDescriptorProto enum_type = 5; + for (unsigned i = 0, + n = static_cast<unsigned>(this->_internal_enum_type_size()); i < n; i++) { + const auto& repfield = this->_internal_enum_type(i); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite:: + InternalWriteMessage(5, repfield, repfield.GetCachedSize(), target, stream); + } + + // repeated .google.protobuf.ServiceDescriptorProto service = 6; + for (unsigned i = 0, + n = static_cast<unsigned>(this->_internal_service_size()); i < n; i++) { + const auto& repfield = this->_internal_service(i); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite:: + InternalWriteMessage(6, repfield, repfield.GetCachedSize(), target, stream); + } + + // repeated .google.protobuf.FieldDescriptorProto extension = 7; + for (unsigned i = 0, + n = static_cast<unsigned>(this->_internal_extension_size()); i < n; i++) { + const auto& repfield = this->_internal_extension(i); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite:: + InternalWriteMessage(7, repfield, repfield.GetCachedSize(), target, stream); + } + + // optional .google.protobuf.FileOptions options = 8; + if (cached_has_bits & 0x00000008u) { + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite:: + InternalWriteMessage(8, _Internal::options(this), + _Internal::options(this).GetCachedSize(), target, stream); + } + + // optional .google.protobuf.SourceCodeInfo source_code_info = 9; + if (cached_has_bits & 0x00000010u) { + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite:: + InternalWriteMessage(9, _Internal::source_code_info(this), + _Internal::source_code_info(this).GetCachedSize(), target, stream); + } + + // repeated int32 public_dependency = 10; + for (int i = 0, n = this->_internal_public_dependency_size(); i < n; i++) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteInt32ToArray(10, this->_internal_public_dependency(i), target); + } + + // repeated int32 weak_dependency = 11; + for (int i = 0, n = this->_internal_weak_dependency_size(); i < n; i++) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteInt32ToArray(11, this->_internal_weak_dependency(i), target); + } + + // optional string syntax = 12; + if (cached_has_bits & 0x00000004u) { + ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::VerifyUTF8StringNamedField( + this->_internal_syntax().data(), static_cast<int>(this->_internal_syntax().length()), + ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::SERIALIZE, + "google.protobuf.FileDescriptorProto.syntax"); + target = stream->WriteStringMaybeAliased( + 12, this->_internal_syntax(), target); + } + + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + target = ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( + _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.FileDescriptorProto) + return target; +} + +size_t FileDescriptorProto::ByteSizeLong() const { +// @@protoc_insertion_point(message_byte_size_start:google.protobuf.FileDescriptorProto) + size_t total_size = 0; + + uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + // repeated string dependency = 3; + total_size += 1 * + ::PROTOBUF_NAMESPACE_ID::internal::FromIntSize(_impl_.dependency_.size()); + for (int i = 0, n = _impl_.dependency_.size(); i < n; i++) { + total_size += ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize( + _impl_.dependency_.Get(i)); + } + + // repeated .google.protobuf.DescriptorProto message_type = 4; + total_size += 1UL * this->_internal_message_type_size(); + for (const auto& msg : this->_impl_.message_type_) { + total_size += + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::MessageSize(msg); + } + + // repeated .google.protobuf.EnumDescriptorProto enum_type = 5; + total_size += 1UL * this->_internal_enum_type_size(); + for (const auto& msg : this->_impl_.enum_type_) { + total_size += + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::MessageSize(msg); + } + + // repeated .google.protobuf.ServiceDescriptorProto service = 6; + total_size += 1UL * this->_internal_service_size(); + for (const auto& msg : this->_impl_.service_) { + total_size += + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::MessageSize(msg); + } + + // repeated .google.protobuf.FieldDescriptorProto extension = 7; + total_size += 1UL * this->_internal_extension_size(); + for (const auto& msg : this->_impl_.extension_) { + total_size += + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::MessageSize(msg); + } + + // repeated int32 public_dependency = 10; + { + size_t data_size = ::_pbi::WireFormatLite:: + Int32Size(this->_impl_.public_dependency_); + total_size += 1 * + ::_pbi::FromIntSize(this->_internal_public_dependency_size()); + total_size += data_size; + } + + // repeated int32 weak_dependency = 11; + { + size_t data_size = ::_pbi::WireFormatLite:: + Int32Size(this->_impl_.weak_dependency_); + total_size += 1 * + ::_pbi::FromIntSize(this->_internal_weak_dependency_size()); + total_size += data_size; + } + + cached_has_bits = _impl_._has_bits_[0]; + if (cached_has_bits & 0x0000001fu) { + // optional string name = 1; + if (cached_has_bits & 0x00000001u) { + total_size += 1 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize( + this->_internal_name()); + } + + // optional string package = 2; + if (cached_has_bits & 0x00000002u) { + total_size += 1 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize( + this->_internal_package()); + } + + // optional string syntax = 12; + if (cached_has_bits & 0x00000004u) { + total_size += 1 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize( + this->_internal_syntax()); + } + + // optional .google.protobuf.FileOptions options = 8; + if (cached_has_bits & 0x00000008u) { + total_size += 1 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::MessageSize( + *_impl_.options_); + } + + // optional .google.protobuf.SourceCodeInfo source_code_info = 9; + if (cached_has_bits & 0x00000010u) { + total_size += 1 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::MessageSize( + *_impl_.source_code_info_); + } + + } + return MaybeComputeUnknownFieldsSize(total_size, &_impl_._cached_size_); +} + +const ::PROTOBUF_NAMESPACE_ID::Message::ClassData FileDescriptorProto::_class_data_ = { + ::PROTOBUF_NAMESPACE_ID::Message::CopyWithSourceCheck, + FileDescriptorProto::MergeImpl +}; +const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*FileDescriptorProto::GetClassData() const { return &_class_data_; } + + +void FileDescriptorProto::MergeImpl(::PROTOBUF_NAMESPACE_ID::Message& to_msg, const ::PROTOBUF_NAMESPACE_ID::Message& from_msg) { + auto* const _this = static_cast<FileDescriptorProto*>(&to_msg); + auto& from = static_cast<const FileDescriptorProto&>(from_msg); + // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.FileDescriptorProto) + GOOGLE_DCHECK_NE(&from, _this); + uint32_t cached_has_bits = 0; + (void) cached_has_bits; + + _this->_impl_.dependency_.MergeFrom(from._impl_.dependency_); + _this->_impl_.message_type_.MergeFrom(from._impl_.message_type_); + _this->_impl_.enum_type_.MergeFrom(from._impl_.enum_type_); + _this->_impl_.service_.MergeFrom(from._impl_.service_); + _this->_impl_.extension_.MergeFrom(from._impl_.extension_); + _this->_impl_.public_dependency_.MergeFrom(from._impl_.public_dependency_); + _this->_impl_.weak_dependency_.MergeFrom(from._impl_.weak_dependency_); + cached_has_bits = from._impl_._has_bits_[0]; + if (cached_has_bits & 0x0000001fu) { + if (cached_has_bits & 0x00000001u) { + _this->_internal_set_name(from._internal_name()); + } + if (cached_has_bits & 0x00000002u) { + _this->_internal_set_package(from._internal_package()); + } + if (cached_has_bits & 0x00000004u) { + _this->_internal_set_syntax(from._internal_syntax()); + } + if (cached_has_bits & 0x00000008u) { + _this->_internal_mutable_options()->::PROTOBUF_NAMESPACE_ID::FileOptions::MergeFrom( + from._internal_options()); + } + if (cached_has_bits & 0x00000010u) { + _this->_internal_mutable_source_code_info()->::PROTOBUF_NAMESPACE_ID::SourceCodeInfo::MergeFrom( + from._internal_source_code_info()); + } + } + _this->_internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); +} + +void FileDescriptorProto::CopyFrom(const FileDescriptorProto& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.FileDescriptorProto) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool FileDescriptorProto::IsInitialized() const { + if (!::PROTOBUF_NAMESPACE_ID::internal::AllAreInitialized(_impl_.message_type_)) + return false; + if (!::PROTOBUF_NAMESPACE_ID::internal::AllAreInitialized(_impl_.enum_type_)) + return false; + if (!::PROTOBUF_NAMESPACE_ID::internal::AllAreInitialized(_impl_.service_)) + return false; + if (!::PROTOBUF_NAMESPACE_ID::internal::AllAreInitialized(_impl_.extension_)) + return false; + if (_internal_has_options()) { + if (!_impl_.options_->IsInitialized()) return false; + } + return true; +} + +void FileDescriptorProto::InternalSwap(FileDescriptorProto* other) { + using std::swap; + auto* lhs_arena = GetArenaForAllocation(); + auto* rhs_arena = other->GetArenaForAllocation(); + _internal_metadata_.InternalSwap(&other->_internal_metadata_); + swap(_impl_._has_bits_[0], other->_impl_._has_bits_[0]); + _impl_.dependency_.InternalSwap(&other->_impl_.dependency_); + _impl_.message_type_.InternalSwap(&other->_impl_.message_type_); + _impl_.enum_type_.InternalSwap(&other->_impl_.enum_type_); + _impl_.service_.InternalSwap(&other->_impl_.service_); + _impl_.extension_.InternalSwap(&other->_impl_.extension_); + _impl_.public_dependency_.InternalSwap(&other->_impl_.public_dependency_); + _impl_.weak_dependency_.InternalSwap(&other->_impl_.weak_dependency_); + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::InternalSwap( + &_impl_.name_, lhs_arena, + &other->_impl_.name_, rhs_arena + ); + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::InternalSwap( + &_impl_.package_, lhs_arena, + &other->_impl_.package_, rhs_arena + ); + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::InternalSwap( + &_impl_.syntax_, lhs_arena, + &other->_impl_.syntax_, rhs_arena + ); + ::PROTOBUF_NAMESPACE_ID::internal::memswap< + PROTOBUF_FIELD_OFFSET(FileDescriptorProto, _impl_.source_code_info_) + + sizeof(FileDescriptorProto::_impl_.source_code_info_) + - PROTOBUF_FIELD_OFFSET(FileDescriptorProto, _impl_.options_)>( + reinterpret_cast<char*>(&_impl_.options_), + reinterpret_cast<char*>(&other->_impl_.options_)); +} + +::PROTOBUF_NAMESPACE_ID::Metadata FileDescriptorProto::GetMetadata() const { + return ::_pbi::AssignDescriptors( + &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_getter, &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_once, + file_level_metadata_google_2fprotobuf_2fdescriptor_2eproto[1]); +} + +// =================================================================== + +class DescriptorProto_ExtensionRange::_Internal { + public: + using HasBits = decltype(std::declval<DescriptorProto_ExtensionRange>()._impl_._has_bits_); + static void set_has_start(HasBits* has_bits) { + (*has_bits)[0] |= 2u; + } + static void set_has_end(HasBits* has_bits) { + (*has_bits)[0] |= 4u; + } + static const ::PROTOBUF_NAMESPACE_ID::ExtensionRangeOptions& options(const DescriptorProto_ExtensionRange* msg); + static void set_has_options(HasBits* has_bits) { + (*has_bits)[0] |= 1u; + } +}; + +const ::PROTOBUF_NAMESPACE_ID::ExtensionRangeOptions& +DescriptorProto_ExtensionRange::_Internal::options(const DescriptorProto_ExtensionRange* msg) { + return *msg->_impl_.options_; +} +DescriptorProto_ExtensionRange::DescriptorProto_ExtensionRange(::PROTOBUF_NAMESPACE_ID::Arena* arena, + bool is_message_owned) + : ::PROTOBUF_NAMESPACE_ID::Message(arena, is_message_owned) { + SharedCtor(arena, is_message_owned); + // @@protoc_insertion_point(arena_constructor:google.protobuf.DescriptorProto.ExtensionRange) +} +DescriptorProto_ExtensionRange::DescriptorProto_ExtensionRange(const DescriptorProto_ExtensionRange& from) + : ::PROTOBUF_NAMESPACE_ID::Message() { + DescriptorProto_ExtensionRange* const _this = this; (void)_this; + new (&_impl_) Impl_{ + decltype(_impl_._has_bits_){from._impl_._has_bits_} + , /*decltype(_impl_._cached_size_)*/{} + , decltype(_impl_.options_){nullptr} + , decltype(_impl_.start_){} + , decltype(_impl_.end_){}}; + + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); + if (from._internal_has_options()) { + _this->_impl_.options_ = new ::PROTOBUF_NAMESPACE_ID::ExtensionRangeOptions(*from._impl_.options_); + } + ::memcpy(&_impl_.start_, &from._impl_.start_, + static_cast<size_t>(reinterpret_cast<char*>(&_impl_.end_) - + reinterpret_cast<char*>(&_impl_.start_)) + sizeof(_impl_.end_)); + // @@protoc_insertion_point(copy_constructor:google.protobuf.DescriptorProto.ExtensionRange) +} + +inline void DescriptorProto_ExtensionRange::SharedCtor( + ::_pb::Arena* arena, bool is_message_owned) { + (void)arena; + (void)is_message_owned; + new (&_impl_) Impl_{ + decltype(_impl_._has_bits_){} + , /*decltype(_impl_._cached_size_)*/{} + , decltype(_impl_.options_){nullptr} + , decltype(_impl_.start_){0} + , decltype(_impl_.end_){0} + }; +} + +DescriptorProto_ExtensionRange::~DescriptorProto_ExtensionRange() { + // @@protoc_insertion_point(destructor:google.protobuf.DescriptorProto.ExtensionRange) + if (auto *arena = _internal_metadata_.DeleteReturnArena<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>()) { + (void)arena; + return; + } + SharedDtor(); +} + +inline void DescriptorProto_ExtensionRange::SharedDtor() { + GOOGLE_DCHECK(GetArenaForAllocation() == nullptr); + if (this != internal_default_instance()) delete _impl_.options_; +} + +void DescriptorProto_ExtensionRange::SetCachedSize(int size) const { + _impl_._cached_size_.Set(size); +} + +void DescriptorProto_ExtensionRange::Clear() { +// @@protoc_insertion_point(message_clear_start:google.protobuf.DescriptorProto.ExtensionRange) + uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + cached_has_bits = _impl_._has_bits_[0]; + if (cached_has_bits & 0x00000001u) { + GOOGLE_DCHECK(_impl_.options_ != nullptr); + _impl_.options_->Clear(); + } + if (cached_has_bits & 0x00000006u) { + ::memset(&_impl_.start_, 0, static_cast<size_t>( + reinterpret_cast<char*>(&_impl_.end_) - + reinterpret_cast<char*>(&_impl_.start_)) + sizeof(_impl_.end_)); + } + _impl_._has_bits_.Clear(); + _internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); +} + +const char* DescriptorProto_ExtensionRange::_InternalParse(const char* ptr, ::_pbi::ParseContext* ctx) { +#define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure + _Internal::HasBits has_bits{}; + while (!ctx->Done(&ptr)) { + uint32_t tag; + ptr = ::_pbi::ReadTag(ptr, &tag); + switch (tag >> 3) { + // optional int32 start = 1; + case 1: + if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 8)) { + _Internal::set_has_start(&has_bits); + _impl_.start_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint32(&ptr); + CHK_(ptr); + } else + goto handle_unusual; + continue; + // optional int32 end = 2; + case 2: + if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 16)) { + _Internal::set_has_end(&has_bits); + _impl_.end_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint32(&ptr); + CHK_(ptr); + } else + goto handle_unusual; + continue; + // optional .google.protobuf.ExtensionRangeOptions options = 3; + case 3: + if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 26)) { + ptr = ctx->ParseMessage(_internal_mutable_options(), ptr); + CHK_(ptr); + } else + goto handle_unusual; + continue; + default: + goto handle_unusual; + } // switch + handle_unusual: + if ((tag == 0) || ((tag & 7) == 4)) { + CHK_(ptr); + ctx->SetLastTag(tag); + goto message_done; + } + ptr = UnknownFieldParse( + tag, + _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(), + ptr, ctx); + CHK_(ptr != nullptr); + } // while +message_done: + _impl_._has_bits_.Or(has_bits); + return ptr; +failure: + ptr = nullptr; + goto message_done; +#undef CHK_ +} + +uint8_t* DescriptorProto_ExtensionRange::_InternalSerialize( + uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const { + // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.DescriptorProto.ExtensionRange) + uint32_t cached_has_bits = 0; + (void) cached_has_bits; + + cached_has_bits = _impl_._has_bits_[0]; + // optional int32 start = 1; + if (cached_has_bits & 0x00000002u) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteInt32ToArray(1, this->_internal_start(), target); + } + + // optional int32 end = 2; + if (cached_has_bits & 0x00000004u) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteInt32ToArray(2, this->_internal_end(), target); + } + + // optional .google.protobuf.ExtensionRangeOptions options = 3; + if (cached_has_bits & 0x00000001u) { + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite:: + InternalWriteMessage(3, _Internal::options(this), + _Internal::options(this).GetCachedSize(), target, stream); + } + + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + target = ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( + _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.DescriptorProto.ExtensionRange) + return target; +} + +size_t DescriptorProto_ExtensionRange::ByteSizeLong() const { +// @@protoc_insertion_point(message_byte_size_start:google.protobuf.DescriptorProto.ExtensionRange) + size_t total_size = 0; + + uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + cached_has_bits = _impl_._has_bits_[0]; + if (cached_has_bits & 0x00000007u) { + // optional .google.protobuf.ExtensionRangeOptions options = 3; + if (cached_has_bits & 0x00000001u) { + total_size += 1 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::MessageSize( + *_impl_.options_); + } + + // optional int32 start = 1; + if (cached_has_bits & 0x00000002u) { + total_size += ::_pbi::WireFormatLite::Int32SizePlusOne(this->_internal_start()); + } + + // optional int32 end = 2; + if (cached_has_bits & 0x00000004u) { + total_size += ::_pbi::WireFormatLite::Int32SizePlusOne(this->_internal_end()); + } + + } + return MaybeComputeUnknownFieldsSize(total_size, &_impl_._cached_size_); +} + +const ::PROTOBUF_NAMESPACE_ID::Message::ClassData DescriptorProto_ExtensionRange::_class_data_ = { + ::PROTOBUF_NAMESPACE_ID::Message::CopyWithSourceCheck, + DescriptorProto_ExtensionRange::MergeImpl +}; +const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*DescriptorProto_ExtensionRange::GetClassData() const { return &_class_data_; } + + +void DescriptorProto_ExtensionRange::MergeImpl(::PROTOBUF_NAMESPACE_ID::Message& to_msg, const ::PROTOBUF_NAMESPACE_ID::Message& from_msg) { + auto* const _this = static_cast<DescriptorProto_ExtensionRange*>(&to_msg); + auto& from = static_cast<const DescriptorProto_ExtensionRange&>(from_msg); + // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.DescriptorProto.ExtensionRange) + GOOGLE_DCHECK_NE(&from, _this); + uint32_t cached_has_bits = 0; + (void) cached_has_bits; + + cached_has_bits = from._impl_._has_bits_[0]; + if (cached_has_bits & 0x00000007u) { + if (cached_has_bits & 0x00000001u) { + _this->_internal_mutable_options()->::PROTOBUF_NAMESPACE_ID::ExtensionRangeOptions::MergeFrom( + from._internal_options()); + } + if (cached_has_bits & 0x00000002u) { + _this->_impl_.start_ = from._impl_.start_; + } + if (cached_has_bits & 0x00000004u) { + _this->_impl_.end_ = from._impl_.end_; + } + _this->_impl_._has_bits_[0] |= cached_has_bits; + } + _this->_internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); +} + +void DescriptorProto_ExtensionRange::CopyFrom(const DescriptorProto_ExtensionRange& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.DescriptorProto.ExtensionRange) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool DescriptorProto_ExtensionRange::IsInitialized() const { + if (_internal_has_options()) { + if (!_impl_.options_->IsInitialized()) return false; + } + return true; +} + +void DescriptorProto_ExtensionRange::InternalSwap(DescriptorProto_ExtensionRange* other) { + using std::swap; + _internal_metadata_.InternalSwap(&other->_internal_metadata_); + swap(_impl_._has_bits_[0], other->_impl_._has_bits_[0]); + ::PROTOBUF_NAMESPACE_ID::internal::memswap< + PROTOBUF_FIELD_OFFSET(DescriptorProto_ExtensionRange, _impl_.end_) + + sizeof(DescriptorProto_ExtensionRange::_impl_.end_) + - PROTOBUF_FIELD_OFFSET(DescriptorProto_ExtensionRange, _impl_.options_)>( + reinterpret_cast<char*>(&_impl_.options_), + reinterpret_cast<char*>(&other->_impl_.options_)); +} + +::PROTOBUF_NAMESPACE_ID::Metadata DescriptorProto_ExtensionRange::GetMetadata() const { + return ::_pbi::AssignDescriptors( + &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_getter, &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_once, + file_level_metadata_google_2fprotobuf_2fdescriptor_2eproto[2]); +} + +// =================================================================== + +class DescriptorProto_ReservedRange::_Internal { + public: + using HasBits = decltype(std::declval<DescriptorProto_ReservedRange>()._impl_._has_bits_); + static void set_has_start(HasBits* has_bits) { + (*has_bits)[0] |= 1u; + } + static void set_has_end(HasBits* has_bits) { + (*has_bits)[0] |= 2u; + } +}; + +DescriptorProto_ReservedRange::DescriptorProto_ReservedRange(::PROTOBUF_NAMESPACE_ID::Arena* arena, + bool is_message_owned) + : ::PROTOBUF_NAMESPACE_ID::Message(arena, is_message_owned) { + SharedCtor(arena, is_message_owned); + // @@protoc_insertion_point(arena_constructor:google.protobuf.DescriptorProto.ReservedRange) +} +DescriptorProto_ReservedRange::DescriptorProto_ReservedRange(const DescriptorProto_ReservedRange& from) + : ::PROTOBUF_NAMESPACE_ID::Message() { + DescriptorProto_ReservedRange* const _this = this; (void)_this; + new (&_impl_) Impl_{ + decltype(_impl_._has_bits_){from._impl_._has_bits_} + , /*decltype(_impl_._cached_size_)*/{} + , decltype(_impl_.start_){} + , decltype(_impl_.end_){}}; + + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); + ::memcpy(&_impl_.start_, &from._impl_.start_, + static_cast<size_t>(reinterpret_cast<char*>(&_impl_.end_) - + reinterpret_cast<char*>(&_impl_.start_)) + sizeof(_impl_.end_)); + // @@protoc_insertion_point(copy_constructor:google.protobuf.DescriptorProto.ReservedRange) +} + +inline void DescriptorProto_ReservedRange::SharedCtor( + ::_pb::Arena* arena, bool is_message_owned) { + (void)arena; + (void)is_message_owned; + new (&_impl_) Impl_{ + decltype(_impl_._has_bits_){} + , /*decltype(_impl_._cached_size_)*/{} + , decltype(_impl_.start_){0} + , decltype(_impl_.end_){0} + }; +} + +DescriptorProto_ReservedRange::~DescriptorProto_ReservedRange() { + // @@protoc_insertion_point(destructor:google.protobuf.DescriptorProto.ReservedRange) + if (auto *arena = _internal_metadata_.DeleteReturnArena<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>()) { + (void)arena; + return; + } + SharedDtor(); +} + +inline void DescriptorProto_ReservedRange::SharedDtor() { + GOOGLE_DCHECK(GetArenaForAllocation() == nullptr); +} + +void DescriptorProto_ReservedRange::SetCachedSize(int size) const { + _impl_._cached_size_.Set(size); +} + +void DescriptorProto_ReservedRange::Clear() { +// @@protoc_insertion_point(message_clear_start:google.protobuf.DescriptorProto.ReservedRange) + uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + cached_has_bits = _impl_._has_bits_[0]; + if (cached_has_bits & 0x00000003u) { + ::memset(&_impl_.start_, 0, static_cast<size_t>( + reinterpret_cast<char*>(&_impl_.end_) - + reinterpret_cast<char*>(&_impl_.start_)) + sizeof(_impl_.end_)); + } + _impl_._has_bits_.Clear(); + _internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); +} + +const char* DescriptorProto_ReservedRange::_InternalParse(const char* ptr, ::_pbi::ParseContext* ctx) { +#define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure + _Internal::HasBits has_bits{}; + while (!ctx->Done(&ptr)) { + uint32_t tag; + ptr = ::_pbi::ReadTag(ptr, &tag); + switch (tag >> 3) { + // optional int32 start = 1; + case 1: + if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 8)) { + _Internal::set_has_start(&has_bits); + _impl_.start_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint32(&ptr); + CHK_(ptr); + } else + goto handle_unusual; + continue; + // optional int32 end = 2; + case 2: + if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 16)) { + _Internal::set_has_end(&has_bits); + _impl_.end_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint32(&ptr); + CHK_(ptr); + } else + goto handle_unusual; + continue; + default: + goto handle_unusual; + } // switch + handle_unusual: + if ((tag == 0) || ((tag & 7) == 4)) { + CHK_(ptr); + ctx->SetLastTag(tag); + goto message_done; + } + ptr = UnknownFieldParse( + tag, + _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(), + ptr, ctx); + CHK_(ptr != nullptr); + } // while +message_done: + _impl_._has_bits_.Or(has_bits); + return ptr; +failure: + ptr = nullptr; + goto message_done; +#undef CHK_ +} + +uint8_t* DescriptorProto_ReservedRange::_InternalSerialize( + uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const { + // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.DescriptorProto.ReservedRange) + uint32_t cached_has_bits = 0; + (void) cached_has_bits; + + cached_has_bits = _impl_._has_bits_[0]; + // optional int32 start = 1; + if (cached_has_bits & 0x00000001u) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteInt32ToArray(1, this->_internal_start(), target); + } + + // optional int32 end = 2; + if (cached_has_bits & 0x00000002u) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteInt32ToArray(2, this->_internal_end(), target); + } + + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + target = ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( + _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.DescriptorProto.ReservedRange) + return target; +} + +size_t DescriptorProto_ReservedRange::ByteSizeLong() const { +// @@protoc_insertion_point(message_byte_size_start:google.protobuf.DescriptorProto.ReservedRange) + size_t total_size = 0; + + uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + cached_has_bits = _impl_._has_bits_[0]; + if (cached_has_bits & 0x00000003u) { + // optional int32 start = 1; + if (cached_has_bits & 0x00000001u) { + total_size += ::_pbi::WireFormatLite::Int32SizePlusOne(this->_internal_start()); + } + + // optional int32 end = 2; + if (cached_has_bits & 0x00000002u) { + total_size += ::_pbi::WireFormatLite::Int32SizePlusOne(this->_internal_end()); + } + + } + return MaybeComputeUnknownFieldsSize(total_size, &_impl_._cached_size_); +} + +const ::PROTOBUF_NAMESPACE_ID::Message::ClassData DescriptorProto_ReservedRange::_class_data_ = { + ::PROTOBUF_NAMESPACE_ID::Message::CopyWithSourceCheck, + DescriptorProto_ReservedRange::MergeImpl +}; +const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*DescriptorProto_ReservedRange::GetClassData() const { return &_class_data_; } + + +void DescriptorProto_ReservedRange::MergeImpl(::PROTOBUF_NAMESPACE_ID::Message& to_msg, const ::PROTOBUF_NAMESPACE_ID::Message& from_msg) { + auto* const _this = static_cast<DescriptorProto_ReservedRange*>(&to_msg); + auto& from = static_cast<const DescriptorProto_ReservedRange&>(from_msg); + // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.DescriptorProto.ReservedRange) + GOOGLE_DCHECK_NE(&from, _this); + uint32_t cached_has_bits = 0; + (void) cached_has_bits; + + cached_has_bits = from._impl_._has_bits_[0]; + if (cached_has_bits & 0x00000003u) { + if (cached_has_bits & 0x00000001u) { + _this->_impl_.start_ = from._impl_.start_; + } + if (cached_has_bits & 0x00000002u) { + _this->_impl_.end_ = from._impl_.end_; + } + _this->_impl_._has_bits_[0] |= cached_has_bits; + } + _this->_internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); +} + +void DescriptorProto_ReservedRange::CopyFrom(const DescriptorProto_ReservedRange& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.DescriptorProto.ReservedRange) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool DescriptorProto_ReservedRange::IsInitialized() const { + return true; +} + +void DescriptorProto_ReservedRange::InternalSwap(DescriptorProto_ReservedRange* other) { + using std::swap; + _internal_metadata_.InternalSwap(&other->_internal_metadata_); + swap(_impl_._has_bits_[0], other->_impl_._has_bits_[0]); + ::PROTOBUF_NAMESPACE_ID::internal::memswap< + PROTOBUF_FIELD_OFFSET(DescriptorProto_ReservedRange, _impl_.end_) + + sizeof(DescriptorProto_ReservedRange::_impl_.end_) + - PROTOBUF_FIELD_OFFSET(DescriptorProto_ReservedRange, _impl_.start_)>( + reinterpret_cast<char*>(&_impl_.start_), + reinterpret_cast<char*>(&other->_impl_.start_)); +} + +::PROTOBUF_NAMESPACE_ID::Metadata DescriptorProto_ReservedRange::GetMetadata() const { + return ::_pbi::AssignDescriptors( + &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_getter, &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_once, + file_level_metadata_google_2fprotobuf_2fdescriptor_2eproto[3]); +} + +// =================================================================== + +class DescriptorProto::_Internal { + public: + using HasBits = decltype(std::declval<DescriptorProto>()._impl_._has_bits_); + static void set_has_name(HasBits* has_bits) { + (*has_bits)[0] |= 1u; + } + static const ::PROTOBUF_NAMESPACE_ID::MessageOptions& options(const DescriptorProto* msg); + static void set_has_options(HasBits* has_bits) { + (*has_bits)[0] |= 2u; + } +}; + +const ::PROTOBUF_NAMESPACE_ID::MessageOptions& +DescriptorProto::_Internal::options(const DescriptorProto* msg) { + return *msg->_impl_.options_; +} +DescriptorProto::DescriptorProto(::PROTOBUF_NAMESPACE_ID::Arena* arena, + bool is_message_owned) + : ::PROTOBUF_NAMESPACE_ID::Message(arena, is_message_owned) { + SharedCtor(arena, is_message_owned); + // @@protoc_insertion_point(arena_constructor:google.protobuf.DescriptorProto) +} +DescriptorProto::DescriptorProto(const DescriptorProto& from) + : ::PROTOBUF_NAMESPACE_ID::Message() { + DescriptorProto* const _this = this; (void)_this; + new (&_impl_) Impl_{ + decltype(_impl_._has_bits_){from._impl_._has_bits_} + , /*decltype(_impl_._cached_size_)*/{} + , decltype(_impl_.field_){from._impl_.field_} + , decltype(_impl_.nested_type_){from._impl_.nested_type_} + , decltype(_impl_.enum_type_){from._impl_.enum_type_} + , decltype(_impl_.extension_range_){from._impl_.extension_range_} + , decltype(_impl_.extension_){from._impl_.extension_} + , decltype(_impl_.oneof_decl_){from._impl_.oneof_decl_} + , decltype(_impl_.reserved_range_){from._impl_.reserved_range_} + , decltype(_impl_.reserved_name_){from._impl_.reserved_name_} + , decltype(_impl_.name_){} + , decltype(_impl_.options_){nullptr}}; + + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); + _impl_.name_.InitDefault(); + #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + _impl_.name_.Set("", GetArenaForAllocation()); + #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (from._internal_has_name()) { + _this->_impl_.name_.Set(from._internal_name(), + _this->GetArenaForAllocation()); + } + if (from._internal_has_options()) { + _this->_impl_.options_ = new ::PROTOBUF_NAMESPACE_ID::MessageOptions(*from._impl_.options_); + } + // @@protoc_insertion_point(copy_constructor:google.protobuf.DescriptorProto) +} + +inline void DescriptorProto::SharedCtor( + ::_pb::Arena* arena, bool is_message_owned) { + (void)arena; + (void)is_message_owned; + new (&_impl_) Impl_{ + decltype(_impl_._has_bits_){} + , /*decltype(_impl_._cached_size_)*/{} + , decltype(_impl_.field_){arena} + , decltype(_impl_.nested_type_){arena} + , decltype(_impl_.enum_type_){arena} + , decltype(_impl_.extension_range_){arena} + , decltype(_impl_.extension_){arena} + , decltype(_impl_.oneof_decl_){arena} + , decltype(_impl_.reserved_range_){arena} + , decltype(_impl_.reserved_name_){arena} + , decltype(_impl_.name_){} + , decltype(_impl_.options_){nullptr} + }; + _impl_.name_.InitDefault(); + #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + _impl_.name_.Set("", GetArenaForAllocation()); + #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING +} + +DescriptorProto::~DescriptorProto() { + // @@protoc_insertion_point(destructor:google.protobuf.DescriptorProto) + if (auto *arena = _internal_metadata_.DeleteReturnArena<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>()) { + (void)arena; + return; + } + SharedDtor(); +} + +inline void DescriptorProto::SharedDtor() { + GOOGLE_DCHECK(GetArenaForAllocation() == nullptr); + _impl_.field_.~RepeatedPtrField(); + _impl_.nested_type_.~RepeatedPtrField(); + _impl_.enum_type_.~RepeatedPtrField(); + _impl_.extension_range_.~RepeatedPtrField(); + _impl_.extension_.~RepeatedPtrField(); + _impl_.oneof_decl_.~RepeatedPtrField(); + _impl_.reserved_range_.~RepeatedPtrField(); + _impl_.reserved_name_.~RepeatedPtrField(); + _impl_.name_.Destroy(); + if (this != internal_default_instance()) delete _impl_.options_; +} + +void DescriptorProto::SetCachedSize(int size) const { + _impl_._cached_size_.Set(size); +} + +void DescriptorProto::Clear() { +// @@protoc_insertion_point(message_clear_start:google.protobuf.DescriptorProto) + uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + _impl_.field_.Clear(); + _impl_.nested_type_.Clear(); + _impl_.enum_type_.Clear(); + _impl_.extension_range_.Clear(); + _impl_.extension_.Clear(); + _impl_.oneof_decl_.Clear(); + _impl_.reserved_range_.Clear(); + _impl_.reserved_name_.Clear(); + cached_has_bits = _impl_._has_bits_[0]; + if (cached_has_bits & 0x00000003u) { + if (cached_has_bits & 0x00000001u) { + _impl_.name_.ClearNonDefaultToEmpty(); + } + if (cached_has_bits & 0x00000002u) { + GOOGLE_DCHECK(_impl_.options_ != nullptr); + _impl_.options_->Clear(); + } + } + _impl_._has_bits_.Clear(); + _internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); +} + +const char* DescriptorProto::_InternalParse(const char* ptr, ::_pbi::ParseContext* ctx) { +#define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure + _Internal::HasBits has_bits{}; + while (!ctx->Done(&ptr)) { + uint32_t tag; + ptr = ::_pbi::ReadTag(ptr, &tag); + switch (tag >> 3) { + // optional string name = 1; + case 1: + if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 10)) { + auto str = _internal_mutable_name(); + ptr = ::_pbi::InlineGreedyStringParser(str, ptr, ctx); + CHK_(ptr); + #ifndef NDEBUG + ::_pbi::VerifyUTF8(str, "google.protobuf.DescriptorProto.name"); + #endif // !NDEBUG + } else + goto handle_unusual; + continue; + // repeated .google.protobuf.FieldDescriptorProto field = 2; + case 2: + if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 18)) { + ptr -= 1; + do { + ptr += 1; + ptr = ctx->ParseMessage(_internal_add_field(), ptr); + CHK_(ptr); + if (!ctx->DataAvailable(ptr)) break; + } while (::PROTOBUF_NAMESPACE_ID::internal::ExpectTag<18>(ptr)); + } else + goto handle_unusual; + continue; + // repeated .google.protobuf.DescriptorProto nested_type = 3; + case 3: + if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 26)) { + ptr -= 1; + do { + ptr += 1; + ptr = ctx->ParseMessage(_internal_add_nested_type(), ptr); + CHK_(ptr); + if (!ctx->DataAvailable(ptr)) break; + } while (::PROTOBUF_NAMESPACE_ID::internal::ExpectTag<26>(ptr)); + } else + goto handle_unusual; + continue; + // repeated .google.protobuf.EnumDescriptorProto enum_type = 4; + case 4: + if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 34)) { + ptr -= 1; + do { + ptr += 1; + ptr = ctx->ParseMessage(_internal_add_enum_type(), ptr); + CHK_(ptr); + if (!ctx->DataAvailable(ptr)) break; + } while (::PROTOBUF_NAMESPACE_ID::internal::ExpectTag<34>(ptr)); + } else + goto handle_unusual; + continue; + // repeated .google.protobuf.DescriptorProto.ExtensionRange extension_range = 5; + case 5: + if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 42)) { + ptr -= 1; + do { + ptr += 1; + ptr = ctx->ParseMessage(_internal_add_extension_range(), ptr); + CHK_(ptr); + if (!ctx->DataAvailable(ptr)) break; + } while (::PROTOBUF_NAMESPACE_ID::internal::ExpectTag<42>(ptr)); + } else + goto handle_unusual; + continue; + // repeated .google.protobuf.FieldDescriptorProto extension = 6; + case 6: + if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 50)) { + ptr -= 1; + do { + ptr += 1; + ptr = ctx->ParseMessage(_internal_add_extension(), ptr); + CHK_(ptr); + if (!ctx->DataAvailable(ptr)) break; + } while (::PROTOBUF_NAMESPACE_ID::internal::ExpectTag<50>(ptr)); + } else + goto handle_unusual; + continue; + // optional .google.protobuf.MessageOptions options = 7; + case 7: + if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 58)) { + ptr = ctx->ParseMessage(_internal_mutable_options(), ptr); + CHK_(ptr); + } else + goto handle_unusual; + continue; + // repeated .google.protobuf.OneofDescriptorProto oneof_decl = 8; + case 8: + if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 66)) { + ptr -= 1; + do { + ptr += 1; + ptr = ctx->ParseMessage(_internal_add_oneof_decl(), ptr); + CHK_(ptr); + if (!ctx->DataAvailable(ptr)) break; + } while (::PROTOBUF_NAMESPACE_ID::internal::ExpectTag<66>(ptr)); + } else + goto handle_unusual; + continue; + // repeated .google.protobuf.DescriptorProto.ReservedRange reserved_range = 9; + case 9: + if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 74)) { + ptr -= 1; + do { + ptr += 1; + ptr = ctx->ParseMessage(_internal_add_reserved_range(), ptr); + CHK_(ptr); + if (!ctx->DataAvailable(ptr)) break; + } while (::PROTOBUF_NAMESPACE_ID::internal::ExpectTag<74>(ptr)); + } else + goto handle_unusual; + continue; + // repeated string reserved_name = 10; + case 10: + if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 82)) { + ptr -= 1; + do { + ptr += 1; + auto str = _internal_add_reserved_name(); + ptr = ::_pbi::InlineGreedyStringParser(str, ptr, ctx); + CHK_(ptr); + #ifndef NDEBUG + ::_pbi::VerifyUTF8(str, "google.protobuf.DescriptorProto.reserved_name"); + #endif // !NDEBUG + if (!ctx->DataAvailable(ptr)) break; + } while (::PROTOBUF_NAMESPACE_ID::internal::ExpectTag<82>(ptr)); + } else + goto handle_unusual; + continue; + default: + goto handle_unusual; + } // switch + handle_unusual: + if ((tag == 0) || ((tag & 7) == 4)) { + CHK_(ptr); + ctx->SetLastTag(tag); + goto message_done; + } + ptr = UnknownFieldParse( + tag, + _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(), + ptr, ctx); + CHK_(ptr != nullptr); + } // while +message_done: + _impl_._has_bits_.Or(has_bits); + return ptr; +failure: + ptr = nullptr; + goto message_done; +#undef CHK_ +} + +uint8_t* DescriptorProto::_InternalSerialize( + uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const { + // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.DescriptorProto) + uint32_t cached_has_bits = 0; + (void) cached_has_bits; + + cached_has_bits = _impl_._has_bits_[0]; + // optional string name = 1; + if (cached_has_bits & 0x00000001u) { + ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::VerifyUTF8StringNamedField( + this->_internal_name().data(), static_cast<int>(this->_internal_name().length()), + ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::SERIALIZE, + "google.protobuf.DescriptorProto.name"); + target = stream->WriteStringMaybeAliased( + 1, this->_internal_name(), target); + } + + // repeated .google.protobuf.FieldDescriptorProto field = 2; + for (unsigned i = 0, + n = static_cast<unsigned>(this->_internal_field_size()); i < n; i++) { + const auto& repfield = this->_internal_field(i); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite:: + InternalWriteMessage(2, repfield, repfield.GetCachedSize(), target, stream); + } + + // repeated .google.protobuf.DescriptorProto nested_type = 3; + for (unsigned i = 0, + n = static_cast<unsigned>(this->_internal_nested_type_size()); i < n; i++) { + const auto& repfield = this->_internal_nested_type(i); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite:: + InternalWriteMessage(3, repfield, repfield.GetCachedSize(), target, stream); + } + + // repeated .google.protobuf.EnumDescriptorProto enum_type = 4; + for (unsigned i = 0, + n = static_cast<unsigned>(this->_internal_enum_type_size()); i < n; i++) { + const auto& repfield = this->_internal_enum_type(i); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite:: + InternalWriteMessage(4, repfield, repfield.GetCachedSize(), target, stream); + } + + // repeated .google.protobuf.DescriptorProto.ExtensionRange extension_range = 5; + for (unsigned i = 0, + n = static_cast<unsigned>(this->_internal_extension_range_size()); i < n; i++) { + const auto& repfield = this->_internal_extension_range(i); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite:: + InternalWriteMessage(5, repfield, repfield.GetCachedSize(), target, stream); + } + + // repeated .google.protobuf.FieldDescriptorProto extension = 6; + for (unsigned i = 0, + n = static_cast<unsigned>(this->_internal_extension_size()); i < n; i++) { + const auto& repfield = this->_internal_extension(i); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite:: + InternalWriteMessage(6, repfield, repfield.GetCachedSize(), target, stream); + } + + // optional .google.protobuf.MessageOptions options = 7; + if (cached_has_bits & 0x00000002u) { + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite:: + InternalWriteMessage(7, _Internal::options(this), + _Internal::options(this).GetCachedSize(), target, stream); + } + + // repeated .google.protobuf.OneofDescriptorProto oneof_decl = 8; + for (unsigned i = 0, + n = static_cast<unsigned>(this->_internal_oneof_decl_size()); i < n; i++) { + const auto& repfield = this->_internal_oneof_decl(i); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite:: + InternalWriteMessage(8, repfield, repfield.GetCachedSize(), target, stream); + } + + // repeated .google.protobuf.DescriptorProto.ReservedRange reserved_range = 9; + for (unsigned i = 0, + n = static_cast<unsigned>(this->_internal_reserved_range_size()); i < n; i++) { + const auto& repfield = this->_internal_reserved_range(i); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite:: + InternalWriteMessage(9, repfield, repfield.GetCachedSize(), target, stream); + } + + // repeated string reserved_name = 10; + for (int i = 0, n = this->_internal_reserved_name_size(); i < n; i++) { + const auto& s = this->_internal_reserved_name(i); + ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::VerifyUTF8StringNamedField( + s.data(), static_cast<int>(s.length()), + ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::SERIALIZE, + "google.protobuf.DescriptorProto.reserved_name"); + target = stream->WriteString(10, s, target); + } + + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + target = ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( + _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.DescriptorProto) + return target; +} + +size_t DescriptorProto::ByteSizeLong() const { +// @@protoc_insertion_point(message_byte_size_start:google.protobuf.DescriptorProto) + size_t total_size = 0; + + uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + // repeated .google.protobuf.FieldDescriptorProto field = 2; + total_size += 1UL * this->_internal_field_size(); + for (const auto& msg : this->_impl_.field_) { + total_size += + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::MessageSize(msg); + } + + // repeated .google.protobuf.DescriptorProto nested_type = 3; + total_size += 1UL * this->_internal_nested_type_size(); + for (const auto& msg : this->_impl_.nested_type_) { + total_size += + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::MessageSize(msg); + } + + // repeated .google.protobuf.EnumDescriptorProto enum_type = 4; + total_size += 1UL * this->_internal_enum_type_size(); + for (const auto& msg : this->_impl_.enum_type_) { + total_size += + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::MessageSize(msg); + } + + // repeated .google.protobuf.DescriptorProto.ExtensionRange extension_range = 5; + total_size += 1UL * this->_internal_extension_range_size(); + for (const auto& msg : this->_impl_.extension_range_) { + total_size += + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::MessageSize(msg); + } + + // repeated .google.protobuf.FieldDescriptorProto extension = 6; + total_size += 1UL * this->_internal_extension_size(); + for (const auto& msg : this->_impl_.extension_) { + total_size += + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::MessageSize(msg); + } + + // repeated .google.protobuf.OneofDescriptorProto oneof_decl = 8; + total_size += 1UL * this->_internal_oneof_decl_size(); + for (const auto& msg : this->_impl_.oneof_decl_) { + total_size += + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::MessageSize(msg); + } + + // repeated .google.protobuf.DescriptorProto.ReservedRange reserved_range = 9; + total_size += 1UL * this->_internal_reserved_range_size(); + for (const auto& msg : this->_impl_.reserved_range_) { + total_size += + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::MessageSize(msg); + } + + // repeated string reserved_name = 10; + total_size += 1 * + ::PROTOBUF_NAMESPACE_ID::internal::FromIntSize(_impl_.reserved_name_.size()); + for (int i = 0, n = _impl_.reserved_name_.size(); i < n; i++) { + total_size += ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize( + _impl_.reserved_name_.Get(i)); + } + + cached_has_bits = _impl_._has_bits_[0]; + if (cached_has_bits & 0x00000003u) { + // optional string name = 1; + if (cached_has_bits & 0x00000001u) { + total_size += 1 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize( + this->_internal_name()); + } + + // optional .google.protobuf.MessageOptions options = 7; + if (cached_has_bits & 0x00000002u) { + total_size += 1 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::MessageSize( + *_impl_.options_); + } + + } + return MaybeComputeUnknownFieldsSize(total_size, &_impl_._cached_size_); +} + +const ::PROTOBUF_NAMESPACE_ID::Message::ClassData DescriptorProto::_class_data_ = { + ::PROTOBUF_NAMESPACE_ID::Message::CopyWithSourceCheck, + DescriptorProto::MergeImpl +}; +const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*DescriptorProto::GetClassData() const { return &_class_data_; } + + +void DescriptorProto::MergeImpl(::PROTOBUF_NAMESPACE_ID::Message& to_msg, const ::PROTOBUF_NAMESPACE_ID::Message& from_msg) { + auto* const _this = static_cast<DescriptorProto*>(&to_msg); + auto& from = static_cast<const DescriptorProto&>(from_msg); + // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.DescriptorProto) + GOOGLE_DCHECK_NE(&from, _this); + uint32_t cached_has_bits = 0; + (void) cached_has_bits; + + _this->_impl_.field_.MergeFrom(from._impl_.field_); + _this->_impl_.nested_type_.MergeFrom(from._impl_.nested_type_); + _this->_impl_.enum_type_.MergeFrom(from._impl_.enum_type_); + _this->_impl_.extension_range_.MergeFrom(from._impl_.extension_range_); + _this->_impl_.extension_.MergeFrom(from._impl_.extension_); + _this->_impl_.oneof_decl_.MergeFrom(from._impl_.oneof_decl_); + _this->_impl_.reserved_range_.MergeFrom(from._impl_.reserved_range_); + _this->_impl_.reserved_name_.MergeFrom(from._impl_.reserved_name_); + cached_has_bits = from._impl_._has_bits_[0]; + if (cached_has_bits & 0x00000003u) { + if (cached_has_bits & 0x00000001u) { + _this->_internal_set_name(from._internal_name()); + } + if (cached_has_bits & 0x00000002u) { + _this->_internal_mutable_options()->::PROTOBUF_NAMESPACE_ID::MessageOptions::MergeFrom( + from._internal_options()); + } + } + _this->_internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); +} + +void DescriptorProto::CopyFrom(const DescriptorProto& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.DescriptorProto) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool DescriptorProto::IsInitialized() const { + if (!::PROTOBUF_NAMESPACE_ID::internal::AllAreInitialized(_impl_.field_)) + return false; + if (!::PROTOBUF_NAMESPACE_ID::internal::AllAreInitialized(_impl_.nested_type_)) + return false; + if (!::PROTOBUF_NAMESPACE_ID::internal::AllAreInitialized(_impl_.enum_type_)) + return false; + if (!::PROTOBUF_NAMESPACE_ID::internal::AllAreInitialized(_impl_.extension_range_)) + return false; + if (!::PROTOBUF_NAMESPACE_ID::internal::AllAreInitialized(_impl_.extension_)) + return false; + if (!::PROTOBUF_NAMESPACE_ID::internal::AllAreInitialized(_impl_.oneof_decl_)) + return false; + if (_internal_has_options()) { + if (!_impl_.options_->IsInitialized()) return false; + } + return true; +} + +void DescriptorProto::InternalSwap(DescriptorProto* other) { + using std::swap; + auto* lhs_arena = GetArenaForAllocation(); + auto* rhs_arena = other->GetArenaForAllocation(); + _internal_metadata_.InternalSwap(&other->_internal_metadata_); + swap(_impl_._has_bits_[0], other->_impl_._has_bits_[0]); + _impl_.field_.InternalSwap(&other->_impl_.field_); + _impl_.nested_type_.InternalSwap(&other->_impl_.nested_type_); + _impl_.enum_type_.InternalSwap(&other->_impl_.enum_type_); + _impl_.extension_range_.InternalSwap(&other->_impl_.extension_range_); + _impl_.extension_.InternalSwap(&other->_impl_.extension_); + _impl_.oneof_decl_.InternalSwap(&other->_impl_.oneof_decl_); + _impl_.reserved_range_.InternalSwap(&other->_impl_.reserved_range_); + _impl_.reserved_name_.InternalSwap(&other->_impl_.reserved_name_); + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::InternalSwap( + &_impl_.name_, lhs_arena, + &other->_impl_.name_, rhs_arena + ); + swap(_impl_.options_, other->_impl_.options_); +} + +::PROTOBUF_NAMESPACE_ID::Metadata DescriptorProto::GetMetadata() const { + return ::_pbi::AssignDescriptors( + &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_getter, &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_once, + file_level_metadata_google_2fprotobuf_2fdescriptor_2eproto[4]); +} + +// =================================================================== + +class ExtensionRangeOptions::_Internal { + public: +}; + +ExtensionRangeOptions::ExtensionRangeOptions(::PROTOBUF_NAMESPACE_ID::Arena* arena, + bool is_message_owned) + : ::PROTOBUF_NAMESPACE_ID::Message(arena, is_message_owned) { + SharedCtor(arena, is_message_owned); + // @@protoc_insertion_point(arena_constructor:google.protobuf.ExtensionRangeOptions) +} +ExtensionRangeOptions::ExtensionRangeOptions(const ExtensionRangeOptions& from) + : ::PROTOBUF_NAMESPACE_ID::Message() { + ExtensionRangeOptions* const _this = this; (void)_this; + new (&_impl_) Impl_{ + /*decltype(_impl_._extensions_)*/{} + , decltype(_impl_.uninterpreted_option_){from._impl_.uninterpreted_option_} + , /*decltype(_impl_._cached_size_)*/{}}; + + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); + _impl_._extensions_.MergeFrom(internal_default_instance(), from._impl_._extensions_); + // @@protoc_insertion_point(copy_constructor:google.protobuf.ExtensionRangeOptions) +} + +inline void ExtensionRangeOptions::SharedCtor( + ::_pb::Arena* arena, bool is_message_owned) { + (void)arena; + (void)is_message_owned; + new (&_impl_) Impl_{ + /*decltype(_impl_._extensions_)*/{::_pbi::ArenaInitialized(), arena} + , decltype(_impl_.uninterpreted_option_){arena} + , /*decltype(_impl_._cached_size_)*/{} + }; +} + +ExtensionRangeOptions::~ExtensionRangeOptions() { + // @@protoc_insertion_point(destructor:google.protobuf.ExtensionRangeOptions) + if (auto *arena = _internal_metadata_.DeleteReturnArena<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>()) { + (void)arena; + return; + } + SharedDtor(); +} + +inline void ExtensionRangeOptions::SharedDtor() { + GOOGLE_DCHECK(GetArenaForAllocation() == nullptr); + _impl_._extensions_.~ExtensionSet(); + _impl_.uninterpreted_option_.~RepeatedPtrField(); +} + +void ExtensionRangeOptions::SetCachedSize(int size) const { + _impl_._cached_size_.Set(size); +} + +void ExtensionRangeOptions::Clear() { +// @@protoc_insertion_point(message_clear_start:google.protobuf.ExtensionRangeOptions) + uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + _impl_._extensions_.Clear(); + _impl_.uninterpreted_option_.Clear(); + _internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); +} + +const char* ExtensionRangeOptions::_InternalParse(const char* ptr, ::_pbi::ParseContext* ctx) { +#define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure + while (!ctx->Done(&ptr)) { + uint32_t tag; + ptr = ::_pbi::ReadTag(ptr, &tag); + switch (tag >> 3) { + // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; + case 999: + if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 58)) { + ptr -= 2; + do { + ptr += 2; + ptr = ctx->ParseMessage(_internal_add_uninterpreted_option(), ptr); + CHK_(ptr); + if (!ctx->DataAvailable(ptr)) break; + } while (::PROTOBUF_NAMESPACE_ID::internal::ExpectTag<7994>(ptr)); + } else + goto handle_unusual; + continue; + default: + goto handle_unusual; + } // switch + handle_unusual: + if ((tag == 0) || ((tag & 7) == 4)) { + CHK_(ptr); + ctx->SetLastTag(tag); + goto message_done; + } + if ((8000u <= tag)) { + ptr = _impl_._extensions_.ParseField(tag, ptr, internal_default_instance(), &_internal_metadata_, ctx); + CHK_(ptr != nullptr); + continue; + } + ptr = UnknownFieldParse( + tag, + _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(), + ptr, ctx); + CHK_(ptr != nullptr); + } // while +message_done: + return ptr; +failure: + ptr = nullptr; + goto message_done; +#undef CHK_ +} + +uint8_t* ExtensionRangeOptions::_InternalSerialize( + uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const { + // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.ExtensionRangeOptions) + uint32_t cached_has_bits = 0; + (void) cached_has_bits; + + // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; + for (unsigned i = 0, + n = static_cast<unsigned>(this->_internal_uninterpreted_option_size()); i < n; i++) { + const auto& repfield = this->_internal_uninterpreted_option(i); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite:: + InternalWriteMessage(999, repfield, repfield.GetCachedSize(), target, stream); + } + + // Extension range [1000, 536870912) + target = _impl_._extensions_._InternalSerialize( + internal_default_instance(), 1000, 536870912, target, stream); + + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + target = ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( + _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.ExtensionRangeOptions) + return target; +} + +size_t ExtensionRangeOptions::ByteSizeLong() const { +// @@protoc_insertion_point(message_byte_size_start:google.protobuf.ExtensionRangeOptions) + size_t total_size = 0; + + total_size += _impl_._extensions_.ByteSize(); + + uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; + total_size += 2UL * this->_internal_uninterpreted_option_size(); + for (const auto& msg : this->_impl_.uninterpreted_option_) { + total_size += + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::MessageSize(msg); + } + + return MaybeComputeUnknownFieldsSize(total_size, &_impl_._cached_size_); +} + +const ::PROTOBUF_NAMESPACE_ID::Message::ClassData ExtensionRangeOptions::_class_data_ = { + ::PROTOBUF_NAMESPACE_ID::Message::CopyWithSourceCheck, + ExtensionRangeOptions::MergeImpl +}; +const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*ExtensionRangeOptions::GetClassData() const { return &_class_data_; } + + +void ExtensionRangeOptions::MergeImpl(::PROTOBUF_NAMESPACE_ID::Message& to_msg, const ::PROTOBUF_NAMESPACE_ID::Message& from_msg) { + auto* const _this = static_cast<ExtensionRangeOptions*>(&to_msg); + auto& from = static_cast<const ExtensionRangeOptions&>(from_msg); + // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.ExtensionRangeOptions) + GOOGLE_DCHECK_NE(&from, _this); + uint32_t cached_has_bits = 0; + (void) cached_has_bits; + + _this->_impl_.uninterpreted_option_.MergeFrom(from._impl_.uninterpreted_option_); + _this->_impl_._extensions_.MergeFrom(internal_default_instance(), from._impl_._extensions_); + _this->_internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); +} + +void ExtensionRangeOptions::CopyFrom(const ExtensionRangeOptions& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.ExtensionRangeOptions) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool ExtensionRangeOptions::IsInitialized() const { + if (!_impl_._extensions_.IsInitialized()) { + return false; + } + + if (!::PROTOBUF_NAMESPACE_ID::internal::AllAreInitialized(_impl_.uninterpreted_option_)) + return false; + return true; +} + +void ExtensionRangeOptions::InternalSwap(ExtensionRangeOptions* other) { + using std::swap; + _impl_._extensions_.InternalSwap(&other->_impl_._extensions_); + _internal_metadata_.InternalSwap(&other->_internal_metadata_); + _impl_.uninterpreted_option_.InternalSwap(&other->_impl_.uninterpreted_option_); +} + +::PROTOBUF_NAMESPACE_ID::Metadata ExtensionRangeOptions::GetMetadata() const { + return ::_pbi::AssignDescriptors( + &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_getter, &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_once, + file_level_metadata_google_2fprotobuf_2fdescriptor_2eproto[5]); +} + +// =================================================================== + +class FieldDescriptorProto::_Internal { + public: + using HasBits = decltype(std::declval<FieldDescriptorProto>()._impl_._has_bits_); + static void set_has_name(HasBits* has_bits) { + (*has_bits)[0] |= 1u; + } + static void set_has_number(HasBits* has_bits) { + (*has_bits)[0] |= 64u; + } + static void set_has_label(HasBits* has_bits) { + (*has_bits)[0] |= 512u; + } + static void set_has_type(HasBits* has_bits) { + (*has_bits)[0] |= 1024u; + } + static void set_has_type_name(HasBits* has_bits) { + (*has_bits)[0] |= 4u; + } + static void set_has_extendee(HasBits* has_bits) { + (*has_bits)[0] |= 2u; + } + static void set_has_default_value(HasBits* has_bits) { + (*has_bits)[0] |= 8u; + } + static void set_has_oneof_index(HasBits* has_bits) { + (*has_bits)[0] |= 128u; + } + static void set_has_json_name(HasBits* has_bits) { + (*has_bits)[0] |= 16u; + } + static const ::PROTOBUF_NAMESPACE_ID::FieldOptions& options(const FieldDescriptorProto* msg); + static void set_has_options(HasBits* has_bits) { + (*has_bits)[0] |= 32u; + } + static void set_has_proto3_optional(HasBits* has_bits) { + (*has_bits)[0] |= 256u; + } +}; + +const ::PROTOBUF_NAMESPACE_ID::FieldOptions& +FieldDescriptorProto::_Internal::options(const FieldDescriptorProto* msg) { + return *msg->_impl_.options_; +} +FieldDescriptorProto::FieldDescriptorProto(::PROTOBUF_NAMESPACE_ID::Arena* arena, + bool is_message_owned) + : ::PROTOBUF_NAMESPACE_ID::Message(arena, is_message_owned) { + SharedCtor(arena, is_message_owned); + // @@protoc_insertion_point(arena_constructor:google.protobuf.FieldDescriptorProto) +} +FieldDescriptorProto::FieldDescriptorProto(const FieldDescriptorProto& from) + : ::PROTOBUF_NAMESPACE_ID::Message() { + FieldDescriptorProto* const _this = this; (void)_this; + new (&_impl_) Impl_{ + decltype(_impl_._has_bits_){from._impl_._has_bits_} + , /*decltype(_impl_._cached_size_)*/{} + , decltype(_impl_.name_){} + , decltype(_impl_.extendee_){} + , decltype(_impl_.type_name_){} + , decltype(_impl_.default_value_){} + , decltype(_impl_.json_name_){} + , decltype(_impl_.options_){nullptr} + , decltype(_impl_.number_){} + , decltype(_impl_.oneof_index_){} + , decltype(_impl_.proto3_optional_){} + , decltype(_impl_.label_){} + , decltype(_impl_.type_){}}; + + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); + _impl_.name_.InitDefault(); + #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + _impl_.name_.Set("", GetArenaForAllocation()); + #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (from._internal_has_name()) { + _this->_impl_.name_.Set(from._internal_name(), + _this->GetArenaForAllocation()); + } + _impl_.extendee_.InitDefault(); + #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + _impl_.extendee_.Set("", GetArenaForAllocation()); + #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (from._internal_has_extendee()) { + _this->_impl_.extendee_.Set(from._internal_extendee(), + _this->GetArenaForAllocation()); + } + _impl_.type_name_.InitDefault(); + #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + _impl_.type_name_.Set("", GetArenaForAllocation()); + #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (from._internal_has_type_name()) { + _this->_impl_.type_name_.Set(from._internal_type_name(), + _this->GetArenaForAllocation()); + } + _impl_.default_value_.InitDefault(); + #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + _impl_.default_value_.Set("", GetArenaForAllocation()); + #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (from._internal_has_default_value()) { + _this->_impl_.default_value_.Set(from._internal_default_value(), + _this->GetArenaForAllocation()); + } + _impl_.json_name_.InitDefault(); + #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + _impl_.json_name_.Set("", GetArenaForAllocation()); + #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (from._internal_has_json_name()) { + _this->_impl_.json_name_.Set(from._internal_json_name(), + _this->GetArenaForAllocation()); + } + if (from._internal_has_options()) { + _this->_impl_.options_ = new ::PROTOBUF_NAMESPACE_ID::FieldOptions(*from._impl_.options_); + } + ::memcpy(&_impl_.number_, &from._impl_.number_, + static_cast<size_t>(reinterpret_cast<char*>(&_impl_.type_) - + reinterpret_cast<char*>(&_impl_.number_)) + sizeof(_impl_.type_)); + // @@protoc_insertion_point(copy_constructor:google.protobuf.FieldDescriptorProto) +} + +inline void FieldDescriptorProto::SharedCtor( + ::_pb::Arena* arena, bool is_message_owned) { + (void)arena; + (void)is_message_owned; + new (&_impl_) Impl_{ + decltype(_impl_._has_bits_){} + , /*decltype(_impl_._cached_size_)*/{} + , decltype(_impl_.name_){} + , decltype(_impl_.extendee_){} + , decltype(_impl_.type_name_){} + , decltype(_impl_.default_value_){} + , decltype(_impl_.json_name_){} + , decltype(_impl_.options_){nullptr} + , decltype(_impl_.number_){0} + , decltype(_impl_.oneof_index_){0} + , decltype(_impl_.proto3_optional_){false} + , decltype(_impl_.label_){1} + , decltype(_impl_.type_){1} + }; + _impl_.name_.InitDefault(); + #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + _impl_.name_.Set("", GetArenaForAllocation()); + #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + _impl_.extendee_.InitDefault(); + #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + _impl_.extendee_.Set("", GetArenaForAllocation()); + #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + _impl_.type_name_.InitDefault(); + #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + _impl_.type_name_.Set("", GetArenaForAllocation()); + #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + _impl_.default_value_.InitDefault(); + #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + _impl_.default_value_.Set("", GetArenaForAllocation()); + #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + _impl_.json_name_.InitDefault(); + #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + _impl_.json_name_.Set("", GetArenaForAllocation()); + #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING +} + +FieldDescriptorProto::~FieldDescriptorProto() { + // @@protoc_insertion_point(destructor:google.protobuf.FieldDescriptorProto) + if (auto *arena = _internal_metadata_.DeleteReturnArena<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>()) { + (void)arena; + return; + } + SharedDtor(); +} + +inline void FieldDescriptorProto::SharedDtor() { + GOOGLE_DCHECK(GetArenaForAllocation() == nullptr); + _impl_.name_.Destroy(); + _impl_.extendee_.Destroy(); + _impl_.type_name_.Destroy(); + _impl_.default_value_.Destroy(); + _impl_.json_name_.Destroy(); + if (this != internal_default_instance()) delete _impl_.options_; +} + +void FieldDescriptorProto::SetCachedSize(int size) const { + _impl_._cached_size_.Set(size); +} + +void FieldDescriptorProto::Clear() { +// @@protoc_insertion_point(message_clear_start:google.protobuf.FieldDescriptorProto) + uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + cached_has_bits = _impl_._has_bits_[0]; + if (cached_has_bits & 0x0000003fu) { + if (cached_has_bits & 0x00000001u) { + _impl_.name_.ClearNonDefaultToEmpty(); + } + if (cached_has_bits & 0x00000002u) { + _impl_.extendee_.ClearNonDefaultToEmpty(); + } + if (cached_has_bits & 0x00000004u) { + _impl_.type_name_.ClearNonDefaultToEmpty(); + } + if (cached_has_bits & 0x00000008u) { + _impl_.default_value_.ClearNonDefaultToEmpty(); + } + if (cached_has_bits & 0x00000010u) { + _impl_.json_name_.ClearNonDefaultToEmpty(); + } + if (cached_has_bits & 0x00000020u) { + GOOGLE_DCHECK(_impl_.options_ != nullptr); + _impl_.options_->Clear(); + } + } + if (cached_has_bits & 0x000000c0u) { + ::memset(&_impl_.number_, 0, static_cast<size_t>( + reinterpret_cast<char*>(&_impl_.oneof_index_) - + reinterpret_cast<char*>(&_impl_.number_)) + sizeof(_impl_.oneof_index_)); + } + if (cached_has_bits & 0x00000700u) { + _impl_.proto3_optional_ = false; + _impl_.label_ = 1; + _impl_.type_ = 1; + } + _impl_._has_bits_.Clear(); + _internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); +} + +const char* FieldDescriptorProto::_InternalParse(const char* ptr, ::_pbi::ParseContext* ctx) { +#define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure + _Internal::HasBits has_bits{}; + while (!ctx->Done(&ptr)) { + uint32_t tag; + ptr = ::_pbi::ReadTag(ptr, &tag); + switch (tag >> 3) { + // optional string name = 1; + case 1: + if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 10)) { + auto str = _internal_mutable_name(); + ptr = ::_pbi::InlineGreedyStringParser(str, ptr, ctx); + CHK_(ptr); + #ifndef NDEBUG + ::_pbi::VerifyUTF8(str, "google.protobuf.FieldDescriptorProto.name"); + #endif // !NDEBUG + } else + goto handle_unusual; + continue; + // optional string extendee = 2; + case 2: + if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 18)) { + auto str = _internal_mutable_extendee(); + ptr = ::_pbi::InlineGreedyStringParser(str, ptr, ctx); + CHK_(ptr); + #ifndef NDEBUG + ::_pbi::VerifyUTF8(str, "google.protobuf.FieldDescriptorProto.extendee"); + #endif // !NDEBUG + } else + goto handle_unusual; + continue; + // optional int32 number = 3; + case 3: + if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 24)) { + _Internal::set_has_number(&has_bits); + _impl_.number_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint32(&ptr); + CHK_(ptr); + } else + goto handle_unusual; + continue; + // optional .google.protobuf.FieldDescriptorProto.Label label = 4; + case 4: + if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 32)) { + uint64_t val = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr); + CHK_(ptr); + if (PROTOBUF_PREDICT_TRUE(::PROTOBUF_NAMESPACE_ID::FieldDescriptorProto_Label_IsValid(val))) { + _internal_set_label(static_cast<::PROTOBUF_NAMESPACE_ID::FieldDescriptorProto_Label>(val)); + } else { + ::PROTOBUF_NAMESPACE_ID::internal::WriteVarint(4, val, mutable_unknown_fields()); + } + } else + goto handle_unusual; + continue; + // optional .google.protobuf.FieldDescriptorProto.Type type = 5; + case 5: + if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 40)) { + uint64_t val = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr); + CHK_(ptr); + if (PROTOBUF_PREDICT_TRUE(::PROTOBUF_NAMESPACE_ID::FieldDescriptorProto_Type_IsValid(val))) { + _internal_set_type(static_cast<::PROTOBUF_NAMESPACE_ID::FieldDescriptorProto_Type>(val)); + } else { + ::PROTOBUF_NAMESPACE_ID::internal::WriteVarint(5, val, mutable_unknown_fields()); + } + } else + goto handle_unusual; + continue; + // optional string type_name = 6; + case 6: + if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 50)) { + auto str = _internal_mutable_type_name(); + ptr = ::_pbi::InlineGreedyStringParser(str, ptr, ctx); + CHK_(ptr); + #ifndef NDEBUG + ::_pbi::VerifyUTF8(str, "google.protobuf.FieldDescriptorProto.type_name"); + #endif // !NDEBUG + } else + goto handle_unusual; + continue; + // optional string default_value = 7; + case 7: + if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 58)) { + auto str = _internal_mutable_default_value(); + ptr = ::_pbi::InlineGreedyStringParser(str, ptr, ctx); + CHK_(ptr); + #ifndef NDEBUG + ::_pbi::VerifyUTF8(str, "google.protobuf.FieldDescriptorProto.default_value"); + #endif // !NDEBUG + } else + goto handle_unusual; + continue; + // optional .google.protobuf.FieldOptions options = 8; + case 8: + if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 66)) { + ptr = ctx->ParseMessage(_internal_mutable_options(), ptr); + CHK_(ptr); + } else + goto handle_unusual; + continue; + // optional int32 oneof_index = 9; + case 9: + if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 72)) { + _Internal::set_has_oneof_index(&has_bits); + _impl_.oneof_index_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint32(&ptr); + CHK_(ptr); + } else + goto handle_unusual; + continue; + // optional string json_name = 10; + case 10: + if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 82)) { + auto str = _internal_mutable_json_name(); + ptr = ::_pbi::InlineGreedyStringParser(str, ptr, ctx); + CHK_(ptr); + #ifndef NDEBUG + ::_pbi::VerifyUTF8(str, "google.protobuf.FieldDescriptorProto.json_name"); + #endif // !NDEBUG + } else + goto handle_unusual; + continue; + // optional bool proto3_optional = 17; + case 17: + if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 136)) { + _Internal::set_has_proto3_optional(&has_bits); + _impl_.proto3_optional_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr); + CHK_(ptr); + } else + goto handle_unusual; + continue; + default: + goto handle_unusual; + } // switch + handle_unusual: + if ((tag == 0) || ((tag & 7) == 4)) { + CHK_(ptr); + ctx->SetLastTag(tag); + goto message_done; + } + ptr = UnknownFieldParse( + tag, + _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(), + ptr, ctx); + CHK_(ptr != nullptr); + } // while +message_done: + _impl_._has_bits_.Or(has_bits); + return ptr; +failure: + ptr = nullptr; + goto message_done; +#undef CHK_ +} + +uint8_t* FieldDescriptorProto::_InternalSerialize( + uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const { + // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.FieldDescriptorProto) + uint32_t cached_has_bits = 0; + (void) cached_has_bits; + + cached_has_bits = _impl_._has_bits_[0]; + // optional string name = 1; + if (cached_has_bits & 0x00000001u) { + ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::VerifyUTF8StringNamedField( + this->_internal_name().data(), static_cast<int>(this->_internal_name().length()), + ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::SERIALIZE, + "google.protobuf.FieldDescriptorProto.name"); + target = stream->WriteStringMaybeAliased( + 1, this->_internal_name(), target); + } + + // optional string extendee = 2; + if (cached_has_bits & 0x00000002u) { + ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::VerifyUTF8StringNamedField( + this->_internal_extendee().data(), static_cast<int>(this->_internal_extendee().length()), + ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::SERIALIZE, + "google.protobuf.FieldDescriptorProto.extendee"); + target = stream->WriteStringMaybeAliased( + 2, this->_internal_extendee(), target); + } + + // optional int32 number = 3; + if (cached_has_bits & 0x00000040u) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteInt32ToArray(3, this->_internal_number(), target); + } + + // optional .google.protobuf.FieldDescriptorProto.Label label = 4; + if (cached_has_bits & 0x00000200u) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteEnumToArray( + 4, this->_internal_label(), target); + } + + // optional .google.protobuf.FieldDescriptorProto.Type type = 5; + if (cached_has_bits & 0x00000400u) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteEnumToArray( + 5, this->_internal_type(), target); + } + + // optional string type_name = 6; + if (cached_has_bits & 0x00000004u) { + ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::VerifyUTF8StringNamedField( + this->_internal_type_name().data(), static_cast<int>(this->_internal_type_name().length()), + ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::SERIALIZE, + "google.protobuf.FieldDescriptorProto.type_name"); + target = stream->WriteStringMaybeAliased( + 6, this->_internal_type_name(), target); + } + + // optional string default_value = 7; + if (cached_has_bits & 0x00000008u) { + ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::VerifyUTF8StringNamedField( + this->_internal_default_value().data(), static_cast<int>(this->_internal_default_value().length()), + ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::SERIALIZE, + "google.protobuf.FieldDescriptorProto.default_value"); + target = stream->WriteStringMaybeAliased( + 7, this->_internal_default_value(), target); + } + + // optional .google.protobuf.FieldOptions options = 8; + if (cached_has_bits & 0x00000020u) { + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite:: + InternalWriteMessage(8, _Internal::options(this), + _Internal::options(this).GetCachedSize(), target, stream); + } + + // optional int32 oneof_index = 9; + if (cached_has_bits & 0x00000080u) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteInt32ToArray(9, this->_internal_oneof_index(), target); + } + + // optional string json_name = 10; + if (cached_has_bits & 0x00000010u) { + ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::VerifyUTF8StringNamedField( + this->_internal_json_name().data(), static_cast<int>(this->_internal_json_name().length()), + ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::SERIALIZE, + "google.protobuf.FieldDescriptorProto.json_name"); + target = stream->WriteStringMaybeAliased( + 10, this->_internal_json_name(), target); + } + + // optional bool proto3_optional = 17; + if (cached_has_bits & 0x00000100u) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteBoolToArray(17, this->_internal_proto3_optional(), target); + } + + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + target = ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( + _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.FieldDescriptorProto) + return target; +} + +size_t FieldDescriptorProto::ByteSizeLong() const { +// @@protoc_insertion_point(message_byte_size_start:google.protobuf.FieldDescriptorProto) + size_t total_size = 0; + + uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + cached_has_bits = _impl_._has_bits_[0]; + if (cached_has_bits & 0x000000ffu) { + // optional string name = 1; + if (cached_has_bits & 0x00000001u) { + total_size += 1 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize( + this->_internal_name()); + } + + // optional string extendee = 2; + if (cached_has_bits & 0x00000002u) { + total_size += 1 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize( + this->_internal_extendee()); + } + + // optional string type_name = 6; + if (cached_has_bits & 0x00000004u) { + total_size += 1 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize( + this->_internal_type_name()); + } + + // optional string default_value = 7; + if (cached_has_bits & 0x00000008u) { + total_size += 1 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize( + this->_internal_default_value()); + } + + // optional string json_name = 10; + if (cached_has_bits & 0x00000010u) { + total_size += 1 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize( + this->_internal_json_name()); + } + + // optional .google.protobuf.FieldOptions options = 8; + if (cached_has_bits & 0x00000020u) { + total_size += 1 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::MessageSize( + *_impl_.options_); + } + + // optional int32 number = 3; + if (cached_has_bits & 0x00000040u) { + total_size += ::_pbi::WireFormatLite::Int32SizePlusOne(this->_internal_number()); + } + + // optional int32 oneof_index = 9; + if (cached_has_bits & 0x00000080u) { + total_size += ::_pbi::WireFormatLite::Int32SizePlusOne(this->_internal_oneof_index()); + } + + } + if (cached_has_bits & 0x00000700u) { + // optional bool proto3_optional = 17; + if (cached_has_bits & 0x00000100u) { + total_size += 2 + 1; + } + + // optional .google.protobuf.FieldDescriptorProto.Label label = 4; + if (cached_has_bits & 0x00000200u) { + total_size += 1 + + ::_pbi::WireFormatLite::EnumSize(this->_internal_label()); + } + + // optional .google.protobuf.FieldDescriptorProto.Type type = 5; + if (cached_has_bits & 0x00000400u) { + total_size += 1 + + ::_pbi::WireFormatLite::EnumSize(this->_internal_type()); + } + + } + return MaybeComputeUnknownFieldsSize(total_size, &_impl_._cached_size_); +} + +const ::PROTOBUF_NAMESPACE_ID::Message::ClassData FieldDescriptorProto::_class_data_ = { + ::PROTOBUF_NAMESPACE_ID::Message::CopyWithSourceCheck, + FieldDescriptorProto::MergeImpl +}; +const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*FieldDescriptorProto::GetClassData() const { return &_class_data_; } + + +void FieldDescriptorProto::MergeImpl(::PROTOBUF_NAMESPACE_ID::Message& to_msg, const ::PROTOBUF_NAMESPACE_ID::Message& from_msg) { + auto* const _this = static_cast<FieldDescriptorProto*>(&to_msg); + auto& from = static_cast<const FieldDescriptorProto&>(from_msg); + // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.FieldDescriptorProto) + GOOGLE_DCHECK_NE(&from, _this); + uint32_t cached_has_bits = 0; + (void) cached_has_bits; + + cached_has_bits = from._impl_._has_bits_[0]; + if (cached_has_bits & 0x000000ffu) { + if (cached_has_bits & 0x00000001u) { + _this->_internal_set_name(from._internal_name()); + } + if (cached_has_bits & 0x00000002u) { + _this->_internal_set_extendee(from._internal_extendee()); + } + if (cached_has_bits & 0x00000004u) { + _this->_internal_set_type_name(from._internal_type_name()); + } + if (cached_has_bits & 0x00000008u) { + _this->_internal_set_default_value(from._internal_default_value()); + } + if (cached_has_bits & 0x00000010u) { + _this->_internal_set_json_name(from._internal_json_name()); + } + if (cached_has_bits & 0x00000020u) { + _this->_internal_mutable_options()->::PROTOBUF_NAMESPACE_ID::FieldOptions::MergeFrom( + from._internal_options()); + } + if (cached_has_bits & 0x00000040u) { + _this->_impl_.number_ = from._impl_.number_; + } + if (cached_has_bits & 0x00000080u) { + _this->_impl_.oneof_index_ = from._impl_.oneof_index_; + } + _this->_impl_._has_bits_[0] |= cached_has_bits; + } + if (cached_has_bits & 0x00000700u) { + if (cached_has_bits & 0x00000100u) { + _this->_impl_.proto3_optional_ = from._impl_.proto3_optional_; + } + if (cached_has_bits & 0x00000200u) { + _this->_impl_.label_ = from._impl_.label_; + } + if (cached_has_bits & 0x00000400u) { + _this->_impl_.type_ = from._impl_.type_; + } + _this->_impl_._has_bits_[0] |= cached_has_bits; + } + _this->_internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); +} + +void FieldDescriptorProto::CopyFrom(const FieldDescriptorProto& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.FieldDescriptorProto) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool FieldDescriptorProto::IsInitialized() const { + if (_internal_has_options()) { + if (!_impl_.options_->IsInitialized()) return false; + } + return true; +} + +void FieldDescriptorProto::InternalSwap(FieldDescriptorProto* other) { + using std::swap; + auto* lhs_arena = GetArenaForAllocation(); + auto* rhs_arena = other->GetArenaForAllocation(); + _internal_metadata_.InternalSwap(&other->_internal_metadata_); + swap(_impl_._has_bits_[0], other->_impl_._has_bits_[0]); + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::InternalSwap( + &_impl_.name_, lhs_arena, + &other->_impl_.name_, rhs_arena + ); + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::InternalSwap( + &_impl_.extendee_, lhs_arena, + &other->_impl_.extendee_, rhs_arena + ); + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::InternalSwap( + &_impl_.type_name_, lhs_arena, + &other->_impl_.type_name_, rhs_arena + ); + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::InternalSwap( + &_impl_.default_value_, lhs_arena, + &other->_impl_.default_value_, rhs_arena + ); + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::InternalSwap( + &_impl_.json_name_, lhs_arena, + &other->_impl_.json_name_, rhs_arena + ); + ::PROTOBUF_NAMESPACE_ID::internal::memswap< + PROTOBUF_FIELD_OFFSET(FieldDescriptorProto, _impl_.proto3_optional_) + + sizeof(FieldDescriptorProto::_impl_.proto3_optional_) + - PROTOBUF_FIELD_OFFSET(FieldDescriptorProto, _impl_.options_)>( + reinterpret_cast<char*>(&_impl_.options_), + reinterpret_cast<char*>(&other->_impl_.options_)); + swap(_impl_.label_, other->_impl_.label_); + swap(_impl_.type_, other->_impl_.type_); +} + +::PROTOBUF_NAMESPACE_ID::Metadata FieldDescriptorProto::GetMetadata() const { + return ::_pbi::AssignDescriptors( + &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_getter, &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_once, + file_level_metadata_google_2fprotobuf_2fdescriptor_2eproto[6]); +} + +// =================================================================== + +class OneofDescriptorProto::_Internal { + public: + using HasBits = decltype(std::declval<OneofDescriptorProto>()._impl_._has_bits_); + static void set_has_name(HasBits* has_bits) { + (*has_bits)[0] |= 1u; + } + static const ::PROTOBUF_NAMESPACE_ID::OneofOptions& options(const OneofDescriptorProto* msg); + static void set_has_options(HasBits* has_bits) { + (*has_bits)[0] |= 2u; + } +}; + +const ::PROTOBUF_NAMESPACE_ID::OneofOptions& +OneofDescriptorProto::_Internal::options(const OneofDescriptorProto* msg) { + return *msg->_impl_.options_; +} +OneofDescriptorProto::OneofDescriptorProto(::PROTOBUF_NAMESPACE_ID::Arena* arena, + bool is_message_owned) + : ::PROTOBUF_NAMESPACE_ID::Message(arena, is_message_owned) { + SharedCtor(arena, is_message_owned); + // @@protoc_insertion_point(arena_constructor:google.protobuf.OneofDescriptorProto) +} +OneofDescriptorProto::OneofDescriptorProto(const OneofDescriptorProto& from) + : ::PROTOBUF_NAMESPACE_ID::Message() { + OneofDescriptorProto* const _this = this; (void)_this; + new (&_impl_) Impl_{ + decltype(_impl_._has_bits_){from._impl_._has_bits_} + , /*decltype(_impl_._cached_size_)*/{} + , decltype(_impl_.name_){} + , decltype(_impl_.options_){nullptr}}; + + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); + _impl_.name_.InitDefault(); + #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + _impl_.name_.Set("", GetArenaForAllocation()); + #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (from._internal_has_name()) { + _this->_impl_.name_.Set(from._internal_name(), + _this->GetArenaForAllocation()); + } + if (from._internal_has_options()) { + _this->_impl_.options_ = new ::PROTOBUF_NAMESPACE_ID::OneofOptions(*from._impl_.options_); + } + // @@protoc_insertion_point(copy_constructor:google.protobuf.OneofDescriptorProto) +} + +inline void OneofDescriptorProto::SharedCtor( + ::_pb::Arena* arena, bool is_message_owned) { + (void)arena; + (void)is_message_owned; + new (&_impl_) Impl_{ + decltype(_impl_._has_bits_){} + , /*decltype(_impl_._cached_size_)*/{} + , decltype(_impl_.name_){} + , decltype(_impl_.options_){nullptr} + }; + _impl_.name_.InitDefault(); + #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + _impl_.name_.Set("", GetArenaForAllocation()); + #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING +} + +OneofDescriptorProto::~OneofDescriptorProto() { + // @@protoc_insertion_point(destructor:google.protobuf.OneofDescriptorProto) + if (auto *arena = _internal_metadata_.DeleteReturnArena<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>()) { + (void)arena; + return; + } + SharedDtor(); +} + +inline void OneofDescriptorProto::SharedDtor() { + GOOGLE_DCHECK(GetArenaForAllocation() == nullptr); + _impl_.name_.Destroy(); + if (this != internal_default_instance()) delete _impl_.options_; +} + +void OneofDescriptorProto::SetCachedSize(int size) const { + _impl_._cached_size_.Set(size); +} + +void OneofDescriptorProto::Clear() { +// @@protoc_insertion_point(message_clear_start:google.protobuf.OneofDescriptorProto) + uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + cached_has_bits = _impl_._has_bits_[0]; + if (cached_has_bits & 0x00000003u) { + if (cached_has_bits & 0x00000001u) { + _impl_.name_.ClearNonDefaultToEmpty(); + } + if (cached_has_bits & 0x00000002u) { + GOOGLE_DCHECK(_impl_.options_ != nullptr); + _impl_.options_->Clear(); + } + } + _impl_._has_bits_.Clear(); + _internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); +} + +const char* OneofDescriptorProto::_InternalParse(const char* ptr, ::_pbi::ParseContext* ctx) { +#define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure + _Internal::HasBits has_bits{}; + while (!ctx->Done(&ptr)) { + uint32_t tag; + ptr = ::_pbi::ReadTag(ptr, &tag); + switch (tag >> 3) { + // optional string name = 1; + case 1: + if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 10)) { + auto str = _internal_mutable_name(); + ptr = ::_pbi::InlineGreedyStringParser(str, ptr, ctx); + CHK_(ptr); + #ifndef NDEBUG + ::_pbi::VerifyUTF8(str, "google.protobuf.OneofDescriptorProto.name"); + #endif // !NDEBUG + } else + goto handle_unusual; + continue; + // optional .google.protobuf.OneofOptions options = 2; + case 2: + if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 18)) { + ptr = ctx->ParseMessage(_internal_mutable_options(), ptr); + CHK_(ptr); + } else + goto handle_unusual; + continue; + default: + goto handle_unusual; + } // switch + handle_unusual: + if ((tag == 0) || ((tag & 7) == 4)) { + CHK_(ptr); + ctx->SetLastTag(tag); + goto message_done; + } + ptr = UnknownFieldParse( + tag, + _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(), + ptr, ctx); + CHK_(ptr != nullptr); + } // while +message_done: + _impl_._has_bits_.Or(has_bits); + return ptr; +failure: + ptr = nullptr; + goto message_done; +#undef CHK_ +} + +uint8_t* OneofDescriptorProto::_InternalSerialize( + uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const { + // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.OneofDescriptorProto) + uint32_t cached_has_bits = 0; + (void) cached_has_bits; + + cached_has_bits = _impl_._has_bits_[0]; + // optional string name = 1; + if (cached_has_bits & 0x00000001u) { + ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::VerifyUTF8StringNamedField( + this->_internal_name().data(), static_cast<int>(this->_internal_name().length()), + ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::SERIALIZE, + "google.protobuf.OneofDescriptorProto.name"); + target = stream->WriteStringMaybeAliased( + 1, this->_internal_name(), target); + } + + // optional .google.protobuf.OneofOptions options = 2; + if (cached_has_bits & 0x00000002u) { + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite:: + InternalWriteMessage(2, _Internal::options(this), + _Internal::options(this).GetCachedSize(), target, stream); + } + + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + target = ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( + _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.OneofDescriptorProto) + return target; +} + +size_t OneofDescriptorProto::ByteSizeLong() const { +// @@protoc_insertion_point(message_byte_size_start:google.protobuf.OneofDescriptorProto) + size_t total_size = 0; + + uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + cached_has_bits = _impl_._has_bits_[0]; + if (cached_has_bits & 0x00000003u) { + // optional string name = 1; + if (cached_has_bits & 0x00000001u) { + total_size += 1 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize( + this->_internal_name()); + } + + // optional .google.protobuf.OneofOptions options = 2; + if (cached_has_bits & 0x00000002u) { + total_size += 1 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::MessageSize( + *_impl_.options_); + } + + } + return MaybeComputeUnknownFieldsSize(total_size, &_impl_._cached_size_); +} + +const ::PROTOBUF_NAMESPACE_ID::Message::ClassData OneofDescriptorProto::_class_data_ = { + ::PROTOBUF_NAMESPACE_ID::Message::CopyWithSourceCheck, + OneofDescriptorProto::MergeImpl +}; +const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*OneofDescriptorProto::GetClassData() const { return &_class_data_; } + + +void OneofDescriptorProto::MergeImpl(::PROTOBUF_NAMESPACE_ID::Message& to_msg, const ::PROTOBUF_NAMESPACE_ID::Message& from_msg) { + auto* const _this = static_cast<OneofDescriptorProto*>(&to_msg); + auto& from = static_cast<const OneofDescriptorProto&>(from_msg); + // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.OneofDescriptorProto) + GOOGLE_DCHECK_NE(&from, _this); + uint32_t cached_has_bits = 0; + (void) cached_has_bits; + + cached_has_bits = from._impl_._has_bits_[0]; + if (cached_has_bits & 0x00000003u) { + if (cached_has_bits & 0x00000001u) { + _this->_internal_set_name(from._internal_name()); + } + if (cached_has_bits & 0x00000002u) { + _this->_internal_mutable_options()->::PROTOBUF_NAMESPACE_ID::OneofOptions::MergeFrom( + from._internal_options()); + } + } + _this->_internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); +} + +void OneofDescriptorProto::CopyFrom(const OneofDescriptorProto& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.OneofDescriptorProto) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool OneofDescriptorProto::IsInitialized() const { + if (_internal_has_options()) { + if (!_impl_.options_->IsInitialized()) return false; + } + return true; +} + +void OneofDescriptorProto::InternalSwap(OneofDescriptorProto* other) { + using std::swap; + auto* lhs_arena = GetArenaForAllocation(); + auto* rhs_arena = other->GetArenaForAllocation(); + _internal_metadata_.InternalSwap(&other->_internal_metadata_); + swap(_impl_._has_bits_[0], other->_impl_._has_bits_[0]); + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::InternalSwap( + &_impl_.name_, lhs_arena, + &other->_impl_.name_, rhs_arena + ); + swap(_impl_.options_, other->_impl_.options_); +} + +::PROTOBUF_NAMESPACE_ID::Metadata OneofDescriptorProto::GetMetadata() const { + return ::_pbi::AssignDescriptors( + &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_getter, &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_once, + file_level_metadata_google_2fprotobuf_2fdescriptor_2eproto[7]); +} + +// =================================================================== + +class EnumDescriptorProto_EnumReservedRange::_Internal { + public: + using HasBits = decltype(std::declval<EnumDescriptorProto_EnumReservedRange>()._impl_._has_bits_); + static void set_has_start(HasBits* has_bits) { + (*has_bits)[0] |= 1u; + } + static void set_has_end(HasBits* has_bits) { + (*has_bits)[0] |= 2u; + } +}; + +EnumDescriptorProto_EnumReservedRange::EnumDescriptorProto_EnumReservedRange(::PROTOBUF_NAMESPACE_ID::Arena* arena, + bool is_message_owned) + : ::PROTOBUF_NAMESPACE_ID::Message(arena, is_message_owned) { + SharedCtor(arena, is_message_owned); + // @@protoc_insertion_point(arena_constructor:google.protobuf.EnumDescriptorProto.EnumReservedRange) +} +EnumDescriptorProto_EnumReservedRange::EnumDescriptorProto_EnumReservedRange(const EnumDescriptorProto_EnumReservedRange& from) + : ::PROTOBUF_NAMESPACE_ID::Message() { + EnumDescriptorProto_EnumReservedRange* const _this = this; (void)_this; + new (&_impl_) Impl_{ + decltype(_impl_._has_bits_){from._impl_._has_bits_} + , /*decltype(_impl_._cached_size_)*/{} + , decltype(_impl_.start_){} + , decltype(_impl_.end_){}}; + + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); + ::memcpy(&_impl_.start_, &from._impl_.start_, + static_cast<size_t>(reinterpret_cast<char*>(&_impl_.end_) - + reinterpret_cast<char*>(&_impl_.start_)) + sizeof(_impl_.end_)); + // @@protoc_insertion_point(copy_constructor:google.protobuf.EnumDescriptorProto.EnumReservedRange) +} + +inline void EnumDescriptorProto_EnumReservedRange::SharedCtor( + ::_pb::Arena* arena, bool is_message_owned) { + (void)arena; + (void)is_message_owned; + new (&_impl_) Impl_{ + decltype(_impl_._has_bits_){} + , /*decltype(_impl_._cached_size_)*/{} + , decltype(_impl_.start_){0} + , decltype(_impl_.end_){0} + }; +} + +EnumDescriptorProto_EnumReservedRange::~EnumDescriptorProto_EnumReservedRange() { + // @@protoc_insertion_point(destructor:google.protobuf.EnumDescriptorProto.EnumReservedRange) + if (auto *arena = _internal_metadata_.DeleteReturnArena<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>()) { + (void)arena; + return; + } + SharedDtor(); +} + +inline void EnumDescriptorProto_EnumReservedRange::SharedDtor() { + GOOGLE_DCHECK(GetArenaForAllocation() == nullptr); +} + +void EnumDescriptorProto_EnumReservedRange::SetCachedSize(int size) const { + _impl_._cached_size_.Set(size); +} + +void EnumDescriptorProto_EnumReservedRange::Clear() { +// @@protoc_insertion_point(message_clear_start:google.protobuf.EnumDescriptorProto.EnumReservedRange) + uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + cached_has_bits = _impl_._has_bits_[0]; + if (cached_has_bits & 0x00000003u) { + ::memset(&_impl_.start_, 0, static_cast<size_t>( + reinterpret_cast<char*>(&_impl_.end_) - + reinterpret_cast<char*>(&_impl_.start_)) + sizeof(_impl_.end_)); + } + _impl_._has_bits_.Clear(); + _internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); +} + +const char* EnumDescriptorProto_EnumReservedRange::_InternalParse(const char* ptr, ::_pbi::ParseContext* ctx) { +#define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure + _Internal::HasBits has_bits{}; + while (!ctx->Done(&ptr)) { + uint32_t tag; + ptr = ::_pbi::ReadTag(ptr, &tag); + switch (tag >> 3) { + // optional int32 start = 1; + case 1: + if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 8)) { + _Internal::set_has_start(&has_bits); + _impl_.start_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint32(&ptr); + CHK_(ptr); + } else + goto handle_unusual; + continue; + // optional int32 end = 2; + case 2: + if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 16)) { + _Internal::set_has_end(&has_bits); + _impl_.end_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint32(&ptr); + CHK_(ptr); + } else + goto handle_unusual; + continue; + default: + goto handle_unusual; + } // switch + handle_unusual: + if ((tag == 0) || ((tag & 7) == 4)) { + CHK_(ptr); + ctx->SetLastTag(tag); + goto message_done; + } + ptr = UnknownFieldParse( + tag, + _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(), + ptr, ctx); + CHK_(ptr != nullptr); + } // while +message_done: + _impl_._has_bits_.Or(has_bits); + return ptr; +failure: + ptr = nullptr; + goto message_done; +#undef CHK_ +} + +uint8_t* EnumDescriptorProto_EnumReservedRange::_InternalSerialize( + uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const { + // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.EnumDescriptorProto.EnumReservedRange) + uint32_t cached_has_bits = 0; + (void) cached_has_bits; + + cached_has_bits = _impl_._has_bits_[0]; + // optional int32 start = 1; + if (cached_has_bits & 0x00000001u) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteInt32ToArray(1, this->_internal_start(), target); + } + + // optional int32 end = 2; + if (cached_has_bits & 0x00000002u) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteInt32ToArray(2, this->_internal_end(), target); + } + + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + target = ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( + _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.EnumDescriptorProto.EnumReservedRange) + return target; +} + +size_t EnumDescriptorProto_EnumReservedRange::ByteSizeLong() const { +// @@protoc_insertion_point(message_byte_size_start:google.protobuf.EnumDescriptorProto.EnumReservedRange) + size_t total_size = 0; + + uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + cached_has_bits = _impl_._has_bits_[0]; + if (cached_has_bits & 0x00000003u) { + // optional int32 start = 1; + if (cached_has_bits & 0x00000001u) { + total_size += ::_pbi::WireFormatLite::Int32SizePlusOne(this->_internal_start()); + } + + // optional int32 end = 2; + if (cached_has_bits & 0x00000002u) { + total_size += ::_pbi::WireFormatLite::Int32SizePlusOne(this->_internal_end()); + } + + } + return MaybeComputeUnknownFieldsSize(total_size, &_impl_._cached_size_); +} + +const ::PROTOBUF_NAMESPACE_ID::Message::ClassData EnumDescriptorProto_EnumReservedRange::_class_data_ = { + ::PROTOBUF_NAMESPACE_ID::Message::CopyWithSourceCheck, + EnumDescriptorProto_EnumReservedRange::MergeImpl +}; +const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*EnumDescriptorProto_EnumReservedRange::GetClassData() const { return &_class_data_; } + + +void EnumDescriptorProto_EnumReservedRange::MergeImpl(::PROTOBUF_NAMESPACE_ID::Message& to_msg, const ::PROTOBUF_NAMESPACE_ID::Message& from_msg) { + auto* const _this = static_cast<EnumDescriptorProto_EnumReservedRange*>(&to_msg); + auto& from = static_cast<const EnumDescriptorProto_EnumReservedRange&>(from_msg); + // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.EnumDescriptorProto.EnumReservedRange) + GOOGLE_DCHECK_NE(&from, _this); + uint32_t cached_has_bits = 0; + (void) cached_has_bits; + + cached_has_bits = from._impl_._has_bits_[0]; + if (cached_has_bits & 0x00000003u) { + if (cached_has_bits & 0x00000001u) { + _this->_impl_.start_ = from._impl_.start_; + } + if (cached_has_bits & 0x00000002u) { + _this->_impl_.end_ = from._impl_.end_; + } + _this->_impl_._has_bits_[0] |= cached_has_bits; + } + _this->_internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); +} + +void EnumDescriptorProto_EnumReservedRange::CopyFrom(const EnumDescriptorProto_EnumReservedRange& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.EnumDescriptorProto.EnumReservedRange) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool EnumDescriptorProto_EnumReservedRange::IsInitialized() const { + return true; +} + +void EnumDescriptorProto_EnumReservedRange::InternalSwap(EnumDescriptorProto_EnumReservedRange* other) { + using std::swap; + _internal_metadata_.InternalSwap(&other->_internal_metadata_); + swap(_impl_._has_bits_[0], other->_impl_._has_bits_[0]); + ::PROTOBUF_NAMESPACE_ID::internal::memswap< + PROTOBUF_FIELD_OFFSET(EnumDescriptorProto_EnumReservedRange, _impl_.end_) + + sizeof(EnumDescriptorProto_EnumReservedRange::_impl_.end_) + - PROTOBUF_FIELD_OFFSET(EnumDescriptorProto_EnumReservedRange, _impl_.start_)>( + reinterpret_cast<char*>(&_impl_.start_), + reinterpret_cast<char*>(&other->_impl_.start_)); +} + +::PROTOBUF_NAMESPACE_ID::Metadata EnumDescriptorProto_EnumReservedRange::GetMetadata() const { + return ::_pbi::AssignDescriptors( + &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_getter, &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_once, + file_level_metadata_google_2fprotobuf_2fdescriptor_2eproto[8]); +} + +// =================================================================== + +class EnumDescriptorProto::_Internal { + public: + using HasBits = decltype(std::declval<EnumDescriptorProto>()._impl_._has_bits_); + static void set_has_name(HasBits* has_bits) { + (*has_bits)[0] |= 1u; + } + static const ::PROTOBUF_NAMESPACE_ID::EnumOptions& options(const EnumDescriptorProto* msg); + static void set_has_options(HasBits* has_bits) { + (*has_bits)[0] |= 2u; + } +}; + +const ::PROTOBUF_NAMESPACE_ID::EnumOptions& +EnumDescriptorProto::_Internal::options(const EnumDescriptorProto* msg) { + return *msg->_impl_.options_; +} +EnumDescriptorProto::EnumDescriptorProto(::PROTOBUF_NAMESPACE_ID::Arena* arena, + bool is_message_owned) + : ::PROTOBUF_NAMESPACE_ID::Message(arena, is_message_owned) { + SharedCtor(arena, is_message_owned); + // @@protoc_insertion_point(arena_constructor:google.protobuf.EnumDescriptorProto) +} +EnumDescriptorProto::EnumDescriptorProto(const EnumDescriptorProto& from) + : ::PROTOBUF_NAMESPACE_ID::Message() { + EnumDescriptorProto* const _this = this; (void)_this; + new (&_impl_) Impl_{ + decltype(_impl_._has_bits_){from._impl_._has_bits_} + , /*decltype(_impl_._cached_size_)*/{} + , decltype(_impl_.value_){from._impl_.value_} + , decltype(_impl_.reserved_range_){from._impl_.reserved_range_} + , decltype(_impl_.reserved_name_){from._impl_.reserved_name_} + , decltype(_impl_.name_){} + , decltype(_impl_.options_){nullptr}}; + + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); + _impl_.name_.InitDefault(); + #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + _impl_.name_.Set("", GetArenaForAllocation()); + #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (from._internal_has_name()) { + _this->_impl_.name_.Set(from._internal_name(), + _this->GetArenaForAllocation()); + } + if (from._internal_has_options()) { + _this->_impl_.options_ = new ::PROTOBUF_NAMESPACE_ID::EnumOptions(*from._impl_.options_); + } + // @@protoc_insertion_point(copy_constructor:google.protobuf.EnumDescriptorProto) +} + +inline void EnumDescriptorProto::SharedCtor( + ::_pb::Arena* arena, bool is_message_owned) { + (void)arena; + (void)is_message_owned; + new (&_impl_) Impl_{ + decltype(_impl_._has_bits_){} + , /*decltype(_impl_._cached_size_)*/{} + , decltype(_impl_.value_){arena} + , decltype(_impl_.reserved_range_){arena} + , decltype(_impl_.reserved_name_){arena} + , decltype(_impl_.name_){} + , decltype(_impl_.options_){nullptr} + }; + _impl_.name_.InitDefault(); + #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + _impl_.name_.Set("", GetArenaForAllocation()); + #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING +} + +EnumDescriptorProto::~EnumDescriptorProto() { + // @@protoc_insertion_point(destructor:google.protobuf.EnumDescriptorProto) + if (auto *arena = _internal_metadata_.DeleteReturnArena<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>()) { + (void)arena; + return; + } + SharedDtor(); +} + +inline void EnumDescriptorProto::SharedDtor() { + GOOGLE_DCHECK(GetArenaForAllocation() == nullptr); + _impl_.value_.~RepeatedPtrField(); + _impl_.reserved_range_.~RepeatedPtrField(); + _impl_.reserved_name_.~RepeatedPtrField(); + _impl_.name_.Destroy(); + if (this != internal_default_instance()) delete _impl_.options_; +} + +void EnumDescriptorProto::SetCachedSize(int size) const { + _impl_._cached_size_.Set(size); +} + +void EnumDescriptorProto::Clear() { +// @@protoc_insertion_point(message_clear_start:google.protobuf.EnumDescriptorProto) + uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + _impl_.value_.Clear(); + _impl_.reserved_range_.Clear(); + _impl_.reserved_name_.Clear(); + cached_has_bits = _impl_._has_bits_[0]; + if (cached_has_bits & 0x00000003u) { + if (cached_has_bits & 0x00000001u) { + _impl_.name_.ClearNonDefaultToEmpty(); + } + if (cached_has_bits & 0x00000002u) { + GOOGLE_DCHECK(_impl_.options_ != nullptr); + _impl_.options_->Clear(); + } + } + _impl_._has_bits_.Clear(); + _internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); +} + +const char* EnumDescriptorProto::_InternalParse(const char* ptr, ::_pbi::ParseContext* ctx) { +#define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure + _Internal::HasBits has_bits{}; + while (!ctx->Done(&ptr)) { + uint32_t tag; + ptr = ::_pbi::ReadTag(ptr, &tag); + switch (tag >> 3) { + // optional string name = 1; + case 1: + if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 10)) { + auto str = _internal_mutable_name(); + ptr = ::_pbi::InlineGreedyStringParser(str, ptr, ctx); + CHK_(ptr); + #ifndef NDEBUG + ::_pbi::VerifyUTF8(str, "google.protobuf.EnumDescriptorProto.name"); + #endif // !NDEBUG + } else + goto handle_unusual; + continue; + // repeated .google.protobuf.EnumValueDescriptorProto value = 2; + case 2: + if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 18)) { + ptr -= 1; + do { + ptr += 1; + ptr = ctx->ParseMessage(_internal_add_value(), ptr); + CHK_(ptr); + if (!ctx->DataAvailable(ptr)) break; + } while (::PROTOBUF_NAMESPACE_ID::internal::ExpectTag<18>(ptr)); + } else + goto handle_unusual; + continue; + // optional .google.protobuf.EnumOptions options = 3; + case 3: + if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 26)) { + ptr = ctx->ParseMessage(_internal_mutable_options(), ptr); + CHK_(ptr); + } else + goto handle_unusual; + continue; + // repeated .google.protobuf.EnumDescriptorProto.EnumReservedRange reserved_range = 4; + case 4: + if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 34)) { + ptr -= 1; + do { + ptr += 1; + ptr = ctx->ParseMessage(_internal_add_reserved_range(), ptr); + CHK_(ptr); + if (!ctx->DataAvailable(ptr)) break; + } while (::PROTOBUF_NAMESPACE_ID::internal::ExpectTag<34>(ptr)); + } else + goto handle_unusual; + continue; + // repeated string reserved_name = 5; + case 5: + if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 42)) { + ptr -= 1; + do { + ptr += 1; + auto str = _internal_add_reserved_name(); + ptr = ::_pbi::InlineGreedyStringParser(str, ptr, ctx); + CHK_(ptr); + #ifndef NDEBUG + ::_pbi::VerifyUTF8(str, "google.protobuf.EnumDescriptorProto.reserved_name"); + #endif // !NDEBUG + if (!ctx->DataAvailable(ptr)) break; + } while (::PROTOBUF_NAMESPACE_ID::internal::ExpectTag<42>(ptr)); + } else + goto handle_unusual; + continue; + default: + goto handle_unusual; + } // switch + handle_unusual: + if ((tag == 0) || ((tag & 7) == 4)) { + CHK_(ptr); + ctx->SetLastTag(tag); + goto message_done; + } + ptr = UnknownFieldParse( + tag, + _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(), + ptr, ctx); + CHK_(ptr != nullptr); + } // while +message_done: + _impl_._has_bits_.Or(has_bits); + return ptr; +failure: + ptr = nullptr; + goto message_done; +#undef CHK_ +} + +uint8_t* EnumDescriptorProto::_InternalSerialize( + uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const { + // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.EnumDescriptorProto) + uint32_t cached_has_bits = 0; + (void) cached_has_bits; + + cached_has_bits = _impl_._has_bits_[0]; + // optional string name = 1; + if (cached_has_bits & 0x00000001u) { + ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::VerifyUTF8StringNamedField( + this->_internal_name().data(), static_cast<int>(this->_internal_name().length()), + ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::SERIALIZE, + "google.protobuf.EnumDescriptorProto.name"); + target = stream->WriteStringMaybeAliased( + 1, this->_internal_name(), target); + } + + // repeated .google.protobuf.EnumValueDescriptorProto value = 2; + for (unsigned i = 0, + n = static_cast<unsigned>(this->_internal_value_size()); i < n; i++) { + const auto& repfield = this->_internal_value(i); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite:: + InternalWriteMessage(2, repfield, repfield.GetCachedSize(), target, stream); + } + + // optional .google.protobuf.EnumOptions options = 3; + if (cached_has_bits & 0x00000002u) { + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite:: + InternalWriteMessage(3, _Internal::options(this), + _Internal::options(this).GetCachedSize(), target, stream); + } + + // repeated .google.protobuf.EnumDescriptorProto.EnumReservedRange reserved_range = 4; + for (unsigned i = 0, + n = static_cast<unsigned>(this->_internal_reserved_range_size()); i < n; i++) { + const auto& repfield = this->_internal_reserved_range(i); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite:: + InternalWriteMessage(4, repfield, repfield.GetCachedSize(), target, stream); + } + + // repeated string reserved_name = 5; + for (int i = 0, n = this->_internal_reserved_name_size(); i < n; i++) { + const auto& s = this->_internal_reserved_name(i); + ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::VerifyUTF8StringNamedField( + s.data(), static_cast<int>(s.length()), + ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::SERIALIZE, + "google.protobuf.EnumDescriptorProto.reserved_name"); + target = stream->WriteString(5, s, target); + } + + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + target = ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( + _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.EnumDescriptorProto) + return target; +} + +size_t EnumDescriptorProto::ByteSizeLong() const { +// @@protoc_insertion_point(message_byte_size_start:google.protobuf.EnumDescriptorProto) + size_t total_size = 0; + + uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + // repeated .google.protobuf.EnumValueDescriptorProto value = 2; + total_size += 1UL * this->_internal_value_size(); + for (const auto& msg : this->_impl_.value_) { + total_size += + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::MessageSize(msg); + } + + // repeated .google.protobuf.EnumDescriptorProto.EnumReservedRange reserved_range = 4; + total_size += 1UL * this->_internal_reserved_range_size(); + for (const auto& msg : this->_impl_.reserved_range_) { + total_size += + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::MessageSize(msg); + } + + // repeated string reserved_name = 5; + total_size += 1 * + ::PROTOBUF_NAMESPACE_ID::internal::FromIntSize(_impl_.reserved_name_.size()); + for (int i = 0, n = _impl_.reserved_name_.size(); i < n; i++) { + total_size += ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize( + _impl_.reserved_name_.Get(i)); + } + + cached_has_bits = _impl_._has_bits_[0]; + if (cached_has_bits & 0x00000003u) { + // optional string name = 1; + if (cached_has_bits & 0x00000001u) { + total_size += 1 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize( + this->_internal_name()); + } + + // optional .google.protobuf.EnumOptions options = 3; + if (cached_has_bits & 0x00000002u) { + total_size += 1 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::MessageSize( + *_impl_.options_); + } + + } + return MaybeComputeUnknownFieldsSize(total_size, &_impl_._cached_size_); +} + +const ::PROTOBUF_NAMESPACE_ID::Message::ClassData EnumDescriptorProto::_class_data_ = { + ::PROTOBUF_NAMESPACE_ID::Message::CopyWithSourceCheck, + EnumDescriptorProto::MergeImpl +}; +const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*EnumDescriptorProto::GetClassData() const { return &_class_data_; } + + +void EnumDescriptorProto::MergeImpl(::PROTOBUF_NAMESPACE_ID::Message& to_msg, const ::PROTOBUF_NAMESPACE_ID::Message& from_msg) { + auto* const _this = static_cast<EnumDescriptorProto*>(&to_msg); + auto& from = static_cast<const EnumDescriptorProto&>(from_msg); + // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.EnumDescriptorProto) + GOOGLE_DCHECK_NE(&from, _this); + uint32_t cached_has_bits = 0; + (void) cached_has_bits; + + _this->_impl_.value_.MergeFrom(from._impl_.value_); + _this->_impl_.reserved_range_.MergeFrom(from._impl_.reserved_range_); + _this->_impl_.reserved_name_.MergeFrom(from._impl_.reserved_name_); + cached_has_bits = from._impl_._has_bits_[0]; + if (cached_has_bits & 0x00000003u) { + if (cached_has_bits & 0x00000001u) { + _this->_internal_set_name(from._internal_name()); + } + if (cached_has_bits & 0x00000002u) { + _this->_internal_mutable_options()->::PROTOBUF_NAMESPACE_ID::EnumOptions::MergeFrom( + from._internal_options()); + } + } + _this->_internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); +} + +void EnumDescriptorProto::CopyFrom(const EnumDescriptorProto& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.EnumDescriptorProto) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool EnumDescriptorProto::IsInitialized() const { + if (!::PROTOBUF_NAMESPACE_ID::internal::AllAreInitialized(_impl_.value_)) + return false; + if (_internal_has_options()) { + if (!_impl_.options_->IsInitialized()) return false; + } + return true; +} + +void EnumDescriptorProto::InternalSwap(EnumDescriptorProto* other) { + using std::swap; + auto* lhs_arena = GetArenaForAllocation(); + auto* rhs_arena = other->GetArenaForAllocation(); + _internal_metadata_.InternalSwap(&other->_internal_metadata_); + swap(_impl_._has_bits_[0], other->_impl_._has_bits_[0]); + _impl_.value_.InternalSwap(&other->_impl_.value_); + _impl_.reserved_range_.InternalSwap(&other->_impl_.reserved_range_); + _impl_.reserved_name_.InternalSwap(&other->_impl_.reserved_name_); + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::InternalSwap( + &_impl_.name_, lhs_arena, + &other->_impl_.name_, rhs_arena + ); + swap(_impl_.options_, other->_impl_.options_); +} + +::PROTOBUF_NAMESPACE_ID::Metadata EnumDescriptorProto::GetMetadata() const { + return ::_pbi::AssignDescriptors( + &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_getter, &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_once, + file_level_metadata_google_2fprotobuf_2fdescriptor_2eproto[9]); +} + +// =================================================================== + +class EnumValueDescriptorProto::_Internal { + public: + using HasBits = decltype(std::declval<EnumValueDescriptorProto>()._impl_._has_bits_); + static void set_has_name(HasBits* has_bits) { + (*has_bits)[0] |= 1u; + } + static void set_has_number(HasBits* has_bits) { + (*has_bits)[0] |= 4u; + } + static const ::PROTOBUF_NAMESPACE_ID::EnumValueOptions& options(const EnumValueDescriptorProto* msg); + static void set_has_options(HasBits* has_bits) { + (*has_bits)[0] |= 2u; + } +}; + +const ::PROTOBUF_NAMESPACE_ID::EnumValueOptions& +EnumValueDescriptorProto::_Internal::options(const EnumValueDescriptorProto* msg) { + return *msg->_impl_.options_; +} +EnumValueDescriptorProto::EnumValueDescriptorProto(::PROTOBUF_NAMESPACE_ID::Arena* arena, + bool is_message_owned) + : ::PROTOBUF_NAMESPACE_ID::Message(arena, is_message_owned) { + SharedCtor(arena, is_message_owned); + // @@protoc_insertion_point(arena_constructor:google.protobuf.EnumValueDescriptorProto) +} +EnumValueDescriptorProto::EnumValueDescriptorProto(const EnumValueDescriptorProto& from) + : ::PROTOBUF_NAMESPACE_ID::Message() { + EnumValueDescriptorProto* const _this = this; (void)_this; + new (&_impl_) Impl_{ + decltype(_impl_._has_bits_){from._impl_._has_bits_} + , /*decltype(_impl_._cached_size_)*/{} + , decltype(_impl_.name_){} + , decltype(_impl_.options_){nullptr} + , decltype(_impl_.number_){}}; + + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); + _impl_.name_.InitDefault(); + #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + _impl_.name_.Set("", GetArenaForAllocation()); + #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (from._internal_has_name()) { + _this->_impl_.name_.Set(from._internal_name(), + _this->GetArenaForAllocation()); + } + if (from._internal_has_options()) { + _this->_impl_.options_ = new ::PROTOBUF_NAMESPACE_ID::EnumValueOptions(*from._impl_.options_); + } + _this->_impl_.number_ = from._impl_.number_; + // @@protoc_insertion_point(copy_constructor:google.protobuf.EnumValueDescriptorProto) +} + +inline void EnumValueDescriptorProto::SharedCtor( + ::_pb::Arena* arena, bool is_message_owned) { + (void)arena; + (void)is_message_owned; + new (&_impl_) Impl_{ + decltype(_impl_._has_bits_){} + , /*decltype(_impl_._cached_size_)*/{} + , decltype(_impl_.name_){} + , decltype(_impl_.options_){nullptr} + , decltype(_impl_.number_){0} + }; + _impl_.name_.InitDefault(); + #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + _impl_.name_.Set("", GetArenaForAllocation()); + #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING +} + +EnumValueDescriptorProto::~EnumValueDescriptorProto() { + // @@protoc_insertion_point(destructor:google.protobuf.EnumValueDescriptorProto) + if (auto *arena = _internal_metadata_.DeleteReturnArena<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>()) { + (void)arena; + return; + } + SharedDtor(); +} + +inline void EnumValueDescriptorProto::SharedDtor() { + GOOGLE_DCHECK(GetArenaForAllocation() == nullptr); + _impl_.name_.Destroy(); + if (this != internal_default_instance()) delete _impl_.options_; +} + +void EnumValueDescriptorProto::SetCachedSize(int size) const { + _impl_._cached_size_.Set(size); +} + +void EnumValueDescriptorProto::Clear() { +// @@protoc_insertion_point(message_clear_start:google.protobuf.EnumValueDescriptorProto) + uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + cached_has_bits = _impl_._has_bits_[0]; + if (cached_has_bits & 0x00000003u) { + if (cached_has_bits & 0x00000001u) { + _impl_.name_.ClearNonDefaultToEmpty(); + } + if (cached_has_bits & 0x00000002u) { + GOOGLE_DCHECK(_impl_.options_ != nullptr); + _impl_.options_->Clear(); + } + } + _impl_.number_ = 0; + _impl_._has_bits_.Clear(); + _internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); +} + +const char* EnumValueDescriptorProto::_InternalParse(const char* ptr, ::_pbi::ParseContext* ctx) { +#define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure + _Internal::HasBits has_bits{}; + while (!ctx->Done(&ptr)) { + uint32_t tag; + ptr = ::_pbi::ReadTag(ptr, &tag); + switch (tag >> 3) { + // optional string name = 1; + case 1: + if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 10)) { + auto str = _internal_mutable_name(); + ptr = ::_pbi::InlineGreedyStringParser(str, ptr, ctx); + CHK_(ptr); + #ifndef NDEBUG + ::_pbi::VerifyUTF8(str, "google.protobuf.EnumValueDescriptorProto.name"); + #endif // !NDEBUG + } else + goto handle_unusual; + continue; + // optional int32 number = 2; + case 2: + if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 16)) { + _Internal::set_has_number(&has_bits); + _impl_.number_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint32(&ptr); + CHK_(ptr); + } else + goto handle_unusual; + continue; + // optional .google.protobuf.EnumValueOptions options = 3; + case 3: + if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 26)) { + ptr = ctx->ParseMessage(_internal_mutable_options(), ptr); + CHK_(ptr); + } else + goto handle_unusual; + continue; + default: + goto handle_unusual; + } // switch + handle_unusual: + if ((tag == 0) || ((tag & 7) == 4)) { + CHK_(ptr); + ctx->SetLastTag(tag); + goto message_done; + } + ptr = UnknownFieldParse( + tag, + _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(), + ptr, ctx); + CHK_(ptr != nullptr); + } // while +message_done: + _impl_._has_bits_.Or(has_bits); + return ptr; +failure: + ptr = nullptr; + goto message_done; +#undef CHK_ +} + +uint8_t* EnumValueDescriptorProto::_InternalSerialize( + uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const { + // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.EnumValueDescriptorProto) + uint32_t cached_has_bits = 0; + (void) cached_has_bits; + + cached_has_bits = _impl_._has_bits_[0]; + // optional string name = 1; + if (cached_has_bits & 0x00000001u) { + ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::VerifyUTF8StringNamedField( + this->_internal_name().data(), static_cast<int>(this->_internal_name().length()), + ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::SERIALIZE, + "google.protobuf.EnumValueDescriptorProto.name"); + target = stream->WriteStringMaybeAliased( + 1, this->_internal_name(), target); + } + + // optional int32 number = 2; + if (cached_has_bits & 0x00000004u) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteInt32ToArray(2, this->_internal_number(), target); + } + + // optional .google.protobuf.EnumValueOptions options = 3; + if (cached_has_bits & 0x00000002u) { + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite:: + InternalWriteMessage(3, _Internal::options(this), + _Internal::options(this).GetCachedSize(), target, stream); + } + + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + target = ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( + _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.EnumValueDescriptorProto) + return target; +} + +size_t EnumValueDescriptorProto::ByteSizeLong() const { +// @@protoc_insertion_point(message_byte_size_start:google.protobuf.EnumValueDescriptorProto) + size_t total_size = 0; + + uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + cached_has_bits = _impl_._has_bits_[0]; + if (cached_has_bits & 0x00000007u) { + // optional string name = 1; + if (cached_has_bits & 0x00000001u) { + total_size += 1 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize( + this->_internal_name()); + } + + // optional .google.protobuf.EnumValueOptions options = 3; + if (cached_has_bits & 0x00000002u) { + total_size += 1 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::MessageSize( + *_impl_.options_); + } + + // optional int32 number = 2; + if (cached_has_bits & 0x00000004u) { + total_size += ::_pbi::WireFormatLite::Int32SizePlusOne(this->_internal_number()); + } + + } + return MaybeComputeUnknownFieldsSize(total_size, &_impl_._cached_size_); +} + +const ::PROTOBUF_NAMESPACE_ID::Message::ClassData EnumValueDescriptorProto::_class_data_ = { + ::PROTOBUF_NAMESPACE_ID::Message::CopyWithSourceCheck, + EnumValueDescriptorProto::MergeImpl +}; +const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*EnumValueDescriptorProto::GetClassData() const { return &_class_data_; } + + +void EnumValueDescriptorProto::MergeImpl(::PROTOBUF_NAMESPACE_ID::Message& to_msg, const ::PROTOBUF_NAMESPACE_ID::Message& from_msg) { + auto* const _this = static_cast<EnumValueDescriptorProto*>(&to_msg); + auto& from = static_cast<const EnumValueDescriptorProto&>(from_msg); + // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.EnumValueDescriptorProto) + GOOGLE_DCHECK_NE(&from, _this); + uint32_t cached_has_bits = 0; + (void) cached_has_bits; + + cached_has_bits = from._impl_._has_bits_[0]; + if (cached_has_bits & 0x00000007u) { + if (cached_has_bits & 0x00000001u) { + _this->_internal_set_name(from._internal_name()); + } + if (cached_has_bits & 0x00000002u) { + _this->_internal_mutable_options()->::PROTOBUF_NAMESPACE_ID::EnumValueOptions::MergeFrom( + from._internal_options()); + } + if (cached_has_bits & 0x00000004u) { + _this->_impl_.number_ = from._impl_.number_; + } + _this->_impl_._has_bits_[0] |= cached_has_bits; + } + _this->_internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); +} + +void EnumValueDescriptorProto::CopyFrom(const EnumValueDescriptorProto& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.EnumValueDescriptorProto) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool EnumValueDescriptorProto::IsInitialized() const { + if (_internal_has_options()) { + if (!_impl_.options_->IsInitialized()) return false; + } + return true; +} + +void EnumValueDescriptorProto::InternalSwap(EnumValueDescriptorProto* other) { + using std::swap; + auto* lhs_arena = GetArenaForAllocation(); + auto* rhs_arena = other->GetArenaForAllocation(); + _internal_metadata_.InternalSwap(&other->_internal_metadata_); + swap(_impl_._has_bits_[0], other->_impl_._has_bits_[0]); + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::InternalSwap( + &_impl_.name_, lhs_arena, + &other->_impl_.name_, rhs_arena + ); + ::PROTOBUF_NAMESPACE_ID::internal::memswap< + PROTOBUF_FIELD_OFFSET(EnumValueDescriptorProto, _impl_.number_) + + sizeof(EnumValueDescriptorProto::_impl_.number_) + - PROTOBUF_FIELD_OFFSET(EnumValueDescriptorProto, _impl_.options_)>( + reinterpret_cast<char*>(&_impl_.options_), + reinterpret_cast<char*>(&other->_impl_.options_)); +} + +::PROTOBUF_NAMESPACE_ID::Metadata EnumValueDescriptorProto::GetMetadata() const { + return ::_pbi::AssignDescriptors( + &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_getter, &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_once, + file_level_metadata_google_2fprotobuf_2fdescriptor_2eproto[10]); +} + +// =================================================================== + +class ServiceDescriptorProto::_Internal { + public: + using HasBits = decltype(std::declval<ServiceDescriptorProto>()._impl_._has_bits_); + static void set_has_name(HasBits* has_bits) { + (*has_bits)[0] |= 1u; + } + static const ::PROTOBUF_NAMESPACE_ID::ServiceOptions& options(const ServiceDescriptorProto* msg); + static void set_has_options(HasBits* has_bits) { + (*has_bits)[0] |= 2u; + } +}; + +const ::PROTOBUF_NAMESPACE_ID::ServiceOptions& +ServiceDescriptorProto::_Internal::options(const ServiceDescriptorProto* msg) { + return *msg->_impl_.options_; +} +ServiceDescriptorProto::ServiceDescriptorProto(::PROTOBUF_NAMESPACE_ID::Arena* arena, + bool is_message_owned) + : ::PROTOBUF_NAMESPACE_ID::Message(arena, is_message_owned) { + SharedCtor(arena, is_message_owned); + // @@protoc_insertion_point(arena_constructor:google.protobuf.ServiceDescriptorProto) +} +ServiceDescriptorProto::ServiceDescriptorProto(const ServiceDescriptorProto& from) + : ::PROTOBUF_NAMESPACE_ID::Message() { + ServiceDescriptorProto* const _this = this; (void)_this; + new (&_impl_) Impl_{ + decltype(_impl_._has_bits_){from._impl_._has_bits_} + , /*decltype(_impl_._cached_size_)*/{} + , decltype(_impl_.method_){from._impl_.method_} + , decltype(_impl_.name_){} + , decltype(_impl_.options_){nullptr}}; + + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); + _impl_.name_.InitDefault(); + #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + _impl_.name_.Set("", GetArenaForAllocation()); + #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (from._internal_has_name()) { + _this->_impl_.name_.Set(from._internal_name(), + _this->GetArenaForAllocation()); + } + if (from._internal_has_options()) { + _this->_impl_.options_ = new ::PROTOBUF_NAMESPACE_ID::ServiceOptions(*from._impl_.options_); + } + // @@protoc_insertion_point(copy_constructor:google.protobuf.ServiceDescriptorProto) +} + +inline void ServiceDescriptorProto::SharedCtor( + ::_pb::Arena* arena, bool is_message_owned) { + (void)arena; + (void)is_message_owned; + new (&_impl_) Impl_{ + decltype(_impl_._has_bits_){} + , /*decltype(_impl_._cached_size_)*/{} + , decltype(_impl_.method_){arena} + , decltype(_impl_.name_){} + , decltype(_impl_.options_){nullptr} + }; + _impl_.name_.InitDefault(); + #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + _impl_.name_.Set("", GetArenaForAllocation()); + #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING +} + +ServiceDescriptorProto::~ServiceDescriptorProto() { + // @@protoc_insertion_point(destructor:google.protobuf.ServiceDescriptorProto) + if (auto *arena = _internal_metadata_.DeleteReturnArena<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>()) { + (void)arena; + return; + } + SharedDtor(); +} + +inline void ServiceDescriptorProto::SharedDtor() { + GOOGLE_DCHECK(GetArenaForAllocation() == nullptr); + _impl_.method_.~RepeatedPtrField(); + _impl_.name_.Destroy(); + if (this != internal_default_instance()) delete _impl_.options_; +} + +void ServiceDescriptorProto::SetCachedSize(int size) const { + _impl_._cached_size_.Set(size); +} + +void ServiceDescriptorProto::Clear() { +// @@protoc_insertion_point(message_clear_start:google.protobuf.ServiceDescriptorProto) + uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + _impl_.method_.Clear(); + cached_has_bits = _impl_._has_bits_[0]; + if (cached_has_bits & 0x00000003u) { + if (cached_has_bits & 0x00000001u) { + _impl_.name_.ClearNonDefaultToEmpty(); + } + if (cached_has_bits & 0x00000002u) { + GOOGLE_DCHECK(_impl_.options_ != nullptr); + _impl_.options_->Clear(); + } + } + _impl_._has_bits_.Clear(); + _internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); +} + +const char* ServiceDescriptorProto::_InternalParse(const char* ptr, ::_pbi::ParseContext* ctx) { +#define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure + _Internal::HasBits has_bits{}; + while (!ctx->Done(&ptr)) { + uint32_t tag; + ptr = ::_pbi::ReadTag(ptr, &tag); + switch (tag >> 3) { + // optional string name = 1; + case 1: + if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 10)) { + auto str = _internal_mutable_name(); + ptr = ::_pbi::InlineGreedyStringParser(str, ptr, ctx); + CHK_(ptr); + #ifndef NDEBUG + ::_pbi::VerifyUTF8(str, "google.protobuf.ServiceDescriptorProto.name"); + #endif // !NDEBUG + } else + goto handle_unusual; + continue; + // repeated .google.protobuf.MethodDescriptorProto method = 2; + case 2: + if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 18)) { + ptr -= 1; + do { + ptr += 1; + ptr = ctx->ParseMessage(_internal_add_method(), ptr); + CHK_(ptr); + if (!ctx->DataAvailable(ptr)) break; + } while (::PROTOBUF_NAMESPACE_ID::internal::ExpectTag<18>(ptr)); + } else + goto handle_unusual; + continue; + // optional .google.protobuf.ServiceOptions options = 3; + case 3: + if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 26)) { + ptr = ctx->ParseMessage(_internal_mutable_options(), ptr); + CHK_(ptr); + } else + goto handle_unusual; + continue; + default: + goto handle_unusual; + } // switch + handle_unusual: + if ((tag == 0) || ((tag & 7) == 4)) { + CHK_(ptr); + ctx->SetLastTag(tag); + goto message_done; + } + ptr = UnknownFieldParse( + tag, + _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(), + ptr, ctx); + CHK_(ptr != nullptr); + } // while +message_done: + _impl_._has_bits_.Or(has_bits); + return ptr; +failure: + ptr = nullptr; + goto message_done; +#undef CHK_ +} + +uint8_t* ServiceDescriptorProto::_InternalSerialize( + uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const { + // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.ServiceDescriptorProto) + uint32_t cached_has_bits = 0; + (void) cached_has_bits; + + cached_has_bits = _impl_._has_bits_[0]; + // optional string name = 1; + if (cached_has_bits & 0x00000001u) { + ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::VerifyUTF8StringNamedField( + this->_internal_name().data(), static_cast<int>(this->_internal_name().length()), + ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::SERIALIZE, + "google.protobuf.ServiceDescriptorProto.name"); + target = stream->WriteStringMaybeAliased( + 1, this->_internal_name(), target); + } + + // repeated .google.protobuf.MethodDescriptorProto method = 2; + for (unsigned i = 0, + n = static_cast<unsigned>(this->_internal_method_size()); i < n; i++) { + const auto& repfield = this->_internal_method(i); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite:: + InternalWriteMessage(2, repfield, repfield.GetCachedSize(), target, stream); + } + + // optional .google.protobuf.ServiceOptions options = 3; + if (cached_has_bits & 0x00000002u) { + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite:: + InternalWriteMessage(3, _Internal::options(this), + _Internal::options(this).GetCachedSize(), target, stream); + } + + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + target = ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( + _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.ServiceDescriptorProto) + return target; +} + +size_t ServiceDescriptorProto::ByteSizeLong() const { +// @@protoc_insertion_point(message_byte_size_start:google.protobuf.ServiceDescriptorProto) + size_t total_size = 0; + + uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + // repeated .google.protobuf.MethodDescriptorProto method = 2; + total_size += 1UL * this->_internal_method_size(); + for (const auto& msg : this->_impl_.method_) { + total_size += + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::MessageSize(msg); + } + + cached_has_bits = _impl_._has_bits_[0]; + if (cached_has_bits & 0x00000003u) { + // optional string name = 1; + if (cached_has_bits & 0x00000001u) { + total_size += 1 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize( + this->_internal_name()); + } + + // optional .google.protobuf.ServiceOptions options = 3; + if (cached_has_bits & 0x00000002u) { + total_size += 1 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::MessageSize( + *_impl_.options_); + } + + } + return MaybeComputeUnknownFieldsSize(total_size, &_impl_._cached_size_); +} + +const ::PROTOBUF_NAMESPACE_ID::Message::ClassData ServiceDescriptorProto::_class_data_ = { + ::PROTOBUF_NAMESPACE_ID::Message::CopyWithSourceCheck, + ServiceDescriptorProto::MergeImpl +}; +const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*ServiceDescriptorProto::GetClassData() const { return &_class_data_; } + + +void ServiceDescriptorProto::MergeImpl(::PROTOBUF_NAMESPACE_ID::Message& to_msg, const ::PROTOBUF_NAMESPACE_ID::Message& from_msg) { + auto* const _this = static_cast<ServiceDescriptorProto*>(&to_msg); + auto& from = static_cast<const ServiceDescriptorProto&>(from_msg); + // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.ServiceDescriptorProto) + GOOGLE_DCHECK_NE(&from, _this); + uint32_t cached_has_bits = 0; + (void) cached_has_bits; + + _this->_impl_.method_.MergeFrom(from._impl_.method_); + cached_has_bits = from._impl_._has_bits_[0]; + if (cached_has_bits & 0x00000003u) { + if (cached_has_bits & 0x00000001u) { + _this->_internal_set_name(from._internal_name()); + } + if (cached_has_bits & 0x00000002u) { + _this->_internal_mutable_options()->::PROTOBUF_NAMESPACE_ID::ServiceOptions::MergeFrom( + from._internal_options()); + } + } + _this->_internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); +} + +void ServiceDescriptorProto::CopyFrom(const ServiceDescriptorProto& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.ServiceDescriptorProto) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool ServiceDescriptorProto::IsInitialized() const { + if (!::PROTOBUF_NAMESPACE_ID::internal::AllAreInitialized(_impl_.method_)) + return false; + if (_internal_has_options()) { + if (!_impl_.options_->IsInitialized()) return false; + } + return true; +} + +void ServiceDescriptorProto::InternalSwap(ServiceDescriptorProto* other) { + using std::swap; + auto* lhs_arena = GetArenaForAllocation(); + auto* rhs_arena = other->GetArenaForAllocation(); + _internal_metadata_.InternalSwap(&other->_internal_metadata_); + swap(_impl_._has_bits_[0], other->_impl_._has_bits_[0]); + _impl_.method_.InternalSwap(&other->_impl_.method_); + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::InternalSwap( + &_impl_.name_, lhs_arena, + &other->_impl_.name_, rhs_arena + ); + swap(_impl_.options_, other->_impl_.options_); +} + +::PROTOBUF_NAMESPACE_ID::Metadata ServiceDescriptorProto::GetMetadata() const { + return ::_pbi::AssignDescriptors( + &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_getter, &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_once, + file_level_metadata_google_2fprotobuf_2fdescriptor_2eproto[11]); +} + +// =================================================================== + +class MethodDescriptorProto::_Internal { + public: + using HasBits = decltype(std::declval<MethodDescriptorProto>()._impl_._has_bits_); + static void set_has_name(HasBits* has_bits) { + (*has_bits)[0] |= 1u; + } + static void set_has_input_type(HasBits* has_bits) { + (*has_bits)[0] |= 2u; + } + static void set_has_output_type(HasBits* has_bits) { + (*has_bits)[0] |= 4u; + } + static const ::PROTOBUF_NAMESPACE_ID::MethodOptions& options(const MethodDescriptorProto* msg); + static void set_has_options(HasBits* has_bits) { + (*has_bits)[0] |= 8u; + } + static void set_has_client_streaming(HasBits* has_bits) { + (*has_bits)[0] |= 16u; + } + static void set_has_server_streaming(HasBits* has_bits) { + (*has_bits)[0] |= 32u; + } +}; + +const ::PROTOBUF_NAMESPACE_ID::MethodOptions& +MethodDescriptorProto::_Internal::options(const MethodDescriptorProto* msg) { + return *msg->_impl_.options_; +} +MethodDescriptorProto::MethodDescriptorProto(::PROTOBUF_NAMESPACE_ID::Arena* arena, + bool is_message_owned) + : ::PROTOBUF_NAMESPACE_ID::Message(arena, is_message_owned) { + SharedCtor(arena, is_message_owned); + // @@protoc_insertion_point(arena_constructor:google.protobuf.MethodDescriptorProto) +} +MethodDescriptorProto::MethodDescriptorProto(const MethodDescriptorProto& from) + : ::PROTOBUF_NAMESPACE_ID::Message() { + MethodDescriptorProto* const _this = this; (void)_this; + new (&_impl_) Impl_{ + decltype(_impl_._has_bits_){from._impl_._has_bits_} + , /*decltype(_impl_._cached_size_)*/{} + , decltype(_impl_.name_){} + , decltype(_impl_.input_type_){} + , decltype(_impl_.output_type_){} + , decltype(_impl_.options_){nullptr} + , decltype(_impl_.client_streaming_){} + , decltype(_impl_.server_streaming_){}}; + + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); + _impl_.name_.InitDefault(); + #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + _impl_.name_.Set("", GetArenaForAllocation()); + #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (from._internal_has_name()) { + _this->_impl_.name_.Set(from._internal_name(), + _this->GetArenaForAllocation()); + } + _impl_.input_type_.InitDefault(); + #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + _impl_.input_type_.Set("", GetArenaForAllocation()); + #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (from._internal_has_input_type()) { + _this->_impl_.input_type_.Set(from._internal_input_type(), + _this->GetArenaForAllocation()); + } + _impl_.output_type_.InitDefault(); + #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + _impl_.output_type_.Set("", GetArenaForAllocation()); + #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (from._internal_has_output_type()) { + _this->_impl_.output_type_.Set(from._internal_output_type(), + _this->GetArenaForAllocation()); + } + if (from._internal_has_options()) { + _this->_impl_.options_ = new ::PROTOBUF_NAMESPACE_ID::MethodOptions(*from._impl_.options_); + } + ::memcpy(&_impl_.client_streaming_, &from._impl_.client_streaming_, + static_cast<size_t>(reinterpret_cast<char*>(&_impl_.server_streaming_) - + reinterpret_cast<char*>(&_impl_.client_streaming_)) + sizeof(_impl_.server_streaming_)); + // @@protoc_insertion_point(copy_constructor:google.protobuf.MethodDescriptorProto) +} + +inline void MethodDescriptorProto::SharedCtor( + ::_pb::Arena* arena, bool is_message_owned) { + (void)arena; + (void)is_message_owned; + new (&_impl_) Impl_{ + decltype(_impl_._has_bits_){} + , /*decltype(_impl_._cached_size_)*/{} + , decltype(_impl_.name_){} + , decltype(_impl_.input_type_){} + , decltype(_impl_.output_type_){} + , decltype(_impl_.options_){nullptr} + , decltype(_impl_.client_streaming_){false} + , decltype(_impl_.server_streaming_){false} + }; + _impl_.name_.InitDefault(); + #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + _impl_.name_.Set("", GetArenaForAllocation()); + #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + _impl_.input_type_.InitDefault(); + #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + _impl_.input_type_.Set("", GetArenaForAllocation()); + #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + _impl_.output_type_.InitDefault(); + #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + _impl_.output_type_.Set("", GetArenaForAllocation()); + #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING +} + +MethodDescriptorProto::~MethodDescriptorProto() { + // @@protoc_insertion_point(destructor:google.protobuf.MethodDescriptorProto) + if (auto *arena = _internal_metadata_.DeleteReturnArena<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>()) { + (void)arena; + return; + } + SharedDtor(); +} + +inline void MethodDescriptorProto::SharedDtor() { + GOOGLE_DCHECK(GetArenaForAllocation() == nullptr); + _impl_.name_.Destroy(); + _impl_.input_type_.Destroy(); + _impl_.output_type_.Destroy(); + if (this != internal_default_instance()) delete _impl_.options_; +} + +void MethodDescriptorProto::SetCachedSize(int size) const { + _impl_._cached_size_.Set(size); +} + +void MethodDescriptorProto::Clear() { +// @@protoc_insertion_point(message_clear_start:google.protobuf.MethodDescriptorProto) + uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + cached_has_bits = _impl_._has_bits_[0]; + if (cached_has_bits & 0x0000000fu) { + if (cached_has_bits & 0x00000001u) { + _impl_.name_.ClearNonDefaultToEmpty(); + } + if (cached_has_bits & 0x00000002u) { + _impl_.input_type_.ClearNonDefaultToEmpty(); + } + if (cached_has_bits & 0x00000004u) { + _impl_.output_type_.ClearNonDefaultToEmpty(); + } + if (cached_has_bits & 0x00000008u) { + GOOGLE_DCHECK(_impl_.options_ != nullptr); + _impl_.options_->Clear(); + } + } + ::memset(&_impl_.client_streaming_, 0, static_cast<size_t>( + reinterpret_cast<char*>(&_impl_.server_streaming_) - + reinterpret_cast<char*>(&_impl_.client_streaming_)) + sizeof(_impl_.server_streaming_)); + _impl_._has_bits_.Clear(); + _internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); +} + +const char* MethodDescriptorProto::_InternalParse(const char* ptr, ::_pbi::ParseContext* ctx) { +#define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure + _Internal::HasBits has_bits{}; + while (!ctx->Done(&ptr)) { + uint32_t tag; + ptr = ::_pbi::ReadTag(ptr, &tag); + switch (tag >> 3) { + // optional string name = 1; + case 1: + if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 10)) { + auto str = _internal_mutable_name(); + ptr = ::_pbi::InlineGreedyStringParser(str, ptr, ctx); + CHK_(ptr); + #ifndef NDEBUG + ::_pbi::VerifyUTF8(str, "google.protobuf.MethodDescriptorProto.name"); + #endif // !NDEBUG + } else + goto handle_unusual; + continue; + // optional string input_type = 2; + case 2: + if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 18)) { + auto str = _internal_mutable_input_type(); + ptr = ::_pbi::InlineGreedyStringParser(str, ptr, ctx); + CHK_(ptr); + #ifndef NDEBUG + ::_pbi::VerifyUTF8(str, "google.protobuf.MethodDescriptorProto.input_type"); + #endif // !NDEBUG + } else + goto handle_unusual; + continue; + // optional string output_type = 3; + case 3: + if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 26)) { + auto str = _internal_mutable_output_type(); + ptr = ::_pbi::InlineGreedyStringParser(str, ptr, ctx); + CHK_(ptr); + #ifndef NDEBUG + ::_pbi::VerifyUTF8(str, "google.protobuf.MethodDescriptorProto.output_type"); + #endif // !NDEBUG + } else + goto handle_unusual; + continue; + // optional .google.protobuf.MethodOptions options = 4; + case 4: + if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 34)) { + ptr = ctx->ParseMessage(_internal_mutable_options(), ptr); + CHK_(ptr); + } else + goto handle_unusual; + continue; + // optional bool client_streaming = 5 [default = false]; + case 5: + if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 40)) { + _Internal::set_has_client_streaming(&has_bits); + _impl_.client_streaming_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr); + CHK_(ptr); + } else + goto handle_unusual; + continue; + // optional bool server_streaming = 6 [default = false]; + case 6: + if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 48)) { + _Internal::set_has_server_streaming(&has_bits); + _impl_.server_streaming_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr); + CHK_(ptr); + } else + goto handle_unusual; + continue; + default: + goto handle_unusual; + } // switch + handle_unusual: + if ((tag == 0) || ((tag & 7) == 4)) { + CHK_(ptr); + ctx->SetLastTag(tag); + goto message_done; + } + ptr = UnknownFieldParse( + tag, + _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(), + ptr, ctx); + CHK_(ptr != nullptr); + } // while +message_done: + _impl_._has_bits_.Or(has_bits); + return ptr; +failure: + ptr = nullptr; + goto message_done; +#undef CHK_ +} + +uint8_t* MethodDescriptorProto::_InternalSerialize( + uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const { + // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.MethodDescriptorProto) + uint32_t cached_has_bits = 0; + (void) cached_has_bits; + + cached_has_bits = _impl_._has_bits_[0]; + // optional string name = 1; + if (cached_has_bits & 0x00000001u) { + ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::VerifyUTF8StringNamedField( + this->_internal_name().data(), static_cast<int>(this->_internal_name().length()), + ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::SERIALIZE, + "google.protobuf.MethodDescriptorProto.name"); + target = stream->WriteStringMaybeAliased( + 1, this->_internal_name(), target); + } + + // optional string input_type = 2; + if (cached_has_bits & 0x00000002u) { + ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::VerifyUTF8StringNamedField( + this->_internal_input_type().data(), static_cast<int>(this->_internal_input_type().length()), + ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::SERIALIZE, + "google.protobuf.MethodDescriptorProto.input_type"); + target = stream->WriteStringMaybeAliased( + 2, this->_internal_input_type(), target); + } + + // optional string output_type = 3; + if (cached_has_bits & 0x00000004u) { + ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::VerifyUTF8StringNamedField( + this->_internal_output_type().data(), static_cast<int>(this->_internal_output_type().length()), + ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::SERIALIZE, + "google.protobuf.MethodDescriptorProto.output_type"); + target = stream->WriteStringMaybeAliased( + 3, this->_internal_output_type(), target); + } + + // optional .google.protobuf.MethodOptions options = 4; + if (cached_has_bits & 0x00000008u) { + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite:: + InternalWriteMessage(4, _Internal::options(this), + _Internal::options(this).GetCachedSize(), target, stream); + } + + // optional bool client_streaming = 5 [default = false]; + if (cached_has_bits & 0x00000010u) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteBoolToArray(5, this->_internal_client_streaming(), target); + } + + // optional bool server_streaming = 6 [default = false]; + if (cached_has_bits & 0x00000020u) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteBoolToArray(6, this->_internal_server_streaming(), target); + } + + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + target = ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( + _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.MethodDescriptorProto) + return target; +} + +size_t MethodDescriptorProto::ByteSizeLong() const { +// @@protoc_insertion_point(message_byte_size_start:google.protobuf.MethodDescriptorProto) + size_t total_size = 0; + + uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + cached_has_bits = _impl_._has_bits_[0]; + if (cached_has_bits & 0x0000003fu) { + // optional string name = 1; + if (cached_has_bits & 0x00000001u) { + total_size += 1 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize( + this->_internal_name()); + } + + // optional string input_type = 2; + if (cached_has_bits & 0x00000002u) { + total_size += 1 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize( + this->_internal_input_type()); + } + + // optional string output_type = 3; + if (cached_has_bits & 0x00000004u) { + total_size += 1 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize( + this->_internal_output_type()); + } + + // optional .google.protobuf.MethodOptions options = 4; + if (cached_has_bits & 0x00000008u) { + total_size += 1 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::MessageSize( + *_impl_.options_); + } + + // optional bool client_streaming = 5 [default = false]; + if (cached_has_bits & 0x00000010u) { + total_size += 1 + 1; + } + + // optional bool server_streaming = 6 [default = false]; + if (cached_has_bits & 0x00000020u) { + total_size += 1 + 1; + } + + } + return MaybeComputeUnknownFieldsSize(total_size, &_impl_._cached_size_); +} + +const ::PROTOBUF_NAMESPACE_ID::Message::ClassData MethodDescriptorProto::_class_data_ = { + ::PROTOBUF_NAMESPACE_ID::Message::CopyWithSourceCheck, + MethodDescriptorProto::MergeImpl +}; +const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*MethodDescriptorProto::GetClassData() const { return &_class_data_; } + + +void MethodDescriptorProto::MergeImpl(::PROTOBUF_NAMESPACE_ID::Message& to_msg, const ::PROTOBUF_NAMESPACE_ID::Message& from_msg) { + auto* const _this = static_cast<MethodDescriptorProto*>(&to_msg); + auto& from = static_cast<const MethodDescriptorProto&>(from_msg); + // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.MethodDescriptorProto) + GOOGLE_DCHECK_NE(&from, _this); + uint32_t cached_has_bits = 0; + (void) cached_has_bits; + + cached_has_bits = from._impl_._has_bits_[0]; + if (cached_has_bits & 0x0000003fu) { + if (cached_has_bits & 0x00000001u) { + _this->_internal_set_name(from._internal_name()); + } + if (cached_has_bits & 0x00000002u) { + _this->_internal_set_input_type(from._internal_input_type()); + } + if (cached_has_bits & 0x00000004u) { + _this->_internal_set_output_type(from._internal_output_type()); + } + if (cached_has_bits & 0x00000008u) { + _this->_internal_mutable_options()->::PROTOBUF_NAMESPACE_ID::MethodOptions::MergeFrom( + from._internal_options()); + } + if (cached_has_bits & 0x00000010u) { + _this->_impl_.client_streaming_ = from._impl_.client_streaming_; + } + if (cached_has_bits & 0x00000020u) { + _this->_impl_.server_streaming_ = from._impl_.server_streaming_; + } + _this->_impl_._has_bits_[0] |= cached_has_bits; + } + _this->_internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); +} + +void MethodDescriptorProto::CopyFrom(const MethodDescriptorProto& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.MethodDescriptorProto) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool MethodDescriptorProto::IsInitialized() const { + if (_internal_has_options()) { + if (!_impl_.options_->IsInitialized()) return false; + } + return true; +} + +void MethodDescriptorProto::InternalSwap(MethodDescriptorProto* other) { + using std::swap; + auto* lhs_arena = GetArenaForAllocation(); + auto* rhs_arena = other->GetArenaForAllocation(); + _internal_metadata_.InternalSwap(&other->_internal_metadata_); + swap(_impl_._has_bits_[0], other->_impl_._has_bits_[0]); + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::InternalSwap( + &_impl_.name_, lhs_arena, + &other->_impl_.name_, rhs_arena + ); + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::InternalSwap( + &_impl_.input_type_, lhs_arena, + &other->_impl_.input_type_, rhs_arena + ); + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::InternalSwap( + &_impl_.output_type_, lhs_arena, + &other->_impl_.output_type_, rhs_arena + ); + ::PROTOBUF_NAMESPACE_ID::internal::memswap< + PROTOBUF_FIELD_OFFSET(MethodDescriptorProto, _impl_.server_streaming_) + + sizeof(MethodDescriptorProto::_impl_.server_streaming_) + - PROTOBUF_FIELD_OFFSET(MethodDescriptorProto, _impl_.options_)>( + reinterpret_cast<char*>(&_impl_.options_), + reinterpret_cast<char*>(&other->_impl_.options_)); +} + +::PROTOBUF_NAMESPACE_ID::Metadata MethodDescriptorProto::GetMetadata() const { + return ::_pbi::AssignDescriptors( + &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_getter, &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_once, + file_level_metadata_google_2fprotobuf_2fdescriptor_2eproto[12]); +} + +// =================================================================== + +class FileOptions::_Internal { + public: + using HasBits = decltype(std::declval<FileOptions>()._impl_._has_bits_); + static void set_has_java_package(HasBits* has_bits) { + (*has_bits)[0] |= 1u; + } + static void set_has_java_outer_classname(HasBits* has_bits) { + (*has_bits)[0] |= 2u; + } + static void set_has_java_multiple_files(HasBits* has_bits) { + (*has_bits)[0] |= 1024u; + } + static void set_has_java_generate_equals_and_hash(HasBits* has_bits) { + (*has_bits)[0] |= 2048u; + } + static void set_has_java_string_check_utf8(HasBits* has_bits) { + (*has_bits)[0] |= 4096u; + } + static void set_has_optimize_for(HasBits* has_bits) { + (*has_bits)[0] |= 262144u; + } + static void set_has_go_package(HasBits* has_bits) { + (*has_bits)[0] |= 4u; + } + static void set_has_cc_generic_services(HasBits* has_bits) { + (*has_bits)[0] |= 8192u; + } + static void set_has_java_generic_services(HasBits* has_bits) { + (*has_bits)[0] |= 16384u; + } + static void set_has_py_generic_services(HasBits* has_bits) { + (*has_bits)[0] |= 32768u; + } + static void set_has_php_generic_services(HasBits* has_bits) { + (*has_bits)[0] |= 65536u; + } + static void set_has_deprecated(HasBits* has_bits) { + (*has_bits)[0] |= 131072u; + } + static void set_has_cc_enable_arenas(HasBits* has_bits) { + (*has_bits)[0] |= 524288u; + } + static void set_has_objc_class_prefix(HasBits* has_bits) { + (*has_bits)[0] |= 8u; + } + static void set_has_csharp_namespace(HasBits* has_bits) { + (*has_bits)[0] |= 16u; + } + static void set_has_swift_prefix(HasBits* has_bits) { + (*has_bits)[0] |= 32u; + } + static void set_has_php_class_prefix(HasBits* has_bits) { + (*has_bits)[0] |= 64u; + } + static void set_has_php_namespace(HasBits* has_bits) { + (*has_bits)[0] |= 128u; + } + static void set_has_php_metadata_namespace(HasBits* has_bits) { + (*has_bits)[0] |= 256u; + } + static void set_has_ruby_package(HasBits* has_bits) { + (*has_bits)[0] |= 512u; + } +}; + +FileOptions::FileOptions(::PROTOBUF_NAMESPACE_ID::Arena* arena, + bool is_message_owned) + : ::PROTOBUF_NAMESPACE_ID::Message(arena, is_message_owned) { + SharedCtor(arena, is_message_owned); + // @@protoc_insertion_point(arena_constructor:google.protobuf.FileOptions) +} +FileOptions::FileOptions(const FileOptions& from) + : ::PROTOBUF_NAMESPACE_ID::Message() { + FileOptions* const _this = this; (void)_this; + new (&_impl_) Impl_{ + /*decltype(_impl_._extensions_)*/{} + , decltype(_impl_._has_bits_){from._impl_._has_bits_} + , /*decltype(_impl_._cached_size_)*/{} + , decltype(_impl_.uninterpreted_option_){from._impl_.uninterpreted_option_} + , decltype(_impl_.java_package_){} + , decltype(_impl_.java_outer_classname_){} + , decltype(_impl_.go_package_){} + , decltype(_impl_.objc_class_prefix_){} + , decltype(_impl_.csharp_namespace_){} + , decltype(_impl_.swift_prefix_){} + , decltype(_impl_.php_class_prefix_){} + , decltype(_impl_.php_namespace_){} + , decltype(_impl_.php_metadata_namespace_){} + , decltype(_impl_.ruby_package_){} + , decltype(_impl_.java_multiple_files_){} + , decltype(_impl_.java_generate_equals_and_hash_){} + , decltype(_impl_.java_string_check_utf8_){} + , decltype(_impl_.cc_generic_services_){} + , decltype(_impl_.java_generic_services_){} + , decltype(_impl_.py_generic_services_){} + , decltype(_impl_.php_generic_services_){} + , decltype(_impl_.deprecated_){} + , decltype(_impl_.optimize_for_){} + , decltype(_impl_.cc_enable_arenas_){}}; + + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); + _impl_._extensions_.MergeFrom(internal_default_instance(), from._impl_._extensions_); + _impl_.java_package_.InitDefault(); + #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + _impl_.java_package_.Set("", GetArenaForAllocation()); + #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (from._internal_has_java_package()) { + _this->_impl_.java_package_.Set(from._internal_java_package(), + _this->GetArenaForAllocation()); + } + _impl_.java_outer_classname_.InitDefault(); + #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + _impl_.java_outer_classname_.Set("", GetArenaForAllocation()); + #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (from._internal_has_java_outer_classname()) { + _this->_impl_.java_outer_classname_.Set(from._internal_java_outer_classname(), + _this->GetArenaForAllocation()); + } + _impl_.go_package_.InitDefault(); + #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + _impl_.go_package_.Set("", GetArenaForAllocation()); + #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (from._internal_has_go_package()) { + _this->_impl_.go_package_.Set(from._internal_go_package(), + _this->GetArenaForAllocation()); + } + _impl_.objc_class_prefix_.InitDefault(); + #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + _impl_.objc_class_prefix_.Set("", GetArenaForAllocation()); + #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (from._internal_has_objc_class_prefix()) { + _this->_impl_.objc_class_prefix_.Set(from._internal_objc_class_prefix(), + _this->GetArenaForAllocation()); + } + _impl_.csharp_namespace_.InitDefault(); + #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + _impl_.csharp_namespace_.Set("", GetArenaForAllocation()); + #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (from._internal_has_csharp_namespace()) { + _this->_impl_.csharp_namespace_.Set(from._internal_csharp_namespace(), + _this->GetArenaForAllocation()); + } + _impl_.swift_prefix_.InitDefault(); + #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + _impl_.swift_prefix_.Set("", GetArenaForAllocation()); + #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (from._internal_has_swift_prefix()) { + _this->_impl_.swift_prefix_.Set(from._internal_swift_prefix(), + _this->GetArenaForAllocation()); + } + _impl_.php_class_prefix_.InitDefault(); + #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + _impl_.php_class_prefix_.Set("", GetArenaForAllocation()); + #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (from._internal_has_php_class_prefix()) { + _this->_impl_.php_class_prefix_.Set(from._internal_php_class_prefix(), + _this->GetArenaForAllocation()); + } + _impl_.php_namespace_.InitDefault(); + #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + _impl_.php_namespace_.Set("", GetArenaForAllocation()); + #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (from._internal_has_php_namespace()) { + _this->_impl_.php_namespace_.Set(from._internal_php_namespace(), + _this->GetArenaForAllocation()); + } + _impl_.php_metadata_namespace_.InitDefault(); + #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + _impl_.php_metadata_namespace_.Set("", GetArenaForAllocation()); + #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (from._internal_has_php_metadata_namespace()) { + _this->_impl_.php_metadata_namespace_.Set(from._internal_php_metadata_namespace(), + _this->GetArenaForAllocation()); + } + _impl_.ruby_package_.InitDefault(); + #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + _impl_.ruby_package_.Set("", GetArenaForAllocation()); + #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (from._internal_has_ruby_package()) { + _this->_impl_.ruby_package_.Set(from._internal_ruby_package(), + _this->GetArenaForAllocation()); + } + ::memcpy(&_impl_.java_multiple_files_, &from._impl_.java_multiple_files_, + static_cast<size_t>(reinterpret_cast<char*>(&_impl_.cc_enable_arenas_) - + reinterpret_cast<char*>(&_impl_.java_multiple_files_)) + sizeof(_impl_.cc_enable_arenas_)); + // @@protoc_insertion_point(copy_constructor:google.protobuf.FileOptions) +} + +inline void FileOptions::SharedCtor( + ::_pb::Arena* arena, bool is_message_owned) { + (void)arena; + (void)is_message_owned; + new (&_impl_) Impl_{ + /*decltype(_impl_._extensions_)*/{::_pbi::ArenaInitialized(), arena} + , decltype(_impl_._has_bits_){} + , /*decltype(_impl_._cached_size_)*/{} + , decltype(_impl_.uninterpreted_option_){arena} + , decltype(_impl_.java_package_){} + , decltype(_impl_.java_outer_classname_){} + , decltype(_impl_.go_package_){} + , decltype(_impl_.objc_class_prefix_){} + , decltype(_impl_.csharp_namespace_){} + , decltype(_impl_.swift_prefix_){} + , decltype(_impl_.php_class_prefix_){} + , decltype(_impl_.php_namespace_){} + , decltype(_impl_.php_metadata_namespace_){} + , decltype(_impl_.ruby_package_){} + , decltype(_impl_.java_multiple_files_){false} + , decltype(_impl_.java_generate_equals_and_hash_){false} + , decltype(_impl_.java_string_check_utf8_){false} + , decltype(_impl_.cc_generic_services_){false} + , decltype(_impl_.java_generic_services_){false} + , decltype(_impl_.py_generic_services_){false} + , decltype(_impl_.php_generic_services_){false} + , decltype(_impl_.deprecated_){false} + , decltype(_impl_.optimize_for_){1} + , decltype(_impl_.cc_enable_arenas_){true} + }; + _impl_.java_package_.InitDefault(); + #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + _impl_.java_package_.Set("", GetArenaForAllocation()); + #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + _impl_.java_outer_classname_.InitDefault(); + #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + _impl_.java_outer_classname_.Set("", GetArenaForAllocation()); + #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + _impl_.go_package_.InitDefault(); + #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + _impl_.go_package_.Set("", GetArenaForAllocation()); + #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + _impl_.objc_class_prefix_.InitDefault(); + #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + _impl_.objc_class_prefix_.Set("", GetArenaForAllocation()); + #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + _impl_.csharp_namespace_.InitDefault(); + #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + _impl_.csharp_namespace_.Set("", GetArenaForAllocation()); + #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + _impl_.swift_prefix_.InitDefault(); + #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + _impl_.swift_prefix_.Set("", GetArenaForAllocation()); + #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + _impl_.php_class_prefix_.InitDefault(); + #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + _impl_.php_class_prefix_.Set("", GetArenaForAllocation()); + #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + _impl_.php_namespace_.InitDefault(); + #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + _impl_.php_namespace_.Set("", GetArenaForAllocation()); + #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + _impl_.php_metadata_namespace_.InitDefault(); + #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + _impl_.php_metadata_namespace_.Set("", GetArenaForAllocation()); + #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + _impl_.ruby_package_.InitDefault(); + #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + _impl_.ruby_package_.Set("", GetArenaForAllocation()); + #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING +} + +FileOptions::~FileOptions() { + // @@protoc_insertion_point(destructor:google.protobuf.FileOptions) + if (auto *arena = _internal_metadata_.DeleteReturnArena<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>()) { + (void)arena; + return; + } + SharedDtor(); +} + +inline void FileOptions::SharedDtor() { + GOOGLE_DCHECK(GetArenaForAllocation() == nullptr); + _impl_._extensions_.~ExtensionSet(); + _impl_.uninterpreted_option_.~RepeatedPtrField(); + _impl_.java_package_.Destroy(); + _impl_.java_outer_classname_.Destroy(); + _impl_.go_package_.Destroy(); + _impl_.objc_class_prefix_.Destroy(); + _impl_.csharp_namespace_.Destroy(); + _impl_.swift_prefix_.Destroy(); + _impl_.php_class_prefix_.Destroy(); + _impl_.php_namespace_.Destroy(); + _impl_.php_metadata_namespace_.Destroy(); + _impl_.ruby_package_.Destroy(); +} + +void FileOptions::SetCachedSize(int size) const { + _impl_._cached_size_.Set(size); +} + +void FileOptions::Clear() { +// @@protoc_insertion_point(message_clear_start:google.protobuf.FileOptions) + uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + _impl_._extensions_.Clear(); + _impl_.uninterpreted_option_.Clear(); + cached_has_bits = _impl_._has_bits_[0]; + if (cached_has_bits & 0x000000ffu) { + if (cached_has_bits & 0x00000001u) { + _impl_.java_package_.ClearNonDefaultToEmpty(); + } + if (cached_has_bits & 0x00000002u) { + _impl_.java_outer_classname_.ClearNonDefaultToEmpty(); + } + if (cached_has_bits & 0x00000004u) { + _impl_.go_package_.ClearNonDefaultToEmpty(); + } + if (cached_has_bits & 0x00000008u) { + _impl_.objc_class_prefix_.ClearNonDefaultToEmpty(); + } + if (cached_has_bits & 0x00000010u) { + _impl_.csharp_namespace_.ClearNonDefaultToEmpty(); + } + if (cached_has_bits & 0x00000020u) { + _impl_.swift_prefix_.ClearNonDefaultToEmpty(); + } + if (cached_has_bits & 0x00000040u) { + _impl_.php_class_prefix_.ClearNonDefaultToEmpty(); + } + if (cached_has_bits & 0x00000080u) { + _impl_.php_namespace_.ClearNonDefaultToEmpty(); + } + } + if (cached_has_bits & 0x00000300u) { + if (cached_has_bits & 0x00000100u) { + _impl_.php_metadata_namespace_.ClearNonDefaultToEmpty(); + } + if (cached_has_bits & 0x00000200u) { + _impl_.ruby_package_.ClearNonDefaultToEmpty(); + } + } + if (cached_has_bits & 0x0000fc00u) { + ::memset(&_impl_.java_multiple_files_, 0, static_cast<size_t>( + reinterpret_cast<char*>(&_impl_.py_generic_services_) - + reinterpret_cast<char*>(&_impl_.java_multiple_files_)) + sizeof(_impl_.py_generic_services_)); + } + if (cached_has_bits & 0x000f0000u) { + ::memset(&_impl_.php_generic_services_, 0, static_cast<size_t>( + reinterpret_cast<char*>(&_impl_.deprecated_) - + reinterpret_cast<char*>(&_impl_.php_generic_services_)) + sizeof(_impl_.deprecated_)); + _impl_.optimize_for_ = 1; + _impl_.cc_enable_arenas_ = true; + } + _impl_._has_bits_.Clear(); + _internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); +} + +const char* FileOptions::_InternalParse(const char* ptr, ::_pbi::ParseContext* ctx) { +#define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure + _Internal::HasBits has_bits{}; + while (!ctx->Done(&ptr)) { + uint32_t tag; + ptr = ::_pbi::ReadTag(ptr, &tag); + switch (tag >> 3) { + // optional string java_package = 1; + case 1: + if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 10)) { + auto str = _internal_mutable_java_package(); + ptr = ::_pbi::InlineGreedyStringParser(str, ptr, ctx); + CHK_(ptr); + #ifndef NDEBUG + ::_pbi::VerifyUTF8(str, "google.protobuf.FileOptions.java_package"); + #endif // !NDEBUG + } else + goto handle_unusual; + continue; + // optional string java_outer_classname = 8; + case 8: + if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 66)) { + auto str = _internal_mutable_java_outer_classname(); + ptr = ::_pbi::InlineGreedyStringParser(str, ptr, ctx); + CHK_(ptr); + #ifndef NDEBUG + ::_pbi::VerifyUTF8(str, "google.protobuf.FileOptions.java_outer_classname"); + #endif // !NDEBUG + } else + goto handle_unusual; + continue; + // optional .google.protobuf.FileOptions.OptimizeMode optimize_for = 9 [default = SPEED]; + case 9: + if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 72)) { + uint64_t val = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr); + CHK_(ptr); + if (PROTOBUF_PREDICT_TRUE(::PROTOBUF_NAMESPACE_ID::FileOptions_OptimizeMode_IsValid(val))) { + _internal_set_optimize_for(static_cast<::PROTOBUF_NAMESPACE_ID::FileOptions_OptimizeMode>(val)); + } else { + ::PROTOBUF_NAMESPACE_ID::internal::WriteVarint(9, val, mutable_unknown_fields()); + } + } else + goto handle_unusual; + continue; + // optional bool java_multiple_files = 10 [default = false]; + case 10: + if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 80)) { + _Internal::set_has_java_multiple_files(&has_bits); + _impl_.java_multiple_files_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr); + CHK_(ptr); + } else + goto handle_unusual; + continue; + // optional string go_package = 11; + case 11: + if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 90)) { + auto str = _internal_mutable_go_package(); + ptr = ::_pbi::InlineGreedyStringParser(str, ptr, ctx); + CHK_(ptr); + #ifndef NDEBUG + ::_pbi::VerifyUTF8(str, "google.protobuf.FileOptions.go_package"); + #endif // !NDEBUG + } else + goto handle_unusual; + continue; + // optional bool cc_generic_services = 16 [default = false]; + case 16: + if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 128)) { + _Internal::set_has_cc_generic_services(&has_bits); + _impl_.cc_generic_services_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr); + CHK_(ptr); + } else + goto handle_unusual; + continue; + // optional bool java_generic_services = 17 [default = false]; + case 17: + if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 136)) { + _Internal::set_has_java_generic_services(&has_bits); + _impl_.java_generic_services_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr); + CHK_(ptr); + } else + goto handle_unusual; + continue; + // optional bool py_generic_services = 18 [default = false]; + case 18: + if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 144)) { + _Internal::set_has_py_generic_services(&has_bits); + _impl_.py_generic_services_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr); + CHK_(ptr); + } else + goto handle_unusual; + continue; + // optional bool java_generate_equals_and_hash = 20 [deprecated = true]; + case 20: + if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 160)) { + _Internal::set_has_java_generate_equals_and_hash(&has_bits); + _impl_.java_generate_equals_and_hash_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr); + CHK_(ptr); + } else + goto handle_unusual; + continue; + // optional bool deprecated = 23 [default = false]; + case 23: + if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 184)) { + _Internal::set_has_deprecated(&has_bits); + _impl_.deprecated_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr); + CHK_(ptr); + } else + goto handle_unusual; + continue; + // optional bool java_string_check_utf8 = 27 [default = false]; + case 27: + if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 216)) { + _Internal::set_has_java_string_check_utf8(&has_bits); + _impl_.java_string_check_utf8_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr); + CHK_(ptr); + } else + goto handle_unusual; + continue; + // optional bool cc_enable_arenas = 31 [default = true]; + case 31: + if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 248)) { + _Internal::set_has_cc_enable_arenas(&has_bits); + _impl_.cc_enable_arenas_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr); + CHK_(ptr); + } else + goto handle_unusual; + continue; + // optional string objc_class_prefix = 36; + case 36: + if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 34)) { + auto str = _internal_mutable_objc_class_prefix(); + ptr = ::_pbi::InlineGreedyStringParser(str, ptr, ctx); + CHK_(ptr); + #ifndef NDEBUG + ::_pbi::VerifyUTF8(str, "google.protobuf.FileOptions.objc_class_prefix"); + #endif // !NDEBUG + } else + goto handle_unusual; + continue; + // optional string csharp_namespace = 37; + case 37: + if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 42)) { + auto str = _internal_mutable_csharp_namespace(); + ptr = ::_pbi::InlineGreedyStringParser(str, ptr, ctx); + CHK_(ptr); + #ifndef NDEBUG + ::_pbi::VerifyUTF8(str, "google.protobuf.FileOptions.csharp_namespace"); + #endif // !NDEBUG + } else + goto handle_unusual; + continue; + // optional string swift_prefix = 39; + case 39: + if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 58)) { + auto str = _internal_mutable_swift_prefix(); + ptr = ::_pbi::InlineGreedyStringParser(str, ptr, ctx); + CHK_(ptr); + #ifndef NDEBUG + ::_pbi::VerifyUTF8(str, "google.protobuf.FileOptions.swift_prefix"); + #endif // !NDEBUG + } else + goto handle_unusual; + continue; + // optional string php_class_prefix = 40; + case 40: + if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 66)) { + auto str = _internal_mutable_php_class_prefix(); + ptr = ::_pbi::InlineGreedyStringParser(str, ptr, ctx); + CHK_(ptr); + #ifndef NDEBUG + ::_pbi::VerifyUTF8(str, "google.protobuf.FileOptions.php_class_prefix"); + #endif // !NDEBUG + } else + goto handle_unusual; + continue; + // optional string php_namespace = 41; + case 41: + if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 74)) { + auto str = _internal_mutable_php_namespace(); + ptr = ::_pbi::InlineGreedyStringParser(str, ptr, ctx); + CHK_(ptr); + #ifndef NDEBUG + ::_pbi::VerifyUTF8(str, "google.protobuf.FileOptions.php_namespace"); + #endif // !NDEBUG + } else + goto handle_unusual; + continue; + // optional bool php_generic_services = 42 [default = false]; + case 42: + if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 80)) { + _Internal::set_has_php_generic_services(&has_bits); + _impl_.php_generic_services_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr); + CHK_(ptr); + } else + goto handle_unusual; + continue; + // optional string php_metadata_namespace = 44; + case 44: + if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 98)) { + auto str = _internal_mutable_php_metadata_namespace(); + ptr = ::_pbi::InlineGreedyStringParser(str, ptr, ctx); + CHK_(ptr); + #ifndef NDEBUG + ::_pbi::VerifyUTF8(str, "google.protobuf.FileOptions.php_metadata_namespace"); + #endif // !NDEBUG + } else + goto handle_unusual; + continue; + // optional string ruby_package = 45; + case 45: + if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 106)) { + auto str = _internal_mutable_ruby_package(); + ptr = ::_pbi::InlineGreedyStringParser(str, ptr, ctx); + CHK_(ptr); + #ifndef NDEBUG + ::_pbi::VerifyUTF8(str, "google.protobuf.FileOptions.ruby_package"); + #endif // !NDEBUG + } else + goto handle_unusual; + continue; + // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; + case 999: + if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 58)) { + ptr -= 2; + do { + ptr += 2; + ptr = ctx->ParseMessage(_internal_add_uninterpreted_option(), ptr); + CHK_(ptr); + if (!ctx->DataAvailable(ptr)) break; + } while (::PROTOBUF_NAMESPACE_ID::internal::ExpectTag<7994>(ptr)); + } else + goto handle_unusual; + continue; + default: + goto handle_unusual; + } // switch + handle_unusual: + if ((tag == 0) || ((tag & 7) == 4)) { + CHK_(ptr); + ctx->SetLastTag(tag); + goto message_done; + } + if ((8000u <= tag)) { + ptr = _impl_._extensions_.ParseField(tag, ptr, internal_default_instance(), &_internal_metadata_, ctx); + CHK_(ptr != nullptr); + continue; + } + ptr = UnknownFieldParse( + tag, + _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(), + ptr, ctx); + CHK_(ptr != nullptr); + } // while +message_done: + _impl_._has_bits_.Or(has_bits); + return ptr; +failure: + ptr = nullptr; + goto message_done; +#undef CHK_ +} + +uint8_t* FileOptions::_InternalSerialize( + uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const { + // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.FileOptions) + uint32_t cached_has_bits = 0; + (void) cached_has_bits; + + cached_has_bits = _impl_._has_bits_[0]; + // optional string java_package = 1; + if (cached_has_bits & 0x00000001u) { + ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::VerifyUTF8StringNamedField( + this->_internal_java_package().data(), static_cast<int>(this->_internal_java_package().length()), + ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::SERIALIZE, + "google.protobuf.FileOptions.java_package"); + target = stream->WriteStringMaybeAliased( + 1, this->_internal_java_package(), target); + } + + // optional string java_outer_classname = 8; + if (cached_has_bits & 0x00000002u) { + ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::VerifyUTF8StringNamedField( + this->_internal_java_outer_classname().data(), static_cast<int>(this->_internal_java_outer_classname().length()), + ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::SERIALIZE, + "google.protobuf.FileOptions.java_outer_classname"); + target = stream->WriteStringMaybeAliased( + 8, this->_internal_java_outer_classname(), target); + } + + // optional .google.protobuf.FileOptions.OptimizeMode optimize_for = 9 [default = SPEED]; + if (cached_has_bits & 0x00040000u) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteEnumToArray( + 9, this->_internal_optimize_for(), target); + } + + // optional bool java_multiple_files = 10 [default = false]; + if (cached_has_bits & 0x00000400u) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteBoolToArray(10, this->_internal_java_multiple_files(), target); + } + + // optional string go_package = 11; + if (cached_has_bits & 0x00000004u) { + ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::VerifyUTF8StringNamedField( + this->_internal_go_package().data(), static_cast<int>(this->_internal_go_package().length()), + ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::SERIALIZE, + "google.protobuf.FileOptions.go_package"); + target = stream->WriteStringMaybeAliased( + 11, this->_internal_go_package(), target); + } + + // optional bool cc_generic_services = 16 [default = false]; + if (cached_has_bits & 0x00002000u) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteBoolToArray(16, this->_internal_cc_generic_services(), target); + } + + // optional bool java_generic_services = 17 [default = false]; + if (cached_has_bits & 0x00004000u) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteBoolToArray(17, this->_internal_java_generic_services(), target); + } + + // optional bool py_generic_services = 18 [default = false]; + if (cached_has_bits & 0x00008000u) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteBoolToArray(18, this->_internal_py_generic_services(), target); + } + + // optional bool java_generate_equals_and_hash = 20 [deprecated = true]; + if (cached_has_bits & 0x00000800u) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteBoolToArray(20, this->_internal_java_generate_equals_and_hash(), target); + } + + // optional bool deprecated = 23 [default = false]; + if (cached_has_bits & 0x00020000u) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteBoolToArray(23, this->_internal_deprecated(), target); + } + + // optional bool java_string_check_utf8 = 27 [default = false]; + if (cached_has_bits & 0x00001000u) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteBoolToArray(27, this->_internal_java_string_check_utf8(), target); + } + + // optional bool cc_enable_arenas = 31 [default = true]; + if (cached_has_bits & 0x00080000u) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteBoolToArray(31, this->_internal_cc_enable_arenas(), target); + } + + // optional string objc_class_prefix = 36; + if (cached_has_bits & 0x00000008u) { + ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::VerifyUTF8StringNamedField( + this->_internal_objc_class_prefix().data(), static_cast<int>(this->_internal_objc_class_prefix().length()), + ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::SERIALIZE, + "google.protobuf.FileOptions.objc_class_prefix"); + target = stream->WriteStringMaybeAliased( + 36, this->_internal_objc_class_prefix(), target); + } + + // optional string csharp_namespace = 37; + if (cached_has_bits & 0x00000010u) { + ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::VerifyUTF8StringNamedField( + this->_internal_csharp_namespace().data(), static_cast<int>(this->_internal_csharp_namespace().length()), + ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::SERIALIZE, + "google.protobuf.FileOptions.csharp_namespace"); + target = stream->WriteStringMaybeAliased( + 37, this->_internal_csharp_namespace(), target); + } + + // optional string swift_prefix = 39; + if (cached_has_bits & 0x00000020u) { + ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::VerifyUTF8StringNamedField( + this->_internal_swift_prefix().data(), static_cast<int>(this->_internal_swift_prefix().length()), + ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::SERIALIZE, + "google.protobuf.FileOptions.swift_prefix"); + target = stream->WriteStringMaybeAliased( + 39, this->_internal_swift_prefix(), target); + } + + // optional string php_class_prefix = 40; + if (cached_has_bits & 0x00000040u) { + ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::VerifyUTF8StringNamedField( + this->_internal_php_class_prefix().data(), static_cast<int>(this->_internal_php_class_prefix().length()), + ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::SERIALIZE, + "google.protobuf.FileOptions.php_class_prefix"); + target = stream->WriteStringMaybeAliased( + 40, this->_internal_php_class_prefix(), target); + } + + // optional string php_namespace = 41; + if (cached_has_bits & 0x00000080u) { + ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::VerifyUTF8StringNamedField( + this->_internal_php_namespace().data(), static_cast<int>(this->_internal_php_namespace().length()), + ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::SERIALIZE, + "google.protobuf.FileOptions.php_namespace"); + target = stream->WriteStringMaybeAliased( + 41, this->_internal_php_namespace(), target); + } + + // optional bool php_generic_services = 42 [default = false]; + if (cached_has_bits & 0x00010000u) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteBoolToArray(42, this->_internal_php_generic_services(), target); + } + + // optional string php_metadata_namespace = 44; + if (cached_has_bits & 0x00000100u) { + ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::VerifyUTF8StringNamedField( + this->_internal_php_metadata_namespace().data(), static_cast<int>(this->_internal_php_metadata_namespace().length()), + ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::SERIALIZE, + "google.protobuf.FileOptions.php_metadata_namespace"); + target = stream->WriteStringMaybeAliased( + 44, this->_internal_php_metadata_namespace(), target); + } + + // optional string ruby_package = 45; + if (cached_has_bits & 0x00000200u) { + ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::VerifyUTF8StringNamedField( + this->_internal_ruby_package().data(), static_cast<int>(this->_internal_ruby_package().length()), + ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::SERIALIZE, + "google.protobuf.FileOptions.ruby_package"); + target = stream->WriteStringMaybeAliased( + 45, this->_internal_ruby_package(), target); + } + + // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; + for (unsigned i = 0, + n = static_cast<unsigned>(this->_internal_uninterpreted_option_size()); i < n; i++) { + const auto& repfield = this->_internal_uninterpreted_option(i); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite:: + InternalWriteMessage(999, repfield, repfield.GetCachedSize(), target, stream); + } + + // Extension range [1000, 536870912) + target = _impl_._extensions_._InternalSerialize( + internal_default_instance(), 1000, 536870912, target, stream); + + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + target = ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( + _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.FileOptions) + return target; +} + +size_t FileOptions::ByteSizeLong() const { +// @@protoc_insertion_point(message_byte_size_start:google.protobuf.FileOptions) + size_t total_size = 0; + + total_size += _impl_._extensions_.ByteSize(); + + uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; + total_size += 2UL * this->_internal_uninterpreted_option_size(); + for (const auto& msg : this->_impl_.uninterpreted_option_) { + total_size += + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::MessageSize(msg); + } + + cached_has_bits = _impl_._has_bits_[0]; + if (cached_has_bits & 0x000000ffu) { + // optional string java_package = 1; + if (cached_has_bits & 0x00000001u) { + total_size += 1 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize( + this->_internal_java_package()); + } + + // optional string java_outer_classname = 8; + if (cached_has_bits & 0x00000002u) { + total_size += 1 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize( + this->_internal_java_outer_classname()); + } + + // optional string go_package = 11; + if (cached_has_bits & 0x00000004u) { + total_size += 1 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize( + this->_internal_go_package()); + } + + // optional string objc_class_prefix = 36; + if (cached_has_bits & 0x00000008u) { + total_size += 2 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize( + this->_internal_objc_class_prefix()); + } + + // optional string csharp_namespace = 37; + if (cached_has_bits & 0x00000010u) { + total_size += 2 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize( + this->_internal_csharp_namespace()); + } + + // optional string swift_prefix = 39; + if (cached_has_bits & 0x00000020u) { + total_size += 2 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize( + this->_internal_swift_prefix()); + } + + // optional string php_class_prefix = 40; + if (cached_has_bits & 0x00000040u) { + total_size += 2 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize( + this->_internal_php_class_prefix()); + } + + // optional string php_namespace = 41; + if (cached_has_bits & 0x00000080u) { + total_size += 2 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize( + this->_internal_php_namespace()); + } + + } + if (cached_has_bits & 0x0000ff00u) { + // optional string php_metadata_namespace = 44; + if (cached_has_bits & 0x00000100u) { + total_size += 2 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize( + this->_internal_php_metadata_namespace()); + } + + // optional string ruby_package = 45; + if (cached_has_bits & 0x00000200u) { + total_size += 2 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize( + this->_internal_ruby_package()); + } + + // optional bool java_multiple_files = 10 [default = false]; + if (cached_has_bits & 0x00000400u) { + total_size += 1 + 1; + } + + // optional bool java_generate_equals_and_hash = 20 [deprecated = true]; + if (cached_has_bits & 0x00000800u) { + total_size += 2 + 1; + } + + // optional bool java_string_check_utf8 = 27 [default = false]; + if (cached_has_bits & 0x00001000u) { + total_size += 2 + 1; + } + + // optional bool cc_generic_services = 16 [default = false]; + if (cached_has_bits & 0x00002000u) { + total_size += 2 + 1; + } + + // optional bool java_generic_services = 17 [default = false]; + if (cached_has_bits & 0x00004000u) { + total_size += 2 + 1; + } + + // optional bool py_generic_services = 18 [default = false]; + if (cached_has_bits & 0x00008000u) { + total_size += 2 + 1; + } + + } + if (cached_has_bits & 0x000f0000u) { + // optional bool php_generic_services = 42 [default = false]; + if (cached_has_bits & 0x00010000u) { + total_size += 2 + 1; + } + + // optional bool deprecated = 23 [default = false]; + if (cached_has_bits & 0x00020000u) { + total_size += 2 + 1; + } + + // optional .google.protobuf.FileOptions.OptimizeMode optimize_for = 9 [default = SPEED]; + if (cached_has_bits & 0x00040000u) { + total_size += 1 + + ::_pbi::WireFormatLite::EnumSize(this->_internal_optimize_for()); + } + + // optional bool cc_enable_arenas = 31 [default = true]; + if (cached_has_bits & 0x00080000u) { + total_size += 2 + 1; + } + + } + return MaybeComputeUnknownFieldsSize(total_size, &_impl_._cached_size_); +} + +const ::PROTOBUF_NAMESPACE_ID::Message::ClassData FileOptions::_class_data_ = { + ::PROTOBUF_NAMESPACE_ID::Message::CopyWithSourceCheck, + FileOptions::MergeImpl +}; +const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*FileOptions::GetClassData() const { return &_class_data_; } + + +void FileOptions::MergeImpl(::PROTOBUF_NAMESPACE_ID::Message& to_msg, const ::PROTOBUF_NAMESPACE_ID::Message& from_msg) { + auto* const _this = static_cast<FileOptions*>(&to_msg); + auto& from = static_cast<const FileOptions&>(from_msg); + // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.FileOptions) + GOOGLE_DCHECK_NE(&from, _this); + uint32_t cached_has_bits = 0; + (void) cached_has_bits; + + _this->_impl_.uninterpreted_option_.MergeFrom(from._impl_.uninterpreted_option_); + cached_has_bits = from._impl_._has_bits_[0]; + if (cached_has_bits & 0x000000ffu) { + if (cached_has_bits & 0x00000001u) { + _this->_internal_set_java_package(from._internal_java_package()); + } + if (cached_has_bits & 0x00000002u) { + _this->_internal_set_java_outer_classname(from._internal_java_outer_classname()); + } + if (cached_has_bits & 0x00000004u) { + _this->_internal_set_go_package(from._internal_go_package()); + } + if (cached_has_bits & 0x00000008u) { + _this->_internal_set_objc_class_prefix(from._internal_objc_class_prefix()); + } + if (cached_has_bits & 0x00000010u) { + _this->_internal_set_csharp_namespace(from._internal_csharp_namespace()); + } + if (cached_has_bits & 0x00000020u) { + _this->_internal_set_swift_prefix(from._internal_swift_prefix()); + } + if (cached_has_bits & 0x00000040u) { + _this->_internal_set_php_class_prefix(from._internal_php_class_prefix()); + } + if (cached_has_bits & 0x00000080u) { + _this->_internal_set_php_namespace(from._internal_php_namespace()); + } + } + if (cached_has_bits & 0x0000ff00u) { + if (cached_has_bits & 0x00000100u) { + _this->_internal_set_php_metadata_namespace(from._internal_php_metadata_namespace()); + } + if (cached_has_bits & 0x00000200u) { + _this->_internal_set_ruby_package(from._internal_ruby_package()); + } + if (cached_has_bits & 0x00000400u) { + _this->_impl_.java_multiple_files_ = from._impl_.java_multiple_files_; + } + if (cached_has_bits & 0x00000800u) { + _this->_impl_.java_generate_equals_and_hash_ = from._impl_.java_generate_equals_and_hash_; + } + if (cached_has_bits & 0x00001000u) { + _this->_impl_.java_string_check_utf8_ = from._impl_.java_string_check_utf8_; + } + if (cached_has_bits & 0x00002000u) { + _this->_impl_.cc_generic_services_ = from._impl_.cc_generic_services_; + } + if (cached_has_bits & 0x00004000u) { + _this->_impl_.java_generic_services_ = from._impl_.java_generic_services_; + } + if (cached_has_bits & 0x00008000u) { + _this->_impl_.py_generic_services_ = from._impl_.py_generic_services_; + } + _this->_impl_._has_bits_[0] |= cached_has_bits; + } + if (cached_has_bits & 0x000f0000u) { + if (cached_has_bits & 0x00010000u) { + _this->_impl_.php_generic_services_ = from._impl_.php_generic_services_; + } + if (cached_has_bits & 0x00020000u) { + _this->_impl_.deprecated_ = from._impl_.deprecated_; + } + if (cached_has_bits & 0x00040000u) { + _this->_impl_.optimize_for_ = from._impl_.optimize_for_; + } + if (cached_has_bits & 0x00080000u) { + _this->_impl_.cc_enable_arenas_ = from._impl_.cc_enable_arenas_; + } + _this->_impl_._has_bits_[0] |= cached_has_bits; + } + _this->_impl_._extensions_.MergeFrom(internal_default_instance(), from._impl_._extensions_); + _this->_internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); +} + +void FileOptions::CopyFrom(const FileOptions& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.FileOptions) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool FileOptions::IsInitialized() const { + if (!_impl_._extensions_.IsInitialized()) { + return false; + } + + if (!::PROTOBUF_NAMESPACE_ID::internal::AllAreInitialized(_impl_.uninterpreted_option_)) + return false; + return true; +} + +void FileOptions::InternalSwap(FileOptions* other) { + using std::swap; + _impl_._extensions_.InternalSwap(&other->_impl_._extensions_); + auto* lhs_arena = GetArenaForAllocation(); + auto* rhs_arena = other->GetArenaForAllocation(); + _internal_metadata_.InternalSwap(&other->_internal_metadata_); + swap(_impl_._has_bits_[0], other->_impl_._has_bits_[0]); + _impl_.uninterpreted_option_.InternalSwap(&other->_impl_.uninterpreted_option_); + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::InternalSwap( + &_impl_.java_package_, lhs_arena, + &other->_impl_.java_package_, rhs_arena + ); + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::InternalSwap( + &_impl_.java_outer_classname_, lhs_arena, + &other->_impl_.java_outer_classname_, rhs_arena + ); + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::InternalSwap( + &_impl_.go_package_, lhs_arena, + &other->_impl_.go_package_, rhs_arena + ); + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::InternalSwap( + &_impl_.objc_class_prefix_, lhs_arena, + &other->_impl_.objc_class_prefix_, rhs_arena + ); + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::InternalSwap( + &_impl_.csharp_namespace_, lhs_arena, + &other->_impl_.csharp_namespace_, rhs_arena + ); + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::InternalSwap( + &_impl_.swift_prefix_, lhs_arena, + &other->_impl_.swift_prefix_, rhs_arena + ); + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::InternalSwap( + &_impl_.php_class_prefix_, lhs_arena, + &other->_impl_.php_class_prefix_, rhs_arena + ); + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::InternalSwap( + &_impl_.php_namespace_, lhs_arena, + &other->_impl_.php_namespace_, rhs_arena + ); + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::InternalSwap( + &_impl_.php_metadata_namespace_, lhs_arena, + &other->_impl_.php_metadata_namespace_, rhs_arena + ); + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::InternalSwap( + &_impl_.ruby_package_, lhs_arena, + &other->_impl_.ruby_package_, rhs_arena + ); + ::PROTOBUF_NAMESPACE_ID::internal::memswap< + PROTOBUF_FIELD_OFFSET(FileOptions, _impl_.deprecated_) + + sizeof(FileOptions::_impl_.deprecated_) + - PROTOBUF_FIELD_OFFSET(FileOptions, _impl_.java_multiple_files_)>( + reinterpret_cast<char*>(&_impl_.java_multiple_files_), + reinterpret_cast<char*>(&other->_impl_.java_multiple_files_)); + swap(_impl_.optimize_for_, other->_impl_.optimize_for_); + swap(_impl_.cc_enable_arenas_, other->_impl_.cc_enable_arenas_); +} + +::PROTOBUF_NAMESPACE_ID::Metadata FileOptions::GetMetadata() const { + return ::_pbi::AssignDescriptors( + &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_getter, &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_once, + file_level_metadata_google_2fprotobuf_2fdescriptor_2eproto[13]); +} + +// =================================================================== + +class MessageOptions::_Internal { + public: + using HasBits = decltype(std::declval<MessageOptions>()._impl_._has_bits_); + static void set_has_message_set_wire_format(HasBits* has_bits) { + (*has_bits)[0] |= 1u; + } + static void set_has_no_standard_descriptor_accessor(HasBits* has_bits) { + (*has_bits)[0] |= 2u; + } + static void set_has_deprecated(HasBits* has_bits) { + (*has_bits)[0] |= 4u; + } + static void set_has_map_entry(HasBits* has_bits) { + (*has_bits)[0] |= 8u; + } +}; + +MessageOptions::MessageOptions(::PROTOBUF_NAMESPACE_ID::Arena* arena, + bool is_message_owned) + : ::PROTOBUF_NAMESPACE_ID::Message(arena, is_message_owned) { + SharedCtor(arena, is_message_owned); + // @@protoc_insertion_point(arena_constructor:google.protobuf.MessageOptions) +} +MessageOptions::MessageOptions(const MessageOptions& from) + : ::PROTOBUF_NAMESPACE_ID::Message() { + MessageOptions* const _this = this; (void)_this; + new (&_impl_) Impl_{ + /*decltype(_impl_._extensions_)*/{} + , decltype(_impl_._has_bits_){from._impl_._has_bits_} + , /*decltype(_impl_._cached_size_)*/{} + , decltype(_impl_.uninterpreted_option_){from._impl_.uninterpreted_option_} + , decltype(_impl_.message_set_wire_format_){} + , decltype(_impl_.no_standard_descriptor_accessor_){} + , decltype(_impl_.deprecated_){} + , decltype(_impl_.map_entry_){}}; + + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); + _impl_._extensions_.MergeFrom(internal_default_instance(), from._impl_._extensions_); + ::memcpy(&_impl_.message_set_wire_format_, &from._impl_.message_set_wire_format_, + static_cast<size_t>(reinterpret_cast<char*>(&_impl_.map_entry_) - + reinterpret_cast<char*>(&_impl_.message_set_wire_format_)) + sizeof(_impl_.map_entry_)); + // @@protoc_insertion_point(copy_constructor:google.protobuf.MessageOptions) +} + +inline void MessageOptions::SharedCtor( + ::_pb::Arena* arena, bool is_message_owned) { + (void)arena; + (void)is_message_owned; + new (&_impl_) Impl_{ + /*decltype(_impl_._extensions_)*/{::_pbi::ArenaInitialized(), arena} + , decltype(_impl_._has_bits_){} + , /*decltype(_impl_._cached_size_)*/{} + , decltype(_impl_.uninterpreted_option_){arena} + , decltype(_impl_.message_set_wire_format_){false} + , decltype(_impl_.no_standard_descriptor_accessor_){false} + , decltype(_impl_.deprecated_){false} + , decltype(_impl_.map_entry_){false} + }; +} + +MessageOptions::~MessageOptions() { + // @@protoc_insertion_point(destructor:google.protobuf.MessageOptions) + if (auto *arena = _internal_metadata_.DeleteReturnArena<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>()) { + (void)arena; + return; + } + SharedDtor(); +} + +inline void MessageOptions::SharedDtor() { + GOOGLE_DCHECK(GetArenaForAllocation() == nullptr); + _impl_._extensions_.~ExtensionSet(); + _impl_.uninterpreted_option_.~RepeatedPtrField(); +} + +void MessageOptions::SetCachedSize(int size) const { + _impl_._cached_size_.Set(size); +} + +void MessageOptions::Clear() { +// @@protoc_insertion_point(message_clear_start:google.protobuf.MessageOptions) + uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + _impl_._extensions_.Clear(); + _impl_.uninterpreted_option_.Clear(); + ::memset(&_impl_.message_set_wire_format_, 0, static_cast<size_t>( + reinterpret_cast<char*>(&_impl_.map_entry_) - + reinterpret_cast<char*>(&_impl_.message_set_wire_format_)) + sizeof(_impl_.map_entry_)); + _impl_._has_bits_.Clear(); + _internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); +} + +const char* MessageOptions::_InternalParse(const char* ptr, ::_pbi::ParseContext* ctx) { +#define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure + _Internal::HasBits has_bits{}; + while (!ctx->Done(&ptr)) { + uint32_t tag; + ptr = ::_pbi::ReadTag(ptr, &tag); + switch (tag >> 3) { + // optional bool message_set_wire_format = 1 [default = false]; + case 1: + if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 8)) { + _Internal::set_has_message_set_wire_format(&has_bits); + _impl_.message_set_wire_format_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr); + CHK_(ptr); + } else + goto handle_unusual; + continue; + // optional bool no_standard_descriptor_accessor = 2 [default = false]; + case 2: + if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 16)) { + _Internal::set_has_no_standard_descriptor_accessor(&has_bits); + _impl_.no_standard_descriptor_accessor_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr); + CHK_(ptr); + } else + goto handle_unusual; + continue; + // optional bool deprecated = 3 [default = false]; + case 3: + if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 24)) { + _Internal::set_has_deprecated(&has_bits); + _impl_.deprecated_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr); + CHK_(ptr); + } else + goto handle_unusual; + continue; + // optional bool map_entry = 7; + case 7: + if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 56)) { + _Internal::set_has_map_entry(&has_bits); + _impl_.map_entry_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr); + CHK_(ptr); + } else + goto handle_unusual; + continue; + // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; + case 999: + if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 58)) { + ptr -= 2; + do { + ptr += 2; + ptr = ctx->ParseMessage(_internal_add_uninterpreted_option(), ptr); + CHK_(ptr); + if (!ctx->DataAvailable(ptr)) break; + } while (::PROTOBUF_NAMESPACE_ID::internal::ExpectTag<7994>(ptr)); + } else + goto handle_unusual; + continue; + default: + goto handle_unusual; + } // switch + handle_unusual: + if ((tag == 0) || ((tag & 7) == 4)) { + CHK_(ptr); + ctx->SetLastTag(tag); + goto message_done; + } + if ((8000u <= tag)) { + ptr = _impl_._extensions_.ParseField(tag, ptr, internal_default_instance(), &_internal_metadata_, ctx); + CHK_(ptr != nullptr); + continue; + } + ptr = UnknownFieldParse( + tag, + _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(), + ptr, ctx); + CHK_(ptr != nullptr); + } // while +message_done: + _impl_._has_bits_.Or(has_bits); + return ptr; +failure: + ptr = nullptr; + goto message_done; +#undef CHK_ +} + +uint8_t* MessageOptions::_InternalSerialize( + uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const { + // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.MessageOptions) + uint32_t cached_has_bits = 0; + (void) cached_has_bits; + + cached_has_bits = _impl_._has_bits_[0]; + // optional bool message_set_wire_format = 1 [default = false]; + if (cached_has_bits & 0x00000001u) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteBoolToArray(1, this->_internal_message_set_wire_format(), target); + } + + // optional bool no_standard_descriptor_accessor = 2 [default = false]; + if (cached_has_bits & 0x00000002u) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteBoolToArray(2, this->_internal_no_standard_descriptor_accessor(), target); + } + + // optional bool deprecated = 3 [default = false]; + if (cached_has_bits & 0x00000004u) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteBoolToArray(3, this->_internal_deprecated(), target); + } + + // optional bool map_entry = 7; + if (cached_has_bits & 0x00000008u) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteBoolToArray(7, this->_internal_map_entry(), target); + } + + // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; + for (unsigned i = 0, + n = static_cast<unsigned>(this->_internal_uninterpreted_option_size()); i < n; i++) { + const auto& repfield = this->_internal_uninterpreted_option(i); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite:: + InternalWriteMessage(999, repfield, repfield.GetCachedSize(), target, stream); + } + + // Extension range [1000, 536870912) + target = _impl_._extensions_._InternalSerialize( + internal_default_instance(), 1000, 536870912, target, stream); + + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + target = ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( + _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.MessageOptions) + return target; +} + +size_t MessageOptions::ByteSizeLong() const { +// @@protoc_insertion_point(message_byte_size_start:google.protobuf.MessageOptions) + size_t total_size = 0; + + total_size += _impl_._extensions_.ByteSize(); + + uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; + total_size += 2UL * this->_internal_uninterpreted_option_size(); + for (const auto& msg : this->_impl_.uninterpreted_option_) { + total_size += + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::MessageSize(msg); + } + + cached_has_bits = _impl_._has_bits_[0]; + if (cached_has_bits & 0x0000000fu) { + // optional bool message_set_wire_format = 1 [default = false]; + if (cached_has_bits & 0x00000001u) { + total_size += 1 + 1; + } + + // optional bool no_standard_descriptor_accessor = 2 [default = false]; + if (cached_has_bits & 0x00000002u) { + total_size += 1 + 1; + } + + // optional bool deprecated = 3 [default = false]; + if (cached_has_bits & 0x00000004u) { + total_size += 1 + 1; + } + + // optional bool map_entry = 7; + if (cached_has_bits & 0x00000008u) { + total_size += 1 + 1; + } + + } + return MaybeComputeUnknownFieldsSize(total_size, &_impl_._cached_size_); +} + +const ::PROTOBUF_NAMESPACE_ID::Message::ClassData MessageOptions::_class_data_ = { + ::PROTOBUF_NAMESPACE_ID::Message::CopyWithSourceCheck, + MessageOptions::MergeImpl +}; +const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*MessageOptions::GetClassData() const { return &_class_data_; } + + +void MessageOptions::MergeImpl(::PROTOBUF_NAMESPACE_ID::Message& to_msg, const ::PROTOBUF_NAMESPACE_ID::Message& from_msg) { + auto* const _this = static_cast<MessageOptions*>(&to_msg); + auto& from = static_cast<const MessageOptions&>(from_msg); + // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.MessageOptions) + GOOGLE_DCHECK_NE(&from, _this); + uint32_t cached_has_bits = 0; + (void) cached_has_bits; + + _this->_impl_.uninterpreted_option_.MergeFrom(from._impl_.uninterpreted_option_); + cached_has_bits = from._impl_._has_bits_[0]; + if (cached_has_bits & 0x0000000fu) { + if (cached_has_bits & 0x00000001u) { + _this->_impl_.message_set_wire_format_ = from._impl_.message_set_wire_format_; + } + if (cached_has_bits & 0x00000002u) { + _this->_impl_.no_standard_descriptor_accessor_ = from._impl_.no_standard_descriptor_accessor_; + } + if (cached_has_bits & 0x00000004u) { + _this->_impl_.deprecated_ = from._impl_.deprecated_; + } + if (cached_has_bits & 0x00000008u) { + _this->_impl_.map_entry_ = from._impl_.map_entry_; + } + _this->_impl_._has_bits_[0] |= cached_has_bits; + } + _this->_impl_._extensions_.MergeFrom(internal_default_instance(), from._impl_._extensions_); + _this->_internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); +} + +void MessageOptions::CopyFrom(const MessageOptions& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.MessageOptions) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool MessageOptions::IsInitialized() const { + if (!_impl_._extensions_.IsInitialized()) { + return false; + } + + if (!::PROTOBUF_NAMESPACE_ID::internal::AllAreInitialized(_impl_.uninterpreted_option_)) + return false; + return true; +} + +void MessageOptions::InternalSwap(MessageOptions* other) { + using std::swap; + _impl_._extensions_.InternalSwap(&other->_impl_._extensions_); + _internal_metadata_.InternalSwap(&other->_internal_metadata_); + swap(_impl_._has_bits_[0], other->_impl_._has_bits_[0]); + _impl_.uninterpreted_option_.InternalSwap(&other->_impl_.uninterpreted_option_); + ::PROTOBUF_NAMESPACE_ID::internal::memswap< + PROTOBUF_FIELD_OFFSET(MessageOptions, _impl_.map_entry_) + + sizeof(MessageOptions::_impl_.map_entry_) + - PROTOBUF_FIELD_OFFSET(MessageOptions, _impl_.message_set_wire_format_)>( + reinterpret_cast<char*>(&_impl_.message_set_wire_format_), + reinterpret_cast<char*>(&other->_impl_.message_set_wire_format_)); +} + +::PROTOBUF_NAMESPACE_ID::Metadata MessageOptions::GetMetadata() const { + return ::_pbi::AssignDescriptors( + &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_getter, &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_once, + file_level_metadata_google_2fprotobuf_2fdescriptor_2eproto[14]); +} + +// =================================================================== + +class FieldOptions::_Internal { + public: + using HasBits = decltype(std::declval<FieldOptions>()._impl_._has_bits_); + static void set_has_ctype(HasBits* has_bits) { + (*has_bits)[0] |= 1u; + } + static void set_has_packed(HasBits* has_bits) { + (*has_bits)[0] |= 4u; + } + static void set_has_jstype(HasBits* has_bits) { + (*has_bits)[0] |= 2u; + } + static void set_has_lazy(HasBits* has_bits) { + (*has_bits)[0] |= 8u; + } + static void set_has_unverified_lazy(HasBits* has_bits) { + (*has_bits)[0] |= 16u; + } + static void set_has_deprecated(HasBits* has_bits) { + (*has_bits)[0] |= 32u; + } + static void set_has_weak(HasBits* has_bits) { + (*has_bits)[0] |= 64u; + } +}; + +FieldOptions::FieldOptions(::PROTOBUF_NAMESPACE_ID::Arena* arena, + bool is_message_owned) + : ::PROTOBUF_NAMESPACE_ID::Message(arena, is_message_owned) { + SharedCtor(arena, is_message_owned); + // @@protoc_insertion_point(arena_constructor:google.protobuf.FieldOptions) +} +FieldOptions::FieldOptions(const FieldOptions& from) + : ::PROTOBUF_NAMESPACE_ID::Message() { + FieldOptions* const _this = this; (void)_this; + new (&_impl_) Impl_{ + /*decltype(_impl_._extensions_)*/{} + , decltype(_impl_._has_bits_){from._impl_._has_bits_} + , /*decltype(_impl_._cached_size_)*/{} + , decltype(_impl_.uninterpreted_option_){from._impl_.uninterpreted_option_} + , decltype(_impl_.ctype_){} + , decltype(_impl_.jstype_){} + , decltype(_impl_.packed_){} + , decltype(_impl_.lazy_){} + , decltype(_impl_.unverified_lazy_){} + , decltype(_impl_.deprecated_){} + , decltype(_impl_.weak_){}}; + + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); + _impl_._extensions_.MergeFrom(internal_default_instance(), from._impl_._extensions_); + ::memcpy(&_impl_.ctype_, &from._impl_.ctype_, + static_cast<size_t>(reinterpret_cast<char*>(&_impl_.weak_) - + reinterpret_cast<char*>(&_impl_.ctype_)) + sizeof(_impl_.weak_)); + // @@protoc_insertion_point(copy_constructor:google.protobuf.FieldOptions) +} + +inline void FieldOptions::SharedCtor( + ::_pb::Arena* arena, bool is_message_owned) { + (void)arena; + (void)is_message_owned; + new (&_impl_) Impl_{ + /*decltype(_impl_._extensions_)*/{::_pbi::ArenaInitialized(), arena} + , decltype(_impl_._has_bits_){} + , /*decltype(_impl_._cached_size_)*/{} + , decltype(_impl_.uninterpreted_option_){arena} + , decltype(_impl_.ctype_){0} + , decltype(_impl_.jstype_){0} + , decltype(_impl_.packed_){false} + , decltype(_impl_.lazy_){false} + , decltype(_impl_.unverified_lazy_){false} + , decltype(_impl_.deprecated_){false} + , decltype(_impl_.weak_){false} + }; +} + +FieldOptions::~FieldOptions() { + // @@protoc_insertion_point(destructor:google.protobuf.FieldOptions) + if (auto *arena = _internal_metadata_.DeleteReturnArena<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>()) { + (void)arena; + return; + } + SharedDtor(); +} + +inline void FieldOptions::SharedDtor() { + GOOGLE_DCHECK(GetArenaForAllocation() == nullptr); + _impl_._extensions_.~ExtensionSet(); + _impl_.uninterpreted_option_.~RepeatedPtrField(); +} + +void FieldOptions::SetCachedSize(int size) const { + _impl_._cached_size_.Set(size); +} + +void FieldOptions::Clear() { +// @@protoc_insertion_point(message_clear_start:google.protobuf.FieldOptions) + uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + _impl_._extensions_.Clear(); + _impl_.uninterpreted_option_.Clear(); + cached_has_bits = _impl_._has_bits_[0]; + if (cached_has_bits & 0x0000007fu) { + ::memset(&_impl_.ctype_, 0, static_cast<size_t>( + reinterpret_cast<char*>(&_impl_.weak_) - + reinterpret_cast<char*>(&_impl_.ctype_)) + sizeof(_impl_.weak_)); + } + _impl_._has_bits_.Clear(); + _internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); +} + +const char* FieldOptions::_InternalParse(const char* ptr, ::_pbi::ParseContext* ctx) { +#define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure + _Internal::HasBits has_bits{}; + while (!ctx->Done(&ptr)) { + uint32_t tag; + ptr = ::_pbi::ReadTag(ptr, &tag); + switch (tag >> 3) { + // optional .google.protobuf.FieldOptions.CType ctype = 1 [default = STRING]; + case 1: + if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 8)) { + uint64_t val = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr); + CHK_(ptr); + if (PROTOBUF_PREDICT_TRUE(::PROTOBUF_NAMESPACE_ID::FieldOptions_CType_IsValid(val))) { + _internal_set_ctype(static_cast<::PROTOBUF_NAMESPACE_ID::FieldOptions_CType>(val)); + } else { + ::PROTOBUF_NAMESPACE_ID::internal::WriteVarint(1, val, mutable_unknown_fields()); + } + } else + goto handle_unusual; + continue; + // optional bool packed = 2; + case 2: + if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 16)) { + _Internal::set_has_packed(&has_bits); + _impl_.packed_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr); + CHK_(ptr); + } else + goto handle_unusual; + continue; + // optional bool deprecated = 3 [default = false]; + case 3: + if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 24)) { + _Internal::set_has_deprecated(&has_bits); + _impl_.deprecated_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr); + CHK_(ptr); + } else + goto handle_unusual; + continue; + // optional bool lazy = 5 [default = false]; + case 5: + if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 40)) { + _Internal::set_has_lazy(&has_bits); + _impl_.lazy_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr); + CHK_(ptr); + } else + goto handle_unusual; + continue; + // optional .google.protobuf.FieldOptions.JSType jstype = 6 [default = JS_NORMAL]; + case 6: + if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 48)) { + uint64_t val = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr); + CHK_(ptr); + if (PROTOBUF_PREDICT_TRUE(::PROTOBUF_NAMESPACE_ID::FieldOptions_JSType_IsValid(val))) { + _internal_set_jstype(static_cast<::PROTOBUF_NAMESPACE_ID::FieldOptions_JSType>(val)); + } else { + ::PROTOBUF_NAMESPACE_ID::internal::WriteVarint(6, val, mutable_unknown_fields()); + } + } else + goto handle_unusual; + continue; + // optional bool weak = 10 [default = false]; + case 10: + if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 80)) { + _Internal::set_has_weak(&has_bits); + _impl_.weak_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr); + CHK_(ptr); + } else + goto handle_unusual; + continue; + // optional bool unverified_lazy = 15 [default = false]; + case 15: + if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 120)) { + _Internal::set_has_unverified_lazy(&has_bits); + _impl_.unverified_lazy_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr); + CHK_(ptr); + } else + goto handle_unusual; + continue; + // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; + case 999: + if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 58)) { + ptr -= 2; + do { + ptr += 2; + ptr = ctx->ParseMessage(_internal_add_uninterpreted_option(), ptr); + CHK_(ptr); + if (!ctx->DataAvailable(ptr)) break; + } while (::PROTOBUF_NAMESPACE_ID::internal::ExpectTag<7994>(ptr)); + } else + goto handle_unusual; + continue; + default: + goto handle_unusual; + } // switch + handle_unusual: + if ((tag == 0) || ((tag & 7) == 4)) { + CHK_(ptr); + ctx->SetLastTag(tag); + goto message_done; + } + if ((8000u <= tag)) { + ptr = _impl_._extensions_.ParseField(tag, ptr, internal_default_instance(), &_internal_metadata_, ctx); + CHK_(ptr != nullptr); + continue; + } + ptr = UnknownFieldParse( + tag, + _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(), + ptr, ctx); + CHK_(ptr != nullptr); + } // while +message_done: + _impl_._has_bits_.Or(has_bits); + return ptr; +failure: + ptr = nullptr; + goto message_done; +#undef CHK_ +} + +uint8_t* FieldOptions::_InternalSerialize( + uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const { + // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.FieldOptions) + uint32_t cached_has_bits = 0; + (void) cached_has_bits; + + cached_has_bits = _impl_._has_bits_[0]; + // optional .google.protobuf.FieldOptions.CType ctype = 1 [default = STRING]; + if (cached_has_bits & 0x00000001u) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteEnumToArray( + 1, this->_internal_ctype(), target); + } + + // optional bool packed = 2; + if (cached_has_bits & 0x00000004u) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteBoolToArray(2, this->_internal_packed(), target); + } + + // optional bool deprecated = 3 [default = false]; + if (cached_has_bits & 0x00000020u) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteBoolToArray(3, this->_internal_deprecated(), target); + } + + // optional bool lazy = 5 [default = false]; + if (cached_has_bits & 0x00000008u) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteBoolToArray(5, this->_internal_lazy(), target); + } + + // optional .google.protobuf.FieldOptions.JSType jstype = 6 [default = JS_NORMAL]; + if (cached_has_bits & 0x00000002u) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteEnumToArray( + 6, this->_internal_jstype(), target); + } + + // optional bool weak = 10 [default = false]; + if (cached_has_bits & 0x00000040u) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteBoolToArray(10, this->_internal_weak(), target); + } + + // optional bool unverified_lazy = 15 [default = false]; + if (cached_has_bits & 0x00000010u) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteBoolToArray(15, this->_internal_unverified_lazy(), target); + } + + // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; + for (unsigned i = 0, + n = static_cast<unsigned>(this->_internal_uninterpreted_option_size()); i < n; i++) { + const auto& repfield = this->_internal_uninterpreted_option(i); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite:: + InternalWriteMessage(999, repfield, repfield.GetCachedSize(), target, stream); + } + + // Extension range [1000, 536870912) + target = _impl_._extensions_._InternalSerialize( + internal_default_instance(), 1000, 536870912, target, stream); + + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + target = ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( + _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.FieldOptions) + return target; +} + +size_t FieldOptions::ByteSizeLong() const { +// @@protoc_insertion_point(message_byte_size_start:google.protobuf.FieldOptions) + size_t total_size = 0; + + total_size += _impl_._extensions_.ByteSize(); + + uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; + total_size += 2UL * this->_internal_uninterpreted_option_size(); + for (const auto& msg : this->_impl_.uninterpreted_option_) { + total_size += + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::MessageSize(msg); + } + + cached_has_bits = _impl_._has_bits_[0]; + if (cached_has_bits & 0x0000007fu) { + // optional .google.protobuf.FieldOptions.CType ctype = 1 [default = STRING]; + if (cached_has_bits & 0x00000001u) { + total_size += 1 + + ::_pbi::WireFormatLite::EnumSize(this->_internal_ctype()); + } + + // optional .google.protobuf.FieldOptions.JSType jstype = 6 [default = JS_NORMAL]; + if (cached_has_bits & 0x00000002u) { + total_size += 1 + + ::_pbi::WireFormatLite::EnumSize(this->_internal_jstype()); + } + + // optional bool packed = 2; + if (cached_has_bits & 0x00000004u) { + total_size += 1 + 1; + } + + // optional bool lazy = 5 [default = false]; + if (cached_has_bits & 0x00000008u) { + total_size += 1 + 1; + } + + // optional bool unverified_lazy = 15 [default = false]; + if (cached_has_bits & 0x00000010u) { + total_size += 1 + 1; + } + + // optional bool deprecated = 3 [default = false]; + if (cached_has_bits & 0x00000020u) { + total_size += 1 + 1; + } + + // optional bool weak = 10 [default = false]; + if (cached_has_bits & 0x00000040u) { + total_size += 1 + 1; + } + + } + return MaybeComputeUnknownFieldsSize(total_size, &_impl_._cached_size_); +} + +const ::PROTOBUF_NAMESPACE_ID::Message::ClassData FieldOptions::_class_data_ = { + ::PROTOBUF_NAMESPACE_ID::Message::CopyWithSourceCheck, + FieldOptions::MergeImpl +}; +const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*FieldOptions::GetClassData() const { return &_class_data_; } + + +void FieldOptions::MergeImpl(::PROTOBUF_NAMESPACE_ID::Message& to_msg, const ::PROTOBUF_NAMESPACE_ID::Message& from_msg) { + auto* const _this = static_cast<FieldOptions*>(&to_msg); + auto& from = static_cast<const FieldOptions&>(from_msg); + // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.FieldOptions) + GOOGLE_DCHECK_NE(&from, _this); + uint32_t cached_has_bits = 0; + (void) cached_has_bits; + + _this->_impl_.uninterpreted_option_.MergeFrom(from._impl_.uninterpreted_option_); + cached_has_bits = from._impl_._has_bits_[0]; + if (cached_has_bits & 0x0000007fu) { + if (cached_has_bits & 0x00000001u) { + _this->_impl_.ctype_ = from._impl_.ctype_; + } + if (cached_has_bits & 0x00000002u) { + _this->_impl_.jstype_ = from._impl_.jstype_; + } + if (cached_has_bits & 0x00000004u) { + _this->_impl_.packed_ = from._impl_.packed_; + } + if (cached_has_bits & 0x00000008u) { + _this->_impl_.lazy_ = from._impl_.lazy_; + } + if (cached_has_bits & 0x00000010u) { + _this->_impl_.unverified_lazy_ = from._impl_.unverified_lazy_; + } + if (cached_has_bits & 0x00000020u) { + _this->_impl_.deprecated_ = from._impl_.deprecated_; + } + if (cached_has_bits & 0x00000040u) { + _this->_impl_.weak_ = from._impl_.weak_; + } + _this->_impl_._has_bits_[0] |= cached_has_bits; + } + _this->_impl_._extensions_.MergeFrom(internal_default_instance(), from._impl_._extensions_); + _this->_internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); +} + +void FieldOptions::CopyFrom(const FieldOptions& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.FieldOptions) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool FieldOptions::IsInitialized() const { + if (!_impl_._extensions_.IsInitialized()) { + return false; + } + + if (!::PROTOBUF_NAMESPACE_ID::internal::AllAreInitialized(_impl_.uninterpreted_option_)) + return false; + return true; +} + +void FieldOptions::InternalSwap(FieldOptions* other) { + using std::swap; + _impl_._extensions_.InternalSwap(&other->_impl_._extensions_); + _internal_metadata_.InternalSwap(&other->_internal_metadata_); + swap(_impl_._has_bits_[0], other->_impl_._has_bits_[0]); + _impl_.uninterpreted_option_.InternalSwap(&other->_impl_.uninterpreted_option_); + ::PROTOBUF_NAMESPACE_ID::internal::memswap< + PROTOBUF_FIELD_OFFSET(FieldOptions, _impl_.weak_) + + sizeof(FieldOptions::_impl_.weak_) + - PROTOBUF_FIELD_OFFSET(FieldOptions, _impl_.ctype_)>( + reinterpret_cast<char*>(&_impl_.ctype_), + reinterpret_cast<char*>(&other->_impl_.ctype_)); +} + +::PROTOBUF_NAMESPACE_ID::Metadata FieldOptions::GetMetadata() const { + return ::_pbi::AssignDescriptors( + &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_getter, &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_once, + file_level_metadata_google_2fprotobuf_2fdescriptor_2eproto[15]); +} + +// =================================================================== + +class OneofOptions::_Internal { + public: +}; + +OneofOptions::OneofOptions(::PROTOBUF_NAMESPACE_ID::Arena* arena, + bool is_message_owned) + : ::PROTOBUF_NAMESPACE_ID::Message(arena, is_message_owned) { + SharedCtor(arena, is_message_owned); + // @@protoc_insertion_point(arena_constructor:google.protobuf.OneofOptions) +} +OneofOptions::OneofOptions(const OneofOptions& from) + : ::PROTOBUF_NAMESPACE_ID::Message() { + OneofOptions* const _this = this; (void)_this; + new (&_impl_) Impl_{ + /*decltype(_impl_._extensions_)*/{} + , decltype(_impl_.uninterpreted_option_){from._impl_.uninterpreted_option_} + , /*decltype(_impl_._cached_size_)*/{}}; + + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); + _impl_._extensions_.MergeFrom(internal_default_instance(), from._impl_._extensions_); + // @@protoc_insertion_point(copy_constructor:google.protobuf.OneofOptions) +} + +inline void OneofOptions::SharedCtor( + ::_pb::Arena* arena, bool is_message_owned) { + (void)arena; + (void)is_message_owned; + new (&_impl_) Impl_{ + /*decltype(_impl_._extensions_)*/{::_pbi::ArenaInitialized(), arena} + , decltype(_impl_.uninterpreted_option_){arena} + , /*decltype(_impl_._cached_size_)*/{} + }; +} + +OneofOptions::~OneofOptions() { + // @@protoc_insertion_point(destructor:google.protobuf.OneofOptions) + if (auto *arena = _internal_metadata_.DeleteReturnArena<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>()) { + (void)arena; + return; + } + SharedDtor(); +} + +inline void OneofOptions::SharedDtor() { + GOOGLE_DCHECK(GetArenaForAllocation() == nullptr); + _impl_._extensions_.~ExtensionSet(); + _impl_.uninterpreted_option_.~RepeatedPtrField(); +} + +void OneofOptions::SetCachedSize(int size) const { + _impl_._cached_size_.Set(size); +} + +void OneofOptions::Clear() { +// @@protoc_insertion_point(message_clear_start:google.protobuf.OneofOptions) + uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + _impl_._extensions_.Clear(); + _impl_.uninterpreted_option_.Clear(); + _internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); +} + +const char* OneofOptions::_InternalParse(const char* ptr, ::_pbi::ParseContext* ctx) { +#define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure + while (!ctx->Done(&ptr)) { + uint32_t tag; + ptr = ::_pbi::ReadTag(ptr, &tag); + switch (tag >> 3) { + // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; + case 999: + if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 58)) { + ptr -= 2; + do { + ptr += 2; + ptr = ctx->ParseMessage(_internal_add_uninterpreted_option(), ptr); + CHK_(ptr); + if (!ctx->DataAvailable(ptr)) break; + } while (::PROTOBUF_NAMESPACE_ID::internal::ExpectTag<7994>(ptr)); + } else + goto handle_unusual; + continue; + default: + goto handle_unusual; + } // switch + handle_unusual: + if ((tag == 0) || ((tag & 7) == 4)) { + CHK_(ptr); + ctx->SetLastTag(tag); + goto message_done; + } + if ((8000u <= tag)) { + ptr = _impl_._extensions_.ParseField(tag, ptr, internal_default_instance(), &_internal_metadata_, ctx); + CHK_(ptr != nullptr); + continue; + } + ptr = UnknownFieldParse( + tag, + _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(), + ptr, ctx); + CHK_(ptr != nullptr); + } // while +message_done: + return ptr; +failure: + ptr = nullptr; + goto message_done; +#undef CHK_ +} + +uint8_t* OneofOptions::_InternalSerialize( + uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const { + // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.OneofOptions) + uint32_t cached_has_bits = 0; + (void) cached_has_bits; + + // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; + for (unsigned i = 0, + n = static_cast<unsigned>(this->_internal_uninterpreted_option_size()); i < n; i++) { + const auto& repfield = this->_internal_uninterpreted_option(i); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite:: + InternalWriteMessage(999, repfield, repfield.GetCachedSize(), target, stream); + } + + // Extension range [1000, 536870912) + target = _impl_._extensions_._InternalSerialize( + internal_default_instance(), 1000, 536870912, target, stream); + + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + target = ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( + _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.OneofOptions) + return target; +} + +size_t OneofOptions::ByteSizeLong() const { +// @@protoc_insertion_point(message_byte_size_start:google.protobuf.OneofOptions) + size_t total_size = 0; + + total_size += _impl_._extensions_.ByteSize(); + + uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; + total_size += 2UL * this->_internal_uninterpreted_option_size(); + for (const auto& msg : this->_impl_.uninterpreted_option_) { + total_size += + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::MessageSize(msg); + } + + return MaybeComputeUnknownFieldsSize(total_size, &_impl_._cached_size_); +} + +const ::PROTOBUF_NAMESPACE_ID::Message::ClassData OneofOptions::_class_data_ = { + ::PROTOBUF_NAMESPACE_ID::Message::CopyWithSourceCheck, + OneofOptions::MergeImpl +}; +const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*OneofOptions::GetClassData() const { return &_class_data_; } + + +void OneofOptions::MergeImpl(::PROTOBUF_NAMESPACE_ID::Message& to_msg, const ::PROTOBUF_NAMESPACE_ID::Message& from_msg) { + auto* const _this = static_cast<OneofOptions*>(&to_msg); + auto& from = static_cast<const OneofOptions&>(from_msg); + // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.OneofOptions) + GOOGLE_DCHECK_NE(&from, _this); + uint32_t cached_has_bits = 0; + (void) cached_has_bits; + + _this->_impl_.uninterpreted_option_.MergeFrom(from._impl_.uninterpreted_option_); + _this->_impl_._extensions_.MergeFrom(internal_default_instance(), from._impl_._extensions_); + _this->_internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); +} + +void OneofOptions::CopyFrom(const OneofOptions& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.OneofOptions) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool OneofOptions::IsInitialized() const { + if (!_impl_._extensions_.IsInitialized()) { + return false; + } + + if (!::PROTOBUF_NAMESPACE_ID::internal::AllAreInitialized(_impl_.uninterpreted_option_)) + return false; + return true; +} + +void OneofOptions::InternalSwap(OneofOptions* other) { + using std::swap; + _impl_._extensions_.InternalSwap(&other->_impl_._extensions_); + _internal_metadata_.InternalSwap(&other->_internal_metadata_); + _impl_.uninterpreted_option_.InternalSwap(&other->_impl_.uninterpreted_option_); +} + +::PROTOBUF_NAMESPACE_ID::Metadata OneofOptions::GetMetadata() const { + return ::_pbi::AssignDescriptors( + &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_getter, &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_once, + file_level_metadata_google_2fprotobuf_2fdescriptor_2eproto[16]); +} + +// =================================================================== + +class EnumOptions::_Internal { + public: + using HasBits = decltype(std::declval<EnumOptions>()._impl_._has_bits_); + static void set_has_allow_alias(HasBits* has_bits) { + (*has_bits)[0] |= 1u; + } + static void set_has_deprecated(HasBits* has_bits) { + (*has_bits)[0] |= 2u; + } +}; + +EnumOptions::EnumOptions(::PROTOBUF_NAMESPACE_ID::Arena* arena, + bool is_message_owned) + : ::PROTOBUF_NAMESPACE_ID::Message(arena, is_message_owned) { + SharedCtor(arena, is_message_owned); + // @@protoc_insertion_point(arena_constructor:google.protobuf.EnumOptions) +} +EnumOptions::EnumOptions(const EnumOptions& from) + : ::PROTOBUF_NAMESPACE_ID::Message() { + EnumOptions* const _this = this; (void)_this; + new (&_impl_) Impl_{ + /*decltype(_impl_._extensions_)*/{} + , decltype(_impl_._has_bits_){from._impl_._has_bits_} + , /*decltype(_impl_._cached_size_)*/{} + , decltype(_impl_.uninterpreted_option_){from._impl_.uninterpreted_option_} + , decltype(_impl_.allow_alias_){} + , decltype(_impl_.deprecated_){}}; + + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); + _impl_._extensions_.MergeFrom(internal_default_instance(), from._impl_._extensions_); + ::memcpy(&_impl_.allow_alias_, &from._impl_.allow_alias_, + static_cast<size_t>(reinterpret_cast<char*>(&_impl_.deprecated_) - + reinterpret_cast<char*>(&_impl_.allow_alias_)) + sizeof(_impl_.deprecated_)); + // @@protoc_insertion_point(copy_constructor:google.protobuf.EnumOptions) +} + +inline void EnumOptions::SharedCtor( + ::_pb::Arena* arena, bool is_message_owned) { + (void)arena; + (void)is_message_owned; + new (&_impl_) Impl_{ + /*decltype(_impl_._extensions_)*/{::_pbi::ArenaInitialized(), arena} + , decltype(_impl_._has_bits_){} + , /*decltype(_impl_._cached_size_)*/{} + , decltype(_impl_.uninterpreted_option_){arena} + , decltype(_impl_.allow_alias_){false} + , decltype(_impl_.deprecated_){false} + }; +} + +EnumOptions::~EnumOptions() { + // @@protoc_insertion_point(destructor:google.protobuf.EnumOptions) + if (auto *arena = _internal_metadata_.DeleteReturnArena<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>()) { + (void)arena; + return; + } + SharedDtor(); +} + +inline void EnumOptions::SharedDtor() { + GOOGLE_DCHECK(GetArenaForAllocation() == nullptr); + _impl_._extensions_.~ExtensionSet(); + _impl_.uninterpreted_option_.~RepeatedPtrField(); +} + +void EnumOptions::SetCachedSize(int size) const { + _impl_._cached_size_.Set(size); +} + +void EnumOptions::Clear() { +// @@protoc_insertion_point(message_clear_start:google.protobuf.EnumOptions) + uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + _impl_._extensions_.Clear(); + _impl_.uninterpreted_option_.Clear(); + ::memset(&_impl_.allow_alias_, 0, static_cast<size_t>( + reinterpret_cast<char*>(&_impl_.deprecated_) - + reinterpret_cast<char*>(&_impl_.allow_alias_)) + sizeof(_impl_.deprecated_)); + _impl_._has_bits_.Clear(); + _internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); +} + +const char* EnumOptions::_InternalParse(const char* ptr, ::_pbi::ParseContext* ctx) { +#define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure + _Internal::HasBits has_bits{}; + while (!ctx->Done(&ptr)) { + uint32_t tag; + ptr = ::_pbi::ReadTag(ptr, &tag); + switch (tag >> 3) { + // optional bool allow_alias = 2; + case 2: + if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 16)) { + _Internal::set_has_allow_alias(&has_bits); + _impl_.allow_alias_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr); + CHK_(ptr); + } else + goto handle_unusual; + continue; + // optional bool deprecated = 3 [default = false]; + case 3: + if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 24)) { + _Internal::set_has_deprecated(&has_bits); + _impl_.deprecated_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr); + CHK_(ptr); + } else + goto handle_unusual; + continue; + // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; + case 999: + if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 58)) { + ptr -= 2; + do { + ptr += 2; + ptr = ctx->ParseMessage(_internal_add_uninterpreted_option(), ptr); + CHK_(ptr); + if (!ctx->DataAvailable(ptr)) break; + } while (::PROTOBUF_NAMESPACE_ID::internal::ExpectTag<7994>(ptr)); + } else + goto handle_unusual; + continue; + default: + goto handle_unusual; + } // switch + handle_unusual: + if ((tag == 0) || ((tag & 7) == 4)) { + CHK_(ptr); + ctx->SetLastTag(tag); + goto message_done; + } + if ((8000u <= tag)) { + ptr = _impl_._extensions_.ParseField(tag, ptr, internal_default_instance(), &_internal_metadata_, ctx); + CHK_(ptr != nullptr); + continue; + } + ptr = UnknownFieldParse( + tag, + _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(), + ptr, ctx); + CHK_(ptr != nullptr); + } // while +message_done: + _impl_._has_bits_.Or(has_bits); + return ptr; +failure: + ptr = nullptr; + goto message_done; +#undef CHK_ +} + +uint8_t* EnumOptions::_InternalSerialize( + uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const { + // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.EnumOptions) + uint32_t cached_has_bits = 0; + (void) cached_has_bits; + + cached_has_bits = _impl_._has_bits_[0]; + // optional bool allow_alias = 2; + if (cached_has_bits & 0x00000001u) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteBoolToArray(2, this->_internal_allow_alias(), target); + } + + // optional bool deprecated = 3 [default = false]; + if (cached_has_bits & 0x00000002u) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteBoolToArray(3, this->_internal_deprecated(), target); + } + + // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; + for (unsigned i = 0, + n = static_cast<unsigned>(this->_internal_uninterpreted_option_size()); i < n; i++) { + const auto& repfield = this->_internal_uninterpreted_option(i); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite:: + InternalWriteMessage(999, repfield, repfield.GetCachedSize(), target, stream); + } + + // Extension range [1000, 536870912) + target = _impl_._extensions_._InternalSerialize( + internal_default_instance(), 1000, 536870912, target, stream); + + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + target = ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( + _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.EnumOptions) + return target; +} + +size_t EnumOptions::ByteSizeLong() const { +// @@protoc_insertion_point(message_byte_size_start:google.protobuf.EnumOptions) + size_t total_size = 0; + + total_size += _impl_._extensions_.ByteSize(); + + uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; + total_size += 2UL * this->_internal_uninterpreted_option_size(); + for (const auto& msg : this->_impl_.uninterpreted_option_) { + total_size += + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::MessageSize(msg); + } + + cached_has_bits = _impl_._has_bits_[0]; + if (cached_has_bits & 0x00000003u) { + // optional bool allow_alias = 2; + if (cached_has_bits & 0x00000001u) { + total_size += 1 + 1; + } + + // optional bool deprecated = 3 [default = false]; + if (cached_has_bits & 0x00000002u) { + total_size += 1 + 1; + } + + } + return MaybeComputeUnknownFieldsSize(total_size, &_impl_._cached_size_); +} + +const ::PROTOBUF_NAMESPACE_ID::Message::ClassData EnumOptions::_class_data_ = { + ::PROTOBUF_NAMESPACE_ID::Message::CopyWithSourceCheck, + EnumOptions::MergeImpl +}; +const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*EnumOptions::GetClassData() const { return &_class_data_; } + + +void EnumOptions::MergeImpl(::PROTOBUF_NAMESPACE_ID::Message& to_msg, const ::PROTOBUF_NAMESPACE_ID::Message& from_msg) { + auto* const _this = static_cast<EnumOptions*>(&to_msg); + auto& from = static_cast<const EnumOptions&>(from_msg); + // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.EnumOptions) + GOOGLE_DCHECK_NE(&from, _this); + uint32_t cached_has_bits = 0; + (void) cached_has_bits; + + _this->_impl_.uninterpreted_option_.MergeFrom(from._impl_.uninterpreted_option_); + cached_has_bits = from._impl_._has_bits_[0]; + if (cached_has_bits & 0x00000003u) { + if (cached_has_bits & 0x00000001u) { + _this->_impl_.allow_alias_ = from._impl_.allow_alias_; + } + if (cached_has_bits & 0x00000002u) { + _this->_impl_.deprecated_ = from._impl_.deprecated_; + } + _this->_impl_._has_bits_[0] |= cached_has_bits; + } + _this->_impl_._extensions_.MergeFrom(internal_default_instance(), from._impl_._extensions_); + _this->_internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); +} + +void EnumOptions::CopyFrom(const EnumOptions& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.EnumOptions) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool EnumOptions::IsInitialized() const { + if (!_impl_._extensions_.IsInitialized()) { + return false; + } + + if (!::PROTOBUF_NAMESPACE_ID::internal::AllAreInitialized(_impl_.uninterpreted_option_)) + return false; + return true; +} + +void EnumOptions::InternalSwap(EnumOptions* other) { + using std::swap; + _impl_._extensions_.InternalSwap(&other->_impl_._extensions_); + _internal_metadata_.InternalSwap(&other->_internal_metadata_); + swap(_impl_._has_bits_[0], other->_impl_._has_bits_[0]); + _impl_.uninterpreted_option_.InternalSwap(&other->_impl_.uninterpreted_option_); + ::PROTOBUF_NAMESPACE_ID::internal::memswap< + PROTOBUF_FIELD_OFFSET(EnumOptions, _impl_.deprecated_) + + sizeof(EnumOptions::_impl_.deprecated_) + - PROTOBUF_FIELD_OFFSET(EnumOptions, _impl_.allow_alias_)>( + reinterpret_cast<char*>(&_impl_.allow_alias_), + reinterpret_cast<char*>(&other->_impl_.allow_alias_)); +} + +::PROTOBUF_NAMESPACE_ID::Metadata EnumOptions::GetMetadata() const { + return ::_pbi::AssignDescriptors( + &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_getter, &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_once, + file_level_metadata_google_2fprotobuf_2fdescriptor_2eproto[17]); +} + +// =================================================================== + +class EnumValueOptions::_Internal { + public: + using HasBits = decltype(std::declval<EnumValueOptions>()._impl_._has_bits_); + static void set_has_deprecated(HasBits* has_bits) { + (*has_bits)[0] |= 1u; + } +}; + +EnumValueOptions::EnumValueOptions(::PROTOBUF_NAMESPACE_ID::Arena* arena, + bool is_message_owned) + : ::PROTOBUF_NAMESPACE_ID::Message(arena, is_message_owned) { + SharedCtor(arena, is_message_owned); + // @@protoc_insertion_point(arena_constructor:google.protobuf.EnumValueOptions) +} +EnumValueOptions::EnumValueOptions(const EnumValueOptions& from) + : ::PROTOBUF_NAMESPACE_ID::Message() { + EnumValueOptions* const _this = this; (void)_this; + new (&_impl_) Impl_{ + /*decltype(_impl_._extensions_)*/{} + , decltype(_impl_._has_bits_){from._impl_._has_bits_} + , /*decltype(_impl_._cached_size_)*/{} + , decltype(_impl_.uninterpreted_option_){from._impl_.uninterpreted_option_} + , decltype(_impl_.deprecated_){}}; + + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); + _impl_._extensions_.MergeFrom(internal_default_instance(), from._impl_._extensions_); + _this->_impl_.deprecated_ = from._impl_.deprecated_; + // @@protoc_insertion_point(copy_constructor:google.protobuf.EnumValueOptions) +} + +inline void EnumValueOptions::SharedCtor( + ::_pb::Arena* arena, bool is_message_owned) { + (void)arena; + (void)is_message_owned; + new (&_impl_) Impl_{ + /*decltype(_impl_._extensions_)*/{::_pbi::ArenaInitialized(), arena} + , decltype(_impl_._has_bits_){} + , /*decltype(_impl_._cached_size_)*/{} + , decltype(_impl_.uninterpreted_option_){arena} + , decltype(_impl_.deprecated_){false} + }; +} + +EnumValueOptions::~EnumValueOptions() { + // @@protoc_insertion_point(destructor:google.protobuf.EnumValueOptions) + if (auto *arena = _internal_metadata_.DeleteReturnArena<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>()) { + (void)arena; + return; + } + SharedDtor(); +} + +inline void EnumValueOptions::SharedDtor() { + GOOGLE_DCHECK(GetArenaForAllocation() == nullptr); + _impl_._extensions_.~ExtensionSet(); + _impl_.uninterpreted_option_.~RepeatedPtrField(); +} + +void EnumValueOptions::SetCachedSize(int size) const { + _impl_._cached_size_.Set(size); +} + +void EnumValueOptions::Clear() { +// @@protoc_insertion_point(message_clear_start:google.protobuf.EnumValueOptions) + uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + _impl_._extensions_.Clear(); + _impl_.uninterpreted_option_.Clear(); + _impl_.deprecated_ = false; + _impl_._has_bits_.Clear(); + _internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); +} + +const char* EnumValueOptions::_InternalParse(const char* ptr, ::_pbi::ParseContext* ctx) { +#define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure + _Internal::HasBits has_bits{}; + while (!ctx->Done(&ptr)) { + uint32_t tag; + ptr = ::_pbi::ReadTag(ptr, &tag); + switch (tag >> 3) { + // optional bool deprecated = 1 [default = false]; + case 1: + if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 8)) { + _Internal::set_has_deprecated(&has_bits); + _impl_.deprecated_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr); + CHK_(ptr); + } else + goto handle_unusual; + continue; + // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; + case 999: + if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 58)) { + ptr -= 2; + do { + ptr += 2; + ptr = ctx->ParseMessage(_internal_add_uninterpreted_option(), ptr); + CHK_(ptr); + if (!ctx->DataAvailable(ptr)) break; + } while (::PROTOBUF_NAMESPACE_ID::internal::ExpectTag<7994>(ptr)); + } else + goto handle_unusual; + continue; + default: + goto handle_unusual; + } // switch + handle_unusual: + if ((tag == 0) || ((tag & 7) == 4)) { + CHK_(ptr); + ctx->SetLastTag(tag); + goto message_done; + } + if ((8000u <= tag)) { + ptr = _impl_._extensions_.ParseField(tag, ptr, internal_default_instance(), &_internal_metadata_, ctx); + CHK_(ptr != nullptr); + continue; + } + ptr = UnknownFieldParse( + tag, + _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(), + ptr, ctx); + CHK_(ptr != nullptr); + } // while +message_done: + _impl_._has_bits_.Or(has_bits); + return ptr; +failure: + ptr = nullptr; + goto message_done; +#undef CHK_ +} + +uint8_t* EnumValueOptions::_InternalSerialize( + uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const { + // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.EnumValueOptions) + uint32_t cached_has_bits = 0; + (void) cached_has_bits; + + cached_has_bits = _impl_._has_bits_[0]; + // optional bool deprecated = 1 [default = false]; + if (cached_has_bits & 0x00000001u) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteBoolToArray(1, this->_internal_deprecated(), target); + } + + // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; + for (unsigned i = 0, + n = static_cast<unsigned>(this->_internal_uninterpreted_option_size()); i < n; i++) { + const auto& repfield = this->_internal_uninterpreted_option(i); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite:: + InternalWriteMessage(999, repfield, repfield.GetCachedSize(), target, stream); + } + + // Extension range [1000, 536870912) + target = _impl_._extensions_._InternalSerialize( + internal_default_instance(), 1000, 536870912, target, stream); + + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + target = ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( + _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.EnumValueOptions) + return target; +} + +size_t EnumValueOptions::ByteSizeLong() const { +// @@protoc_insertion_point(message_byte_size_start:google.protobuf.EnumValueOptions) + size_t total_size = 0; + + total_size += _impl_._extensions_.ByteSize(); + + uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; + total_size += 2UL * this->_internal_uninterpreted_option_size(); + for (const auto& msg : this->_impl_.uninterpreted_option_) { + total_size += + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::MessageSize(msg); + } + + // optional bool deprecated = 1 [default = false]; + cached_has_bits = _impl_._has_bits_[0]; + if (cached_has_bits & 0x00000001u) { + total_size += 1 + 1; + } + + return MaybeComputeUnknownFieldsSize(total_size, &_impl_._cached_size_); +} + +const ::PROTOBUF_NAMESPACE_ID::Message::ClassData EnumValueOptions::_class_data_ = { + ::PROTOBUF_NAMESPACE_ID::Message::CopyWithSourceCheck, + EnumValueOptions::MergeImpl +}; +const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*EnumValueOptions::GetClassData() const { return &_class_data_; } + + +void EnumValueOptions::MergeImpl(::PROTOBUF_NAMESPACE_ID::Message& to_msg, const ::PROTOBUF_NAMESPACE_ID::Message& from_msg) { + auto* const _this = static_cast<EnumValueOptions*>(&to_msg); + auto& from = static_cast<const EnumValueOptions&>(from_msg); + // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.EnumValueOptions) + GOOGLE_DCHECK_NE(&from, _this); + uint32_t cached_has_bits = 0; + (void) cached_has_bits; + + _this->_impl_.uninterpreted_option_.MergeFrom(from._impl_.uninterpreted_option_); + if (from._internal_has_deprecated()) { + _this->_internal_set_deprecated(from._internal_deprecated()); + } + _this->_impl_._extensions_.MergeFrom(internal_default_instance(), from._impl_._extensions_); + _this->_internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); +} + +void EnumValueOptions::CopyFrom(const EnumValueOptions& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.EnumValueOptions) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool EnumValueOptions::IsInitialized() const { + if (!_impl_._extensions_.IsInitialized()) { + return false; + } + + if (!::PROTOBUF_NAMESPACE_ID::internal::AllAreInitialized(_impl_.uninterpreted_option_)) + return false; + return true; +} + +void EnumValueOptions::InternalSwap(EnumValueOptions* other) { + using std::swap; + _impl_._extensions_.InternalSwap(&other->_impl_._extensions_); + _internal_metadata_.InternalSwap(&other->_internal_metadata_); + swap(_impl_._has_bits_[0], other->_impl_._has_bits_[0]); + _impl_.uninterpreted_option_.InternalSwap(&other->_impl_.uninterpreted_option_); + swap(_impl_.deprecated_, other->_impl_.deprecated_); +} + +::PROTOBUF_NAMESPACE_ID::Metadata EnumValueOptions::GetMetadata() const { + return ::_pbi::AssignDescriptors( + &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_getter, &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_once, + file_level_metadata_google_2fprotobuf_2fdescriptor_2eproto[18]); +} + +// =================================================================== + +class ServiceOptions::_Internal { + public: + using HasBits = decltype(std::declval<ServiceOptions>()._impl_._has_bits_); + static void set_has_deprecated(HasBits* has_bits) { + (*has_bits)[0] |= 1u; + } +}; + +ServiceOptions::ServiceOptions(::PROTOBUF_NAMESPACE_ID::Arena* arena, + bool is_message_owned) + : ::PROTOBUF_NAMESPACE_ID::Message(arena, is_message_owned) { + SharedCtor(arena, is_message_owned); + // @@protoc_insertion_point(arena_constructor:google.protobuf.ServiceOptions) +} +ServiceOptions::ServiceOptions(const ServiceOptions& from) + : ::PROTOBUF_NAMESPACE_ID::Message() { + ServiceOptions* const _this = this; (void)_this; + new (&_impl_) Impl_{ + /*decltype(_impl_._extensions_)*/{} + , decltype(_impl_._has_bits_){from._impl_._has_bits_} + , /*decltype(_impl_._cached_size_)*/{} + , decltype(_impl_.uninterpreted_option_){from._impl_.uninterpreted_option_} + , decltype(_impl_.deprecated_){}}; + + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); + _impl_._extensions_.MergeFrom(internal_default_instance(), from._impl_._extensions_); + _this->_impl_.deprecated_ = from._impl_.deprecated_; + // @@protoc_insertion_point(copy_constructor:google.protobuf.ServiceOptions) +} + +inline void ServiceOptions::SharedCtor( + ::_pb::Arena* arena, bool is_message_owned) { + (void)arena; + (void)is_message_owned; + new (&_impl_) Impl_{ + /*decltype(_impl_._extensions_)*/{::_pbi::ArenaInitialized(), arena} + , decltype(_impl_._has_bits_){} + , /*decltype(_impl_._cached_size_)*/{} + , decltype(_impl_.uninterpreted_option_){arena} + , decltype(_impl_.deprecated_){false} + }; +} + +ServiceOptions::~ServiceOptions() { + // @@protoc_insertion_point(destructor:google.protobuf.ServiceOptions) + if (auto *arena = _internal_metadata_.DeleteReturnArena<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>()) { + (void)arena; + return; + } + SharedDtor(); +} + +inline void ServiceOptions::SharedDtor() { + GOOGLE_DCHECK(GetArenaForAllocation() == nullptr); + _impl_._extensions_.~ExtensionSet(); + _impl_.uninterpreted_option_.~RepeatedPtrField(); +} + +void ServiceOptions::SetCachedSize(int size) const { + _impl_._cached_size_.Set(size); +} + +void ServiceOptions::Clear() { +// @@protoc_insertion_point(message_clear_start:google.protobuf.ServiceOptions) + uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + _impl_._extensions_.Clear(); + _impl_.uninterpreted_option_.Clear(); + _impl_.deprecated_ = false; + _impl_._has_bits_.Clear(); + _internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); +} + +const char* ServiceOptions::_InternalParse(const char* ptr, ::_pbi::ParseContext* ctx) { +#define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure + _Internal::HasBits has_bits{}; + while (!ctx->Done(&ptr)) { + uint32_t tag; + ptr = ::_pbi::ReadTag(ptr, &tag); + switch (tag >> 3) { + // optional bool deprecated = 33 [default = false]; + case 33: + if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 8)) { + _Internal::set_has_deprecated(&has_bits); + _impl_.deprecated_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr); + CHK_(ptr); + } else + goto handle_unusual; + continue; + // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; + case 999: + if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 58)) { + ptr -= 2; + do { + ptr += 2; + ptr = ctx->ParseMessage(_internal_add_uninterpreted_option(), ptr); + CHK_(ptr); + if (!ctx->DataAvailable(ptr)) break; + } while (::PROTOBUF_NAMESPACE_ID::internal::ExpectTag<7994>(ptr)); + } else + goto handle_unusual; + continue; + default: + goto handle_unusual; + } // switch + handle_unusual: + if ((tag == 0) || ((tag & 7) == 4)) { + CHK_(ptr); + ctx->SetLastTag(tag); + goto message_done; + } + if ((8000u <= tag)) { + ptr = _impl_._extensions_.ParseField(tag, ptr, internal_default_instance(), &_internal_metadata_, ctx); + CHK_(ptr != nullptr); + continue; + } + ptr = UnknownFieldParse( + tag, + _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(), + ptr, ctx); + CHK_(ptr != nullptr); + } // while +message_done: + _impl_._has_bits_.Or(has_bits); + return ptr; +failure: + ptr = nullptr; + goto message_done; +#undef CHK_ +} + +uint8_t* ServiceOptions::_InternalSerialize( + uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const { + // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.ServiceOptions) + uint32_t cached_has_bits = 0; + (void) cached_has_bits; + + cached_has_bits = _impl_._has_bits_[0]; + // optional bool deprecated = 33 [default = false]; + if (cached_has_bits & 0x00000001u) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteBoolToArray(33, this->_internal_deprecated(), target); + } + + // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; + for (unsigned i = 0, + n = static_cast<unsigned>(this->_internal_uninterpreted_option_size()); i < n; i++) { + const auto& repfield = this->_internal_uninterpreted_option(i); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite:: + InternalWriteMessage(999, repfield, repfield.GetCachedSize(), target, stream); + } + + // Extension range [1000, 536870912) + target = _impl_._extensions_._InternalSerialize( + internal_default_instance(), 1000, 536870912, target, stream); + + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + target = ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( + _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.ServiceOptions) + return target; +} + +size_t ServiceOptions::ByteSizeLong() const { +// @@protoc_insertion_point(message_byte_size_start:google.protobuf.ServiceOptions) + size_t total_size = 0; + + total_size += _impl_._extensions_.ByteSize(); + + uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; + total_size += 2UL * this->_internal_uninterpreted_option_size(); + for (const auto& msg : this->_impl_.uninterpreted_option_) { + total_size += + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::MessageSize(msg); + } + + // optional bool deprecated = 33 [default = false]; + cached_has_bits = _impl_._has_bits_[0]; + if (cached_has_bits & 0x00000001u) { + total_size += 2 + 1; + } + + return MaybeComputeUnknownFieldsSize(total_size, &_impl_._cached_size_); +} + +const ::PROTOBUF_NAMESPACE_ID::Message::ClassData ServiceOptions::_class_data_ = { + ::PROTOBUF_NAMESPACE_ID::Message::CopyWithSourceCheck, + ServiceOptions::MergeImpl +}; +const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*ServiceOptions::GetClassData() const { return &_class_data_; } + + +void ServiceOptions::MergeImpl(::PROTOBUF_NAMESPACE_ID::Message& to_msg, const ::PROTOBUF_NAMESPACE_ID::Message& from_msg) { + auto* const _this = static_cast<ServiceOptions*>(&to_msg); + auto& from = static_cast<const ServiceOptions&>(from_msg); + // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.ServiceOptions) + GOOGLE_DCHECK_NE(&from, _this); + uint32_t cached_has_bits = 0; + (void) cached_has_bits; + + _this->_impl_.uninterpreted_option_.MergeFrom(from._impl_.uninterpreted_option_); + if (from._internal_has_deprecated()) { + _this->_internal_set_deprecated(from._internal_deprecated()); + } + _this->_impl_._extensions_.MergeFrom(internal_default_instance(), from._impl_._extensions_); + _this->_internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); +} + +void ServiceOptions::CopyFrom(const ServiceOptions& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.ServiceOptions) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool ServiceOptions::IsInitialized() const { + if (!_impl_._extensions_.IsInitialized()) { + return false; + } + + if (!::PROTOBUF_NAMESPACE_ID::internal::AllAreInitialized(_impl_.uninterpreted_option_)) + return false; + return true; +} + +void ServiceOptions::InternalSwap(ServiceOptions* other) { + using std::swap; + _impl_._extensions_.InternalSwap(&other->_impl_._extensions_); + _internal_metadata_.InternalSwap(&other->_internal_metadata_); + swap(_impl_._has_bits_[0], other->_impl_._has_bits_[0]); + _impl_.uninterpreted_option_.InternalSwap(&other->_impl_.uninterpreted_option_); + swap(_impl_.deprecated_, other->_impl_.deprecated_); +} + +::PROTOBUF_NAMESPACE_ID::Metadata ServiceOptions::GetMetadata() const { + return ::_pbi::AssignDescriptors( + &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_getter, &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_once, + file_level_metadata_google_2fprotobuf_2fdescriptor_2eproto[19]); +} + +// =================================================================== + +class MethodOptions::_Internal { + public: + using HasBits = decltype(std::declval<MethodOptions>()._impl_._has_bits_); + static void set_has_deprecated(HasBits* has_bits) { + (*has_bits)[0] |= 1u; + } + static void set_has_idempotency_level(HasBits* has_bits) { + (*has_bits)[0] |= 2u; + } +}; + +MethodOptions::MethodOptions(::PROTOBUF_NAMESPACE_ID::Arena* arena, + bool is_message_owned) + : ::PROTOBUF_NAMESPACE_ID::Message(arena, is_message_owned) { + SharedCtor(arena, is_message_owned); + // @@protoc_insertion_point(arena_constructor:google.protobuf.MethodOptions) +} +MethodOptions::MethodOptions(const MethodOptions& from) + : ::PROTOBUF_NAMESPACE_ID::Message() { + MethodOptions* const _this = this; (void)_this; + new (&_impl_) Impl_{ + /*decltype(_impl_._extensions_)*/{} + , decltype(_impl_._has_bits_){from._impl_._has_bits_} + , /*decltype(_impl_._cached_size_)*/{} + , decltype(_impl_.uninterpreted_option_){from._impl_.uninterpreted_option_} + , decltype(_impl_.deprecated_){} + , decltype(_impl_.idempotency_level_){}}; + + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); + _impl_._extensions_.MergeFrom(internal_default_instance(), from._impl_._extensions_); + ::memcpy(&_impl_.deprecated_, &from._impl_.deprecated_, + static_cast<size_t>(reinterpret_cast<char*>(&_impl_.idempotency_level_) - + reinterpret_cast<char*>(&_impl_.deprecated_)) + sizeof(_impl_.idempotency_level_)); + // @@protoc_insertion_point(copy_constructor:google.protobuf.MethodOptions) +} + +inline void MethodOptions::SharedCtor( + ::_pb::Arena* arena, bool is_message_owned) { + (void)arena; + (void)is_message_owned; + new (&_impl_) Impl_{ + /*decltype(_impl_._extensions_)*/{::_pbi::ArenaInitialized(), arena} + , decltype(_impl_._has_bits_){} + , /*decltype(_impl_._cached_size_)*/{} + , decltype(_impl_.uninterpreted_option_){arena} + , decltype(_impl_.deprecated_){false} + , decltype(_impl_.idempotency_level_){0} + }; +} + +MethodOptions::~MethodOptions() { + // @@protoc_insertion_point(destructor:google.protobuf.MethodOptions) + if (auto *arena = _internal_metadata_.DeleteReturnArena<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>()) { + (void)arena; + return; + } + SharedDtor(); +} + +inline void MethodOptions::SharedDtor() { + GOOGLE_DCHECK(GetArenaForAllocation() == nullptr); + _impl_._extensions_.~ExtensionSet(); + _impl_.uninterpreted_option_.~RepeatedPtrField(); +} + +void MethodOptions::SetCachedSize(int size) const { + _impl_._cached_size_.Set(size); +} + +void MethodOptions::Clear() { +// @@protoc_insertion_point(message_clear_start:google.protobuf.MethodOptions) + uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + _impl_._extensions_.Clear(); + _impl_.uninterpreted_option_.Clear(); + cached_has_bits = _impl_._has_bits_[0]; + if (cached_has_bits & 0x00000003u) { + ::memset(&_impl_.deprecated_, 0, static_cast<size_t>( + reinterpret_cast<char*>(&_impl_.idempotency_level_) - + reinterpret_cast<char*>(&_impl_.deprecated_)) + sizeof(_impl_.idempotency_level_)); + } + _impl_._has_bits_.Clear(); + _internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); +} + +const char* MethodOptions::_InternalParse(const char* ptr, ::_pbi::ParseContext* ctx) { +#define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure + _Internal::HasBits has_bits{}; + while (!ctx->Done(&ptr)) { + uint32_t tag; + ptr = ::_pbi::ReadTag(ptr, &tag); + switch (tag >> 3) { + // optional bool deprecated = 33 [default = false]; + case 33: + if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 8)) { + _Internal::set_has_deprecated(&has_bits); + _impl_.deprecated_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr); + CHK_(ptr); + } else + goto handle_unusual; + continue; + // optional .google.protobuf.MethodOptions.IdempotencyLevel idempotency_level = 34 [default = IDEMPOTENCY_UNKNOWN]; + case 34: + if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 16)) { + uint64_t val = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr); + CHK_(ptr); + if (PROTOBUF_PREDICT_TRUE(::PROTOBUF_NAMESPACE_ID::MethodOptions_IdempotencyLevel_IsValid(val))) { + _internal_set_idempotency_level(static_cast<::PROTOBUF_NAMESPACE_ID::MethodOptions_IdempotencyLevel>(val)); + } else { + ::PROTOBUF_NAMESPACE_ID::internal::WriteVarint(34, val, mutable_unknown_fields()); + } + } else + goto handle_unusual; + continue; + // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; + case 999: + if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 58)) { + ptr -= 2; + do { + ptr += 2; + ptr = ctx->ParseMessage(_internal_add_uninterpreted_option(), ptr); + CHK_(ptr); + if (!ctx->DataAvailable(ptr)) break; + } while (::PROTOBUF_NAMESPACE_ID::internal::ExpectTag<7994>(ptr)); + } else + goto handle_unusual; + continue; + default: + goto handle_unusual; + } // switch + handle_unusual: + if ((tag == 0) || ((tag & 7) == 4)) { + CHK_(ptr); + ctx->SetLastTag(tag); + goto message_done; + } + if ((8000u <= tag)) { + ptr = _impl_._extensions_.ParseField(tag, ptr, internal_default_instance(), &_internal_metadata_, ctx); + CHK_(ptr != nullptr); + continue; + } + ptr = UnknownFieldParse( + tag, + _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(), + ptr, ctx); + CHK_(ptr != nullptr); + } // while +message_done: + _impl_._has_bits_.Or(has_bits); + return ptr; +failure: + ptr = nullptr; + goto message_done; +#undef CHK_ +} + +uint8_t* MethodOptions::_InternalSerialize( + uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const { + // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.MethodOptions) + uint32_t cached_has_bits = 0; + (void) cached_has_bits; + + cached_has_bits = _impl_._has_bits_[0]; + // optional bool deprecated = 33 [default = false]; + if (cached_has_bits & 0x00000001u) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteBoolToArray(33, this->_internal_deprecated(), target); + } + + // optional .google.protobuf.MethodOptions.IdempotencyLevel idempotency_level = 34 [default = IDEMPOTENCY_UNKNOWN]; + if (cached_has_bits & 0x00000002u) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteEnumToArray( + 34, this->_internal_idempotency_level(), target); + } + + // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; + for (unsigned i = 0, + n = static_cast<unsigned>(this->_internal_uninterpreted_option_size()); i < n; i++) { + const auto& repfield = this->_internal_uninterpreted_option(i); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite:: + InternalWriteMessage(999, repfield, repfield.GetCachedSize(), target, stream); + } + + // Extension range [1000, 536870912) + target = _impl_._extensions_._InternalSerialize( + internal_default_instance(), 1000, 536870912, target, stream); + + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + target = ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( + _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.MethodOptions) + return target; +} + +size_t MethodOptions::ByteSizeLong() const { +// @@protoc_insertion_point(message_byte_size_start:google.protobuf.MethodOptions) + size_t total_size = 0; + + total_size += _impl_._extensions_.ByteSize(); + + uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; + total_size += 2UL * this->_internal_uninterpreted_option_size(); + for (const auto& msg : this->_impl_.uninterpreted_option_) { + total_size += + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::MessageSize(msg); + } + + cached_has_bits = _impl_._has_bits_[0]; + if (cached_has_bits & 0x00000003u) { + // optional bool deprecated = 33 [default = false]; + if (cached_has_bits & 0x00000001u) { + total_size += 2 + 1; + } + + // optional .google.protobuf.MethodOptions.IdempotencyLevel idempotency_level = 34 [default = IDEMPOTENCY_UNKNOWN]; + if (cached_has_bits & 0x00000002u) { + total_size += 2 + + ::_pbi::WireFormatLite::EnumSize(this->_internal_idempotency_level()); + } + + } + return MaybeComputeUnknownFieldsSize(total_size, &_impl_._cached_size_); +} + +const ::PROTOBUF_NAMESPACE_ID::Message::ClassData MethodOptions::_class_data_ = { + ::PROTOBUF_NAMESPACE_ID::Message::CopyWithSourceCheck, + MethodOptions::MergeImpl +}; +const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*MethodOptions::GetClassData() const { return &_class_data_; } + + +void MethodOptions::MergeImpl(::PROTOBUF_NAMESPACE_ID::Message& to_msg, const ::PROTOBUF_NAMESPACE_ID::Message& from_msg) { + auto* const _this = static_cast<MethodOptions*>(&to_msg); + auto& from = static_cast<const MethodOptions&>(from_msg); + // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.MethodOptions) + GOOGLE_DCHECK_NE(&from, _this); + uint32_t cached_has_bits = 0; + (void) cached_has_bits; + + _this->_impl_.uninterpreted_option_.MergeFrom(from._impl_.uninterpreted_option_); + cached_has_bits = from._impl_._has_bits_[0]; + if (cached_has_bits & 0x00000003u) { + if (cached_has_bits & 0x00000001u) { + _this->_impl_.deprecated_ = from._impl_.deprecated_; + } + if (cached_has_bits & 0x00000002u) { + _this->_impl_.idempotency_level_ = from._impl_.idempotency_level_; + } + _this->_impl_._has_bits_[0] |= cached_has_bits; + } + _this->_impl_._extensions_.MergeFrom(internal_default_instance(), from._impl_._extensions_); + _this->_internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); +} + +void MethodOptions::CopyFrom(const MethodOptions& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.MethodOptions) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool MethodOptions::IsInitialized() const { + if (!_impl_._extensions_.IsInitialized()) { + return false; + } + + if (!::PROTOBUF_NAMESPACE_ID::internal::AllAreInitialized(_impl_.uninterpreted_option_)) + return false; + return true; +} + +void MethodOptions::InternalSwap(MethodOptions* other) { + using std::swap; + _impl_._extensions_.InternalSwap(&other->_impl_._extensions_); + _internal_metadata_.InternalSwap(&other->_internal_metadata_); + swap(_impl_._has_bits_[0], other->_impl_._has_bits_[0]); + _impl_.uninterpreted_option_.InternalSwap(&other->_impl_.uninterpreted_option_); + ::PROTOBUF_NAMESPACE_ID::internal::memswap< + PROTOBUF_FIELD_OFFSET(MethodOptions, _impl_.idempotency_level_) + + sizeof(MethodOptions::_impl_.idempotency_level_) + - PROTOBUF_FIELD_OFFSET(MethodOptions, _impl_.deprecated_)>( + reinterpret_cast<char*>(&_impl_.deprecated_), + reinterpret_cast<char*>(&other->_impl_.deprecated_)); +} + +::PROTOBUF_NAMESPACE_ID::Metadata MethodOptions::GetMetadata() const { + return ::_pbi::AssignDescriptors( + &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_getter, &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_once, + file_level_metadata_google_2fprotobuf_2fdescriptor_2eproto[20]); +} + +// =================================================================== + +class UninterpretedOption_NamePart::_Internal { + public: + using HasBits = decltype(std::declval<UninterpretedOption_NamePart>()._impl_._has_bits_); + static void set_has_name_part(HasBits* has_bits) { + (*has_bits)[0] |= 1u; + } + static void set_has_is_extension(HasBits* has_bits) { + (*has_bits)[0] |= 2u; + } + static bool MissingRequiredFields(const HasBits& has_bits) { + return ((has_bits[0] & 0x00000003) ^ 0x00000003) != 0; + } +}; + +UninterpretedOption_NamePart::UninterpretedOption_NamePart(::PROTOBUF_NAMESPACE_ID::Arena* arena, + bool is_message_owned) + : ::PROTOBUF_NAMESPACE_ID::Message(arena, is_message_owned) { + SharedCtor(arena, is_message_owned); + // @@protoc_insertion_point(arena_constructor:google.protobuf.UninterpretedOption.NamePart) +} +UninterpretedOption_NamePart::UninterpretedOption_NamePart(const UninterpretedOption_NamePart& from) + : ::PROTOBUF_NAMESPACE_ID::Message() { + UninterpretedOption_NamePart* const _this = this; (void)_this; + new (&_impl_) Impl_{ + decltype(_impl_._has_bits_){from._impl_._has_bits_} + , /*decltype(_impl_._cached_size_)*/{} + , decltype(_impl_.name_part_){} + , decltype(_impl_.is_extension_){}}; + + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); + _impl_.name_part_.InitDefault(); + #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + _impl_.name_part_.Set("", GetArenaForAllocation()); + #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (from._internal_has_name_part()) { + _this->_impl_.name_part_.Set(from._internal_name_part(), + _this->GetArenaForAllocation()); + } + _this->_impl_.is_extension_ = from._impl_.is_extension_; + // @@protoc_insertion_point(copy_constructor:google.protobuf.UninterpretedOption.NamePart) +} + +inline void UninterpretedOption_NamePart::SharedCtor( + ::_pb::Arena* arena, bool is_message_owned) { + (void)arena; + (void)is_message_owned; + new (&_impl_) Impl_{ + decltype(_impl_._has_bits_){} + , /*decltype(_impl_._cached_size_)*/{} + , decltype(_impl_.name_part_){} + , decltype(_impl_.is_extension_){false} + }; + _impl_.name_part_.InitDefault(); + #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + _impl_.name_part_.Set("", GetArenaForAllocation()); + #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING +} + +UninterpretedOption_NamePart::~UninterpretedOption_NamePart() { + // @@protoc_insertion_point(destructor:google.protobuf.UninterpretedOption.NamePart) + if (auto *arena = _internal_metadata_.DeleteReturnArena<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>()) { + (void)arena; + return; + } + SharedDtor(); +} + +inline void UninterpretedOption_NamePart::SharedDtor() { + GOOGLE_DCHECK(GetArenaForAllocation() == nullptr); + _impl_.name_part_.Destroy(); +} + +void UninterpretedOption_NamePart::SetCachedSize(int size) const { + _impl_._cached_size_.Set(size); +} + +void UninterpretedOption_NamePart::Clear() { +// @@protoc_insertion_point(message_clear_start:google.protobuf.UninterpretedOption.NamePart) + uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + cached_has_bits = _impl_._has_bits_[0]; + if (cached_has_bits & 0x00000001u) { + _impl_.name_part_.ClearNonDefaultToEmpty(); + } + _impl_.is_extension_ = false; + _impl_._has_bits_.Clear(); + _internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); +} + +const char* UninterpretedOption_NamePart::_InternalParse(const char* ptr, ::_pbi::ParseContext* ctx) { +#define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure + _Internal::HasBits has_bits{}; + while (!ctx->Done(&ptr)) { + uint32_t tag; + ptr = ::_pbi::ReadTag(ptr, &tag); + switch (tag >> 3) { + // required string name_part = 1; + case 1: + if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 10)) { + auto str = _internal_mutable_name_part(); + ptr = ::_pbi::InlineGreedyStringParser(str, ptr, ctx); + CHK_(ptr); + #ifndef NDEBUG + ::_pbi::VerifyUTF8(str, "google.protobuf.UninterpretedOption.NamePart.name_part"); + #endif // !NDEBUG + } else + goto handle_unusual; + continue; + // required bool is_extension = 2; + case 2: + if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 16)) { + _Internal::set_has_is_extension(&has_bits); + _impl_.is_extension_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr); + CHK_(ptr); + } else + goto handle_unusual; + continue; + default: + goto handle_unusual; + } // switch + handle_unusual: + if ((tag == 0) || ((tag & 7) == 4)) { + CHK_(ptr); + ctx->SetLastTag(tag); + goto message_done; + } + ptr = UnknownFieldParse( + tag, + _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(), + ptr, ctx); + CHK_(ptr != nullptr); + } // while +message_done: + _impl_._has_bits_.Or(has_bits); + return ptr; +failure: + ptr = nullptr; + goto message_done; +#undef CHK_ +} + +uint8_t* UninterpretedOption_NamePart::_InternalSerialize( + uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const { + // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.UninterpretedOption.NamePart) + uint32_t cached_has_bits = 0; + (void) cached_has_bits; + + cached_has_bits = _impl_._has_bits_[0]; + // required string name_part = 1; + if (cached_has_bits & 0x00000001u) { + ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::VerifyUTF8StringNamedField( + this->_internal_name_part().data(), static_cast<int>(this->_internal_name_part().length()), + ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::SERIALIZE, + "google.protobuf.UninterpretedOption.NamePart.name_part"); + target = stream->WriteStringMaybeAliased( + 1, this->_internal_name_part(), target); + } + + // required bool is_extension = 2; + if (cached_has_bits & 0x00000002u) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteBoolToArray(2, this->_internal_is_extension(), target); + } + + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + target = ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( + _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.UninterpretedOption.NamePart) + return target; +} + +size_t UninterpretedOption_NamePart::RequiredFieldsByteSizeFallback() const { +// @@protoc_insertion_point(required_fields_byte_size_fallback_start:google.protobuf.UninterpretedOption.NamePart) + size_t total_size = 0; + + if (_internal_has_name_part()) { + // required string name_part = 1; + total_size += 1 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize( + this->_internal_name_part()); + } + + if (_internal_has_is_extension()) { + // required bool is_extension = 2; + total_size += 1 + 1; + } + + return total_size; +} +size_t UninterpretedOption_NamePart::ByteSizeLong() const { +// @@protoc_insertion_point(message_byte_size_start:google.protobuf.UninterpretedOption.NamePart) + size_t total_size = 0; + + if (((_impl_._has_bits_[0] & 0x00000003) ^ 0x00000003) == 0) { // All required fields are present. + // required string name_part = 1; + total_size += 1 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize( + this->_internal_name_part()); + + // required bool is_extension = 2; + total_size += 1 + 1; + + } else { + total_size += RequiredFieldsByteSizeFallback(); + } + uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + return MaybeComputeUnknownFieldsSize(total_size, &_impl_._cached_size_); +} + +const ::PROTOBUF_NAMESPACE_ID::Message::ClassData UninterpretedOption_NamePart::_class_data_ = { + ::PROTOBUF_NAMESPACE_ID::Message::CopyWithSourceCheck, + UninterpretedOption_NamePart::MergeImpl +}; +const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*UninterpretedOption_NamePart::GetClassData() const { return &_class_data_; } + + +void UninterpretedOption_NamePart::MergeImpl(::PROTOBUF_NAMESPACE_ID::Message& to_msg, const ::PROTOBUF_NAMESPACE_ID::Message& from_msg) { + auto* const _this = static_cast<UninterpretedOption_NamePart*>(&to_msg); + auto& from = static_cast<const UninterpretedOption_NamePart&>(from_msg); + // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.UninterpretedOption.NamePart) + GOOGLE_DCHECK_NE(&from, _this); + uint32_t cached_has_bits = 0; + (void) cached_has_bits; + + cached_has_bits = from._impl_._has_bits_[0]; + if (cached_has_bits & 0x00000003u) { + if (cached_has_bits & 0x00000001u) { + _this->_internal_set_name_part(from._internal_name_part()); + } + if (cached_has_bits & 0x00000002u) { + _this->_impl_.is_extension_ = from._impl_.is_extension_; + } + _this->_impl_._has_bits_[0] |= cached_has_bits; + } + _this->_internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); +} + +void UninterpretedOption_NamePart::CopyFrom(const UninterpretedOption_NamePart& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.UninterpretedOption.NamePart) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool UninterpretedOption_NamePart::IsInitialized() const { + if (_Internal::MissingRequiredFields(_impl_._has_bits_)) return false; + return true; +} + +void UninterpretedOption_NamePart::InternalSwap(UninterpretedOption_NamePart* other) { + using std::swap; + auto* lhs_arena = GetArenaForAllocation(); + auto* rhs_arena = other->GetArenaForAllocation(); + _internal_metadata_.InternalSwap(&other->_internal_metadata_); + swap(_impl_._has_bits_[0], other->_impl_._has_bits_[0]); + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::InternalSwap( + &_impl_.name_part_, lhs_arena, + &other->_impl_.name_part_, rhs_arena + ); + swap(_impl_.is_extension_, other->_impl_.is_extension_); +} + +::PROTOBUF_NAMESPACE_ID::Metadata UninterpretedOption_NamePart::GetMetadata() const { + return ::_pbi::AssignDescriptors( + &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_getter, &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_once, + file_level_metadata_google_2fprotobuf_2fdescriptor_2eproto[21]); +} + +// =================================================================== + +class UninterpretedOption::_Internal { + public: + using HasBits = decltype(std::declval<UninterpretedOption>()._impl_._has_bits_); + static void set_has_identifier_value(HasBits* has_bits) { + (*has_bits)[0] |= 1u; + } + static void set_has_positive_int_value(HasBits* has_bits) { + (*has_bits)[0] |= 8u; + } + static void set_has_negative_int_value(HasBits* has_bits) { + (*has_bits)[0] |= 16u; + } + static void set_has_double_value(HasBits* has_bits) { + (*has_bits)[0] |= 32u; + } + static void set_has_string_value(HasBits* has_bits) { + (*has_bits)[0] |= 2u; + } + static void set_has_aggregate_value(HasBits* has_bits) { + (*has_bits)[0] |= 4u; + } +}; + +UninterpretedOption::UninterpretedOption(::PROTOBUF_NAMESPACE_ID::Arena* arena, + bool is_message_owned) + : ::PROTOBUF_NAMESPACE_ID::Message(arena, is_message_owned) { + SharedCtor(arena, is_message_owned); + // @@protoc_insertion_point(arena_constructor:google.protobuf.UninterpretedOption) +} +UninterpretedOption::UninterpretedOption(const UninterpretedOption& from) + : ::PROTOBUF_NAMESPACE_ID::Message() { + UninterpretedOption* const _this = this; (void)_this; + new (&_impl_) Impl_{ + decltype(_impl_._has_bits_){from._impl_._has_bits_} + , /*decltype(_impl_._cached_size_)*/{} + , decltype(_impl_.name_){from._impl_.name_} + , decltype(_impl_.identifier_value_){} + , decltype(_impl_.string_value_){} + , decltype(_impl_.aggregate_value_){} + , decltype(_impl_.positive_int_value_){} + , decltype(_impl_.negative_int_value_){} + , decltype(_impl_.double_value_){}}; + + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); + _impl_.identifier_value_.InitDefault(); + #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + _impl_.identifier_value_.Set("", GetArenaForAllocation()); + #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (from._internal_has_identifier_value()) { + _this->_impl_.identifier_value_.Set(from._internal_identifier_value(), + _this->GetArenaForAllocation()); + } + _impl_.string_value_.InitDefault(); + #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + _impl_.string_value_.Set("", GetArenaForAllocation()); + #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (from._internal_has_string_value()) { + _this->_impl_.string_value_.Set(from._internal_string_value(), + _this->GetArenaForAllocation()); + } + _impl_.aggregate_value_.InitDefault(); + #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + _impl_.aggregate_value_.Set("", GetArenaForAllocation()); + #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (from._internal_has_aggregate_value()) { + _this->_impl_.aggregate_value_.Set(from._internal_aggregate_value(), + _this->GetArenaForAllocation()); + } + ::memcpy(&_impl_.positive_int_value_, &from._impl_.positive_int_value_, + static_cast<size_t>(reinterpret_cast<char*>(&_impl_.double_value_) - + reinterpret_cast<char*>(&_impl_.positive_int_value_)) + sizeof(_impl_.double_value_)); + // @@protoc_insertion_point(copy_constructor:google.protobuf.UninterpretedOption) +} + +inline void UninterpretedOption::SharedCtor( + ::_pb::Arena* arena, bool is_message_owned) { + (void)arena; + (void)is_message_owned; + new (&_impl_) Impl_{ + decltype(_impl_._has_bits_){} + , /*decltype(_impl_._cached_size_)*/{} + , decltype(_impl_.name_){arena} + , decltype(_impl_.identifier_value_){} + , decltype(_impl_.string_value_){} + , decltype(_impl_.aggregate_value_){} + , decltype(_impl_.positive_int_value_){uint64_t{0u}} + , decltype(_impl_.negative_int_value_){int64_t{0}} + , decltype(_impl_.double_value_){0} + }; + _impl_.identifier_value_.InitDefault(); + #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + _impl_.identifier_value_.Set("", GetArenaForAllocation()); + #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + _impl_.string_value_.InitDefault(); + #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + _impl_.string_value_.Set("", GetArenaForAllocation()); + #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + _impl_.aggregate_value_.InitDefault(); + #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + _impl_.aggregate_value_.Set("", GetArenaForAllocation()); + #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING +} + +UninterpretedOption::~UninterpretedOption() { + // @@protoc_insertion_point(destructor:google.protobuf.UninterpretedOption) + if (auto *arena = _internal_metadata_.DeleteReturnArena<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>()) { + (void)arena; + return; + } + SharedDtor(); +} + +inline void UninterpretedOption::SharedDtor() { + GOOGLE_DCHECK(GetArenaForAllocation() == nullptr); + _impl_.name_.~RepeatedPtrField(); + _impl_.identifier_value_.Destroy(); + _impl_.string_value_.Destroy(); + _impl_.aggregate_value_.Destroy(); +} + +void UninterpretedOption::SetCachedSize(int size) const { + _impl_._cached_size_.Set(size); +} + +void UninterpretedOption::Clear() { +// @@protoc_insertion_point(message_clear_start:google.protobuf.UninterpretedOption) + uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + _impl_.name_.Clear(); + cached_has_bits = _impl_._has_bits_[0]; + if (cached_has_bits & 0x00000007u) { + if (cached_has_bits & 0x00000001u) { + _impl_.identifier_value_.ClearNonDefaultToEmpty(); + } + if (cached_has_bits & 0x00000002u) { + _impl_.string_value_.ClearNonDefaultToEmpty(); + } + if (cached_has_bits & 0x00000004u) { + _impl_.aggregate_value_.ClearNonDefaultToEmpty(); + } + } + if (cached_has_bits & 0x00000038u) { + ::memset(&_impl_.positive_int_value_, 0, static_cast<size_t>( + reinterpret_cast<char*>(&_impl_.double_value_) - + reinterpret_cast<char*>(&_impl_.positive_int_value_)) + sizeof(_impl_.double_value_)); + } + _impl_._has_bits_.Clear(); + _internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); +} + +const char* UninterpretedOption::_InternalParse(const char* ptr, ::_pbi::ParseContext* ctx) { +#define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure + _Internal::HasBits has_bits{}; + while (!ctx->Done(&ptr)) { + uint32_t tag; + ptr = ::_pbi::ReadTag(ptr, &tag); + switch (tag >> 3) { + // repeated .google.protobuf.UninterpretedOption.NamePart name = 2; + case 2: + if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 18)) { + ptr -= 1; + do { + ptr += 1; + ptr = ctx->ParseMessage(_internal_add_name(), ptr); + CHK_(ptr); + if (!ctx->DataAvailable(ptr)) break; + } while (::PROTOBUF_NAMESPACE_ID::internal::ExpectTag<18>(ptr)); + } else + goto handle_unusual; + continue; + // optional string identifier_value = 3; + case 3: + if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 26)) { + auto str = _internal_mutable_identifier_value(); + ptr = ::_pbi::InlineGreedyStringParser(str, ptr, ctx); + CHK_(ptr); + #ifndef NDEBUG + ::_pbi::VerifyUTF8(str, "google.protobuf.UninterpretedOption.identifier_value"); + #endif // !NDEBUG + } else + goto handle_unusual; + continue; + // optional uint64 positive_int_value = 4; + case 4: + if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 32)) { + _Internal::set_has_positive_int_value(&has_bits); + _impl_.positive_int_value_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr); + CHK_(ptr); + } else + goto handle_unusual; + continue; + // optional int64 negative_int_value = 5; + case 5: + if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 40)) { + _Internal::set_has_negative_int_value(&has_bits); + _impl_.negative_int_value_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr); + CHK_(ptr); + } else + goto handle_unusual; + continue; + // optional double double_value = 6; + case 6: + if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 49)) { + _Internal::set_has_double_value(&has_bits); + _impl_.double_value_ = ::PROTOBUF_NAMESPACE_ID::internal::UnalignedLoad<double>(ptr); + ptr += sizeof(double); + } else + goto handle_unusual; + continue; + // optional bytes string_value = 7; + case 7: + if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 58)) { + auto str = _internal_mutable_string_value(); + ptr = ::_pbi::InlineGreedyStringParser(str, ptr, ctx); + CHK_(ptr); + } else + goto handle_unusual; + continue; + // optional string aggregate_value = 8; + case 8: + if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 66)) { + auto str = _internal_mutable_aggregate_value(); + ptr = ::_pbi::InlineGreedyStringParser(str, ptr, ctx); + CHK_(ptr); + #ifndef NDEBUG + ::_pbi::VerifyUTF8(str, "google.protobuf.UninterpretedOption.aggregate_value"); + #endif // !NDEBUG + } else + goto handle_unusual; + continue; + default: + goto handle_unusual; + } // switch + handle_unusual: + if ((tag == 0) || ((tag & 7) == 4)) { + CHK_(ptr); + ctx->SetLastTag(tag); + goto message_done; + } + ptr = UnknownFieldParse( + tag, + _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(), + ptr, ctx); + CHK_(ptr != nullptr); + } // while +message_done: + _impl_._has_bits_.Or(has_bits); + return ptr; +failure: + ptr = nullptr; + goto message_done; +#undef CHK_ +} + +uint8_t* UninterpretedOption::_InternalSerialize( + uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const { + // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.UninterpretedOption) + uint32_t cached_has_bits = 0; + (void) cached_has_bits; + + // repeated .google.protobuf.UninterpretedOption.NamePart name = 2; + for (unsigned i = 0, + n = static_cast<unsigned>(this->_internal_name_size()); i < n; i++) { + const auto& repfield = this->_internal_name(i); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite:: + InternalWriteMessage(2, repfield, repfield.GetCachedSize(), target, stream); + } + + cached_has_bits = _impl_._has_bits_[0]; + // optional string identifier_value = 3; + if (cached_has_bits & 0x00000001u) { + ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::VerifyUTF8StringNamedField( + this->_internal_identifier_value().data(), static_cast<int>(this->_internal_identifier_value().length()), + ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::SERIALIZE, + "google.protobuf.UninterpretedOption.identifier_value"); + target = stream->WriteStringMaybeAliased( + 3, this->_internal_identifier_value(), target); + } + + // optional uint64 positive_int_value = 4; + if (cached_has_bits & 0x00000008u) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteUInt64ToArray(4, this->_internal_positive_int_value(), target); + } + + // optional int64 negative_int_value = 5; + if (cached_has_bits & 0x00000010u) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteInt64ToArray(5, this->_internal_negative_int_value(), target); + } + + // optional double double_value = 6; + if (cached_has_bits & 0x00000020u) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteDoubleToArray(6, this->_internal_double_value(), target); + } + + // optional bytes string_value = 7; + if (cached_has_bits & 0x00000002u) { + target = stream->WriteBytesMaybeAliased( + 7, this->_internal_string_value(), target); + } + + // optional string aggregate_value = 8; + if (cached_has_bits & 0x00000004u) { + ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::VerifyUTF8StringNamedField( + this->_internal_aggregate_value().data(), static_cast<int>(this->_internal_aggregate_value().length()), + ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::SERIALIZE, + "google.protobuf.UninterpretedOption.aggregate_value"); + target = stream->WriteStringMaybeAliased( + 8, this->_internal_aggregate_value(), target); + } + + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + target = ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( + _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.UninterpretedOption) + return target; +} + +size_t UninterpretedOption::ByteSizeLong() const { +// @@protoc_insertion_point(message_byte_size_start:google.protobuf.UninterpretedOption) + size_t total_size = 0; + + uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + // repeated .google.protobuf.UninterpretedOption.NamePart name = 2; + total_size += 1UL * this->_internal_name_size(); + for (const auto& msg : this->_impl_.name_) { + total_size += + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::MessageSize(msg); + } + + cached_has_bits = _impl_._has_bits_[0]; + if (cached_has_bits & 0x0000003fu) { + // optional string identifier_value = 3; + if (cached_has_bits & 0x00000001u) { + total_size += 1 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize( + this->_internal_identifier_value()); + } + + // optional bytes string_value = 7; + if (cached_has_bits & 0x00000002u) { + total_size += 1 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::BytesSize( + this->_internal_string_value()); + } + + // optional string aggregate_value = 8; + if (cached_has_bits & 0x00000004u) { + total_size += 1 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize( + this->_internal_aggregate_value()); + } + + // optional uint64 positive_int_value = 4; + if (cached_has_bits & 0x00000008u) { + total_size += ::_pbi::WireFormatLite::UInt64SizePlusOne(this->_internal_positive_int_value()); + } + + // optional int64 negative_int_value = 5; + if (cached_has_bits & 0x00000010u) { + total_size += ::_pbi::WireFormatLite::Int64SizePlusOne(this->_internal_negative_int_value()); + } + + // optional double double_value = 6; + if (cached_has_bits & 0x00000020u) { + total_size += 1 + 8; + } + + } + return MaybeComputeUnknownFieldsSize(total_size, &_impl_._cached_size_); +} + +const ::PROTOBUF_NAMESPACE_ID::Message::ClassData UninterpretedOption::_class_data_ = { + ::PROTOBUF_NAMESPACE_ID::Message::CopyWithSourceCheck, + UninterpretedOption::MergeImpl +}; +const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*UninterpretedOption::GetClassData() const { return &_class_data_; } + + +void UninterpretedOption::MergeImpl(::PROTOBUF_NAMESPACE_ID::Message& to_msg, const ::PROTOBUF_NAMESPACE_ID::Message& from_msg) { + auto* const _this = static_cast<UninterpretedOption*>(&to_msg); + auto& from = static_cast<const UninterpretedOption&>(from_msg); + // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.UninterpretedOption) + GOOGLE_DCHECK_NE(&from, _this); + uint32_t cached_has_bits = 0; + (void) cached_has_bits; + + _this->_impl_.name_.MergeFrom(from._impl_.name_); + cached_has_bits = from._impl_._has_bits_[0]; + if (cached_has_bits & 0x0000003fu) { + if (cached_has_bits & 0x00000001u) { + _this->_internal_set_identifier_value(from._internal_identifier_value()); + } + if (cached_has_bits & 0x00000002u) { + _this->_internal_set_string_value(from._internal_string_value()); + } + if (cached_has_bits & 0x00000004u) { + _this->_internal_set_aggregate_value(from._internal_aggregate_value()); + } + if (cached_has_bits & 0x00000008u) { + _this->_impl_.positive_int_value_ = from._impl_.positive_int_value_; + } + if (cached_has_bits & 0x00000010u) { + _this->_impl_.negative_int_value_ = from._impl_.negative_int_value_; + } + if (cached_has_bits & 0x00000020u) { + _this->_impl_.double_value_ = from._impl_.double_value_; + } + _this->_impl_._has_bits_[0] |= cached_has_bits; + } + _this->_internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); +} + +void UninterpretedOption::CopyFrom(const UninterpretedOption& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.UninterpretedOption) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool UninterpretedOption::IsInitialized() const { + if (!::PROTOBUF_NAMESPACE_ID::internal::AllAreInitialized(_impl_.name_)) + return false; + return true; +} + +void UninterpretedOption::InternalSwap(UninterpretedOption* other) { + using std::swap; + auto* lhs_arena = GetArenaForAllocation(); + auto* rhs_arena = other->GetArenaForAllocation(); + _internal_metadata_.InternalSwap(&other->_internal_metadata_); + swap(_impl_._has_bits_[0], other->_impl_._has_bits_[0]); + _impl_.name_.InternalSwap(&other->_impl_.name_); + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::InternalSwap( + &_impl_.identifier_value_, lhs_arena, + &other->_impl_.identifier_value_, rhs_arena + ); + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::InternalSwap( + &_impl_.string_value_, lhs_arena, + &other->_impl_.string_value_, rhs_arena + ); + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::InternalSwap( + &_impl_.aggregate_value_, lhs_arena, + &other->_impl_.aggregate_value_, rhs_arena + ); + ::PROTOBUF_NAMESPACE_ID::internal::memswap< + PROTOBUF_FIELD_OFFSET(UninterpretedOption, _impl_.double_value_) + + sizeof(UninterpretedOption::_impl_.double_value_) + - PROTOBUF_FIELD_OFFSET(UninterpretedOption, _impl_.positive_int_value_)>( + reinterpret_cast<char*>(&_impl_.positive_int_value_), + reinterpret_cast<char*>(&other->_impl_.positive_int_value_)); +} + +::PROTOBUF_NAMESPACE_ID::Metadata UninterpretedOption::GetMetadata() const { + return ::_pbi::AssignDescriptors( + &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_getter, &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_once, + file_level_metadata_google_2fprotobuf_2fdescriptor_2eproto[22]); +} + +// =================================================================== + +class SourceCodeInfo_Location::_Internal { + public: + using HasBits = decltype(std::declval<SourceCodeInfo_Location>()._impl_._has_bits_); + static void set_has_leading_comments(HasBits* has_bits) { + (*has_bits)[0] |= 1u; + } + static void set_has_trailing_comments(HasBits* has_bits) { + (*has_bits)[0] |= 2u; + } +}; + +SourceCodeInfo_Location::SourceCodeInfo_Location(::PROTOBUF_NAMESPACE_ID::Arena* arena, + bool is_message_owned) + : ::PROTOBUF_NAMESPACE_ID::Message(arena, is_message_owned) { + SharedCtor(arena, is_message_owned); + // @@protoc_insertion_point(arena_constructor:google.protobuf.SourceCodeInfo.Location) +} +SourceCodeInfo_Location::SourceCodeInfo_Location(const SourceCodeInfo_Location& from) + : ::PROTOBUF_NAMESPACE_ID::Message() { + SourceCodeInfo_Location* const _this = this; (void)_this; + new (&_impl_) Impl_{ + decltype(_impl_._has_bits_){from._impl_._has_bits_} + , /*decltype(_impl_._cached_size_)*/{} + , decltype(_impl_.path_){from._impl_.path_} + , /*decltype(_impl_._path_cached_byte_size_)*/{0} + , decltype(_impl_.span_){from._impl_.span_} + , /*decltype(_impl_._span_cached_byte_size_)*/{0} + , decltype(_impl_.leading_detached_comments_){from._impl_.leading_detached_comments_} + , decltype(_impl_.leading_comments_){} + , decltype(_impl_.trailing_comments_){}}; + + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); + _impl_.leading_comments_.InitDefault(); + #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + _impl_.leading_comments_.Set("", GetArenaForAllocation()); + #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (from._internal_has_leading_comments()) { + _this->_impl_.leading_comments_.Set(from._internal_leading_comments(), + _this->GetArenaForAllocation()); + } + _impl_.trailing_comments_.InitDefault(); + #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + _impl_.trailing_comments_.Set("", GetArenaForAllocation()); + #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (from._internal_has_trailing_comments()) { + _this->_impl_.trailing_comments_.Set(from._internal_trailing_comments(), + _this->GetArenaForAllocation()); + } + // @@protoc_insertion_point(copy_constructor:google.protobuf.SourceCodeInfo.Location) +} + +inline void SourceCodeInfo_Location::SharedCtor( + ::_pb::Arena* arena, bool is_message_owned) { + (void)arena; + (void)is_message_owned; + new (&_impl_) Impl_{ + decltype(_impl_._has_bits_){} + , /*decltype(_impl_._cached_size_)*/{} + , decltype(_impl_.path_){arena} + , /*decltype(_impl_._path_cached_byte_size_)*/{0} + , decltype(_impl_.span_){arena} + , /*decltype(_impl_._span_cached_byte_size_)*/{0} + , decltype(_impl_.leading_detached_comments_){arena} + , decltype(_impl_.leading_comments_){} + , decltype(_impl_.trailing_comments_){} + }; + _impl_.leading_comments_.InitDefault(); + #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + _impl_.leading_comments_.Set("", GetArenaForAllocation()); + #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + _impl_.trailing_comments_.InitDefault(); + #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + _impl_.trailing_comments_.Set("", GetArenaForAllocation()); + #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING +} + +SourceCodeInfo_Location::~SourceCodeInfo_Location() { + // @@protoc_insertion_point(destructor:google.protobuf.SourceCodeInfo.Location) + if (auto *arena = _internal_metadata_.DeleteReturnArena<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>()) { + (void)arena; + return; + } + SharedDtor(); +} + +inline void SourceCodeInfo_Location::SharedDtor() { + GOOGLE_DCHECK(GetArenaForAllocation() == nullptr); + _impl_.path_.~RepeatedField(); + _impl_.span_.~RepeatedField(); + _impl_.leading_detached_comments_.~RepeatedPtrField(); + _impl_.leading_comments_.Destroy(); + _impl_.trailing_comments_.Destroy(); +} + +void SourceCodeInfo_Location::SetCachedSize(int size) const { + _impl_._cached_size_.Set(size); +} + +void SourceCodeInfo_Location::Clear() { +// @@protoc_insertion_point(message_clear_start:google.protobuf.SourceCodeInfo.Location) + uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + _impl_.path_.Clear(); + _impl_.span_.Clear(); + _impl_.leading_detached_comments_.Clear(); + cached_has_bits = _impl_._has_bits_[0]; + if (cached_has_bits & 0x00000003u) { + if (cached_has_bits & 0x00000001u) { + _impl_.leading_comments_.ClearNonDefaultToEmpty(); + } + if (cached_has_bits & 0x00000002u) { + _impl_.trailing_comments_.ClearNonDefaultToEmpty(); + } + } + _impl_._has_bits_.Clear(); + _internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); +} + +const char* SourceCodeInfo_Location::_InternalParse(const char* ptr, ::_pbi::ParseContext* ctx) { +#define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure + _Internal::HasBits has_bits{}; + while (!ctx->Done(&ptr)) { + uint32_t tag; + ptr = ::_pbi::ReadTag(ptr, &tag); + switch (tag >> 3) { + // repeated int32 path = 1 [packed = true]; + case 1: + if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 10)) { + ptr = ::PROTOBUF_NAMESPACE_ID::internal::PackedInt32Parser(_internal_mutable_path(), ptr, ctx); + CHK_(ptr); + } else if (static_cast<uint8_t>(tag) == 8) { + _internal_add_path(::PROTOBUF_NAMESPACE_ID::internal::ReadVarint32(&ptr)); + CHK_(ptr); + } else + goto handle_unusual; + continue; + // repeated int32 span = 2 [packed = true]; + case 2: + if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 18)) { + ptr = ::PROTOBUF_NAMESPACE_ID::internal::PackedInt32Parser(_internal_mutable_span(), ptr, ctx); + CHK_(ptr); + } else if (static_cast<uint8_t>(tag) == 16) { + _internal_add_span(::PROTOBUF_NAMESPACE_ID::internal::ReadVarint32(&ptr)); + CHK_(ptr); + } else + goto handle_unusual; + continue; + // optional string leading_comments = 3; + case 3: + if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 26)) { + auto str = _internal_mutable_leading_comments(); + ptr = ::_pbi::InlineGreedyStringParser(str, ptr, ctx); + CHK_(ptr); + #ifndef NDEBUG + ::_pbi::VerifyUTF8(str, "google.protobuf.SourceCodeInfo.Location.leading_comments"); + #endif // !NDEBUG + } else + goto handle_unusual; + continue; + // optional string trailing_comments = 4; + case 4: + if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 34)) { + auto str = _internal_mutable_trailing_comments(); + ptr = ::_pbi::InlineGreedyStringParser(str, ptr, ctx); + CHK_(ptr); + #ifndef NDEBUG + ::_pbi::VerifyUTF8(str, "google.protobuf.SourceCodeInfo.Location.trailing_comments"); + #endif // !NDEBUG + } else + goto handle_unusual; + continue; + // repeated string leading_detached_comments = 6; + case 6: + if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 50)) { + ptr -= 1; + do { + ptr += 1; + auto str = _internal_add_leading_detached_comments(); + ptr = ::_pbi::InlineGreedyStringParser(str, ptr, ctx); + CHK_(ptr); + #ifndef NDEBUG + ::_pbi::VerifyUTF8(str, "google.protobuf.SourceCodeInfo.Location.leading_detached_comments"); + #endif // !NDEBUG + if (!ctx->DataAvailable(ptr)) break; + } while (::PROTOBUF_NAMESPACE_ID::internal::ExpectTag<50>(ptr)); + } else + goto handle_unusual; + continue; + default: + goto handle_unusual; + } // switch + handle_unusual: + if ((tag == 0) || ((tag & 7) == 4)) { + CHK_(ptr); + ctx->SetLastTag(tag); + goto message_done; + } + ptr = UnknownFieldParse( + tag, + _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(), + ptr, ctx); + CHK_(ptr != nullptr); + } // while +message_done: + _impl_._has_bits_.Or(has_bits); + return ptr; +failure: + ptr = nullptr; + goto message_done; +#undef CHK_ +} + +uint8_t* SourceCodeInfo_Location::_InternalSerialize( + uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const { + // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.SourceCodeInfo.Location) + uint32_t cached_has_bits = 0; + (void) cached_has_bits; + + // repeated int32 path = 1 [packed = true]; + { + int byte_size = _impl_._path_cached_byte_size_.load(std::memory_order_relaxed); + if (byte_size > 0) { + target = stream->WriteInt32Packed( + 1, _internal_path(), byte_size, target); + } + } + + // repeated int32 span = 2 [packed = true]; + { + int byte_size = _impl_._span_cached_byte_size_.load(std::memory_order_relaxed); + if (byte_size > 0) { + target = stream->WriteInt32Packed( + 2, _internal_span(), byte_size, target); + } + } + + cached_has_bits = _impl_._has_bits_[0]; + // optional string leading_comments = 3; + if (cached_has_bits & 0x00000001u) { + ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::VerifyUTF8StringNamedField( + this->_internal_leading_comments().data(), static_cast<int>(this->_internal_leading_comments().length()), + ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::SERIALIZE, + "google.protobuf.SourceCodeInfo.Location.leading_comments"); + target = stream->WriteStringMaybeAliased( + 3, this->_internal_leading_comments(), target); + } + + // optional string trailing_comments = 4; + if (cached_has_bits & 0x00000002u) { + ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::VerifyUTF8StringNamedField( + this->_internal_trailing_comments().data(), static_cast<int>(this->_internal_trailing_comments().length()), + ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::SERIALIZE, + "google.protobuf.SourceCodeInfo.Location.trailing_comments"); + target = stream->WriteStringMaybeAliased( + 4, this->_internal_trailing_comments(), target); + } + + // repeated string leading_detached_comments = 6; + for (int i = 0, n = this->_internal_leading_detached_comments_size(); i < n; i++) { + const auto& s = this->_internal_leading_detached_comments(i); + ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::VerifyUTF8StringNamedField( + s.data(), static_cast<int>(s.length()), + ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::SERIALIZE, + "google.protobuf.SourceCodeInfo.Location.leading_detached_comments"); + target = stream->WriteString(6, s, target); + } + + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + target = ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( + _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.SourceCodeInfo.Location) + return target; +} + +size_t SourceCodeInfo_Location::ByteSizeLong() const { +// @@protoc_insertion_point(message_byte_size_start:google.protobuf.SourceCodeInfo.Location) + size_t total_size = 0; + + uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + // repeated int32 path = 1 [packed = true]; + { + size_t data_size = ::_pbi::WireFormatLite:: + Int32Size(this->_impl_.path_); + if (data_size > 0) { + total_size += 1 + + ::_pbi::WireFormatLite::Int32Size(static_cast<int32_t>(data_size)); + } + int cached_size = ::_pbi::ToCachedSize(data_size); + _impl_._path_cached_byte_size_.store(cached_size, + std::memory_order_relaxed); + total_size += data_size; + } + + // repeated int32 span = 2 [packed = true]; + { + size_t data_size = ::_pbi::WireFormatLite:: + Int32Size(this->_impl_.span_); + if (data_size > 0) { + total_size += 1 + + ::_pbi::WireFormatLite::Int32Size(static_cast<int32_t>(data_size)); + } + int cached_size = ::_pbi::ToCachedSize(data_size); + _impl_._span_cached_byte_size_.store(cached_size, + std::memory_order_relaxed); + total_size += data_size; + } + + // repeated string leading_detached_comments = 6; + total_size += 1 * + ::PROTOBUF_NAMESPACE_ID::internal::FromIntSize(_impl_.leading_detached_comments_.size()); + for (int i = 0, n = _impl_.leading_detached_comments_.size(); i < n; i++) { + total_size += ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize( + _impl_.leading_detached_comments_.Get(i)); + } + + cached_has_bits = _impl_._has_bits_[0]; + if (cached_has_bits & 0x00000003u) { + // optional string leading_comments = 3; + if (cached_has_bits & 0x00000001u) { + total_size += 1 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize( + this->_internal_leading_comments()); + } + + // optional string trailing_comments = 4; + if (cached_has_bits & 0x00000002u) { + total_size += 1 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize( + this->_internal_trailing_comments()); + } + + } + return MaybeComputeUnknownFieldsSize(total_size, &_impl_._cached_size_); +} + +const ::PROTOBUF_NAMESPACE_ID::Message::ClassData SourceCodeInfo_Location::_class_data_ = { + ::PROTOBUF_NAMESPACE_ID::Message::CopyWithSourceCheck, + SourceCodeInfo_Location::MergeImpl +}; +const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*SourceCodeInfo_Location::GetClassData() const { return &_class_data_; } + + +void SourceCodeInfo_Location::MergeImpl(::PROTOBUF_NAMESPACE_ID::Message& to_msg, const ::PROTOBUF_NAMESPACE_ID::Message& from_msg) { + auto* const _this = static_cast<SourceCodeInfo_Location*>(&to_msg); + auto& from = static_cast<const SourceCodeInfo_Location&>(from_msg); + // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.SourceCodeInfo.Location) + GOOGLE_DCHECK_NE(&from, _this); + uint32_t cached_has_bits = 0; + (void) cached_has_bits; + + _this->_impl_.path_.MergeFrom(from._impl_.path_); + _this->_impl_.span_.MergeFrom(from._impl_.span_); + _this->_impl_.leading_detached_comments_.MergeFrom(from._impl_.leading_detached_comments_); + cached_has_bits = from._impl_._has_bits_[0]; + if (cached_has_bits & 0x00000003u) { + if (cached_has_bits & 0x00000001u) { + _this->_internal_set_leading_comments(from._internal_leading_comments()); + } + if (cached_has_bits & 0x00000002u) { + _this->_internal_set_trailing_comments(from._internal_trailing_comments()); + } + } + _this->_internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); +} + +void SourceCodeInfo_Location::CopyFrom(const SourceCodeInfo_Location& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.SourceCodeInfo.Location) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool SourceCodeInfo_Location::IsInitialized() const { + return true; +} + +void SourceCodeInfo_Location::InternalSwap(SourceCodeInfo_Location* other) { + using std::swap; + auto* lhs_arena = GetArenaForAllocation(); + auto* rhs_arena = other->GetArenaForAllocation(); + _internal_metadata_.InternalSwap(&other->_internal_metadata_); + swap(_impl_._has_bits_[0], other->_impl_._has_bits_[0]); + _impl_.path_.InternalSwap(&other->_impl_.path_); + _impl_.span_.InternalSwap(&other->_impl_.span_); + _impl_.leading_detached_comments_.InternalSwap(&other->_impl_.leading_detached_comments_); + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::InternalSwap( + &_impl_.leading_comments_, lhs_arena, + &other->_impl_.leading_comments_, rhs_arena + ); + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::InternalSwap( + &_impl_.trailing_comments_, lhs_arena, + &other->_impl_.trailing_comments_, rhs_arena + ); +} + +::PROTOBUF_NAMESPACE_ID::Metadata SourceCodeInfo_Location::GetMetadata() const { + return ::_pbi::AssignDescriptors( + &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_getter, &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_once, + file_level_metadata_google_2fprotobuf_2fdescriptor_2eproto[23]); +} + +// =================================================================== + +class SourceCodeInfo::_Internal { + public: +}; + +SourceCodeInfo::SourceCodeInfo(::PROTOBUF_NAMESPACE_ID::Arena* arena, + bool is_message_owned) + : ::PROTOBUF_NAMESPACE_ID::Message(arena, is_message_owned) { + SharedCtor(arena, is_message_owned); + // @@protoc_insertion_point(arena_constructor:google.protobuf.SourceCodeInfo) +} +SourceCodeInfo::SourceCodeInfo(const SourceCodeInfo& from) + : ::PROTOBUF_NAMESPACE_ID::Message() { + SourceCodeInfo* const _this = this; (void)_this; + new (&_impl_) Impl_{ + decltype(_impl_.location_){from._impl_.location_} + , /*decltype(_impl_._cached_size_)*/{}}; + + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); + // @@protoc_insertion_point(copy_constructor:google.protobuf.SourceCodeInfo) +} + +inline void SourceCodeInfo::SharedCtor( + ::_pb::Arena* arena, bool is_message_owned) { + (void)arena; + (void)is_message_owned; + new (&_impl_) Impl_{ + decltype(_impl_.location_){arena} + , /*decltype(_impl_._cached_size_)*/{} + }; +} + +SourceCodeInfo::~SourceCodeInfo() { + // @@protoc_insertion_point(destructor:google.protobuf.SourceCodeInfo) + if (auto *arena = _internal_metadata_.DeleteReturnArena<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>()) { + (void)arena; + return; + } + SharedDtor(); +} + +inline void SourceCodeInfo::SharedDtor() { + GOOGLE_DCHECK(GetArenaForAllocation() == nullptr); + _impl_.location_.~RepeatedPtrField(); +} + +void SourceCodeInfo::SetCachedSize(int size) const { + _impl_._cached_size_.Set(size); +} + +void SourceCodeInfo::Clear() { +// @@protoc_insertion_point(message_clear_start:google.protobuf.SourceCodeInfo) + uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + _impl_.location_.Clear(); + _internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); +} + +const char* SourceCodeInfo::_InternalParse(const char* ptr, ::_pbi::ParseContext* ctx) { +#define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure + while (!ctx->Done(&ptr)) { + uint32_t tag; + ptr = ::_pbi::ReadTag(ptr, &tag); + switch (tag >> 3) { + // repeated .google.protobuf.SourceCodeInfo.Location location = 1; + case 1: + if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 10)) { + ptr -= 1; + do { + ptr += 1; + ptr = ctx->ParseMessage(_internal_add_location(), ptr); + CHK_(ptr); + if (!ctx->DataAvailable(ptr)) break; + } while (::PROTOBUF_NAMESPACE_ID::internal::ExpectTag<10>(ptr)); + } else + goto handle_unusual; + continue; + default: + goto handle_unusual; + } // switch + handle_unusual: + if ((tag == 0) || ((tag & 7) == 4)) { + CHK_(ptr); + ctx->SetLastTag(tag); + goto message_done; + } + ptr = UnknownFieldParse( + tag, + _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(), + ptr, ctx); + CHK_(ptr != nullptr); + } // while +message_done: + return ptr; +failure: + ptr = nullptr; + goto message_done; +#undef CHK_ +} + +uint8_t* SourceCodeInfo::_InternalSerialize( + uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const { + // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.SourceCodeInfo) + uint32_t cached_has_bits = 0; + (void) cached_has_bits; + + // repeated .google.protobuf.SourceCodeInfo.Location location = 1; + for (unsigned i = 0, + n = static_cast<unsigned>(this->_internal_location_size()); i < n; i++) { + const auto& repfield = this->_internal_location(i); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite:: + InternalWriteMessage(1, repfield, repfield.GetCachedSize(), target, stream); + } + + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + target = ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( + _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.SourceCodeInfo) + return target; +} + +size_t SourceCodeInfo::ByteSizeLong() const { +// @@protoc_insertion_point(message_byte_size_start:google.protobuf.SourceCodeInfo) + size_t total_size = 0; + + uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + // repeated .google.protobuf.SourceCodeInfo.Location location = 1; + total_size += 1UL * this->_internal_location_size(); + for (const auto& msg : this->_impl_.location_) { + total_size += + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::MessageSize(msg); + } + + return MaybeComputeUnknownFieldsSize(total_size, &_impl_._cached_size_); +} + +const ::PROTOBUF_NAMESPACE_ID::Message::ClassData SourceCodeInfo::_class_data_ = { + ::PROTOBUF_NAMESPACE_ID::Message::CopyWithSourceCheck, + SourceCodeInfo::MergeImpl +}; +const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*SourceCodeInfo::GetClassData() const { return &_class_data_; } + + +void SourceCodeInfo::MergeImpl(::PROTOBUF_NAMESPACE_ID::Message& to_msg, const ::PROTOBUF_NAMESPACE_ID::Message& from_msg) { + auto* const _this = static_cast<SourceCodeInfo*>(&to_msg); + auto& from = static_cast<const SourceCodeInfo&>(from_msg); + // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.SourceCodeInfo) + GOOGLE_DCHECK_NE(&from, _this); + uint32_t cached_has_bits = 0; + (void) cached_has_bits; + + _this->_impl_.location_.MergeFrom(from._impl_.location_); + _this->_internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); +} + +void SourceCodeInfo::CopyFrom(const SourceCodeInfo& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.SourceCodeInfo) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool SourceCodeInfo::IsInitialized() const { + return true; +} + +void SourceCodeInfo::InternalSwap(SourceCodeInfo* other) { + using std::swap; + _internal_metadata_.InternalSwap(&other->_internal_metadata_); + _impl_.location_.InternalSwap(&other->_impl_.location_); +} + +::PROTOBUF_NAMESPACE_ID::Metadata SourceCodeInfo::GetMetadata() const { + return ::_pbi::AssignDescriptors( + &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_getter, &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_once, + file_level_metadata_google_2fprotobuf_2fdescriptor_2eproto[24]); +} + +// =================================================================== + +class GeneratedCodeInfo_Annotation::_Internal { + public: + using HasBits = decltype(std::declval<GeneratedCodeInfo_Annotation>()._impl_._has_bits_); + static void set_has_source_file(HasBits* has_bits) { + (*has_bits)[0] |= 1u; + } + static void set_has_begin(HasBits* has_bits) { + (*has_bits)[0] |= 2u; + } + static void set_has_end(HasBits* has_bits) { + (*has_bits)[0] |= 4u; + } +}; + +GeneratedCodeInfo_Annotation::GeneratedCodeInfo_Annotation(::PROTOBUF_NAMESPACE_ID::Arena* arena, + bool is_message_owned) + : ::PROTOBUF_NAMESPACE_ID::Message(arena, is_message_owned) { + SharedCtor(arena, is_message_owned); + // @@protoc_insertion_point(arena_constructor:google.protobuf.GeneratedCodeInfo.Annotation) +} +GeneratedCodeInfo_Annotation::GeneratedCodeInfo_Annotation(const GeneratedCodeInfo_Annotation& from) + : ::PROTOBUF_NAMESPACE_ID::Message() { + GeneratedCodeInfo_Annotation* const _this = this; (void)_this; + new (&_impl_) Impl_{ + decltype(_impl_._has_bits_){from._impl_._has_bits_} + , /*decltype(_impl_._cached_size_)*/{} + , decltype(_impl_.path_){from._impl_.path_} + , /*decltype(_impl_._path_cached_byte_size_)*/{0} + , decltype(_impl_.source_file_){} + , decltype(_impl_.begin_){} + , decltype(_impl_.end_){}}; + + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); + _impl_.source_file_.InitDefault(); + #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + _impl_.source_file_.Set("", GetArenaForAllocation()); + #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (from._internal_has_source_file()) { + _this->_impl_.source_file_.Set(from._internal_source_file(), + _this->GetArenaForAllocation()); + } + ::memcpy(&_impl_.begin_, &from._impl_.begin_, + static_cast<size_t>(reinterpret_cast<char*>(&_impl_.end_) - + reinterpret_cast<char*>(&_impl_.begin_)) + sizeof(_impl_.end_)); + // @@protoc_insertion_point(copy_constructor:google.protobuf.GeneratedCodeInfo.Annotation) +} + +inline void GeneratedCodeInfo_Annotation::SharedCtor( + ::_pb::Arena* arena, bool is_message_owned) { + (void)arena; + (void)is_message_owned; + new (&_impl_) Impl_{ + decltype(_impl_._has_bits_){} + , /*decltype(_impl_._cached_size_)*/{} + , decltype(_impl_.path_){arena} + , /*decltype(_impl_._path_cached_byte_size_)*/{0} + , decltype(_impl_.source_file_){} + , decltype(_impl_.begin_){0} + , decltype(_impl_.end_){0} + }; + _impl_.source_file_.InitDefault(); + #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + _impl_.source_file_.Set("", GetArenaForAllocation()); + #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING +} + +GeneratedCodeInfo_Annotation::~GeneratedCodeInfo_Annotation() { + // @@protoc_insertion_point(destructor:google.protobuf.GeneratedCodeInfo.Annotation) + if (auto *arena = _internal_metadata_.DeleteReturnArena<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>()) { + (void)arena; + return; + } + SharedDtor(); +} + +inline void GeneratedCodeInfo_Annotation::SharedDtor() { + GOOGLE_DCHECK(GetArenaForAllocation() == nullptr); + _impl_.path_.~RepeatedField(); + _impl_.source_file_.Destroy(); +} + +void GeneratedCodeInfo_Annotation::SetCachedSize(int size) const { + _impl_._cached_size_.Set(size); +} + +void GeneratedCodeInfo_Annotation::Clear() { +// @@protoc_insertion_point(message_clear_start:google.protobuf.GeneratedCodeInfo.Annotation) + uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + _impl_.path_.Clear(); + cached_has_bits = _impl_._has_bits_[0]; + if (cached_has_bits & 0x00000001u) { + _impl_.source_file_.ClearNonDefaultToEmpty(); + } + if (cached_has_bits & 0x00000006u) { + ::memset(&_impl_.begin_, 0, static_cast<size_t>( + reinterpret_cast<char*>(&_impl_.end_) - + reinterpret_cast<char*>(&_impl_.begin_)) + sizeof(_impl_.end_)); + } + _impl_._has_bits_.Clear(); + _internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); +} + +const char* GeneratedCodeInfo_Annotation::_InternalParse(const char* ptr, ::_pbi::ParseContext* ctx) { +#define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure + _Internal::HasBits has_bits{}; + while (!ctx->Done(&ptr)) { + uint32_t tag; + ptr = ::_pbi::ReadTag(ptr, &tag); + switch (tag >> 3) { + // repeated int32 path = 1 [packed = true]; + case 1: + if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 10)) { + ptr = ::PROTOBUF_NAMESPACE_ID::internal::PackedInt32Parser(_internal_mutable_path(), ptr, ctx); + CHK_(ptr); + } else if (static_cast<uint8_t>(tag) == 8) { + _internal_add_path(::PROTOBUF_NAMESPACE_ID::internal::ReadVarint32(&ptr)); + CHK_(ptr); + } else + goto handle_unusual; + continue; + // optional string source_file = 2; + case 2: + if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 18)) { + auto str = _internal_mutable_source_file(); + ptr = ::_pbi::InlineGreedyStringParser(str, ptr, ctx); + CHK_(ptr); + #ifndef NDEBUG + ::_pbi::VerifyUTF8(str, "google.protobuf.GeneratedCodeInfo.Annotation.source_file"); + #endif // !NDEBUG + } else + goto handle_unusual; + continue; + // optional int32 begin = 3; + case 3: + if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 24)) { + _Internal::set_has_begin(&has_bits); + _impl_.begin_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint32(&ptr); + CHK_(ptr); + } else + goto handle_unusual; + continue; + // optional int32 end = 4; + case 4: + if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 32)) { + _Internal::set_has_end(&has_bits); + _impl_.end_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint32(&ptr); + CHK_(ptr); + } else + goto handle_unusual; + continue; + default: + goto handle_unusual; + } // switch + handle_unusual: + if ((tag == 0) || ((tag & 7) == 4)) { + CHK_(ptr); + ctx->SetLastTag(tag); + goto message_done; + } + ptr = UnknownFieldParse( + tag, + _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(), + ptr, ctx); + CHK_(ptr != nullptr); + } // while +message_done: + _impl_._has_bits_.Or(has_bits); + return ptr; +failure: + ptr = nullptr; + goto message_done; +#undef CHK_ +} + +uint8_t* GeneratedCodeInfo_Annotation::_InternalSerialize( + uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const { + // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.GeneratedCodeInfo.Annotation) + uint32_t cached_has_bits = 0; + (void) cached_has_bits; + + // repeated int32 path = 1 [packed = true]; + { + int byte_size = _impl_._path_cached_byte_size_.load(std::memory_order_relaxed); + if (byte_size > 0) { + target = stream->WriteInt32Packed( + 1, _internal_path(), byte_size, target); + } + } + + cached_has_bits = _impl_._has_bits_[0]; + // optional string source_file = 2; + if (cached_has_bits & 0x00000001u) { + ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::VerifyUTF8StringNamedField( + this->_internal_source_file().data(), static_cast<int>(this->_internal_source_file().length()), + ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::SERIALIZE, + "google.protobuf.GeneratedCodeInfo.Annotation.source_file"); + target = stream->WriteStringMaybeAliased( + 2, this->_internal_source_file(), target); + } + + // optional int32 begin = 3; + if (cached_has_bits & 0x00000002u) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteInt32ToArray(3, this->_internal_begin(), target); + } + + // optional int32 end = 4; + if (cached_has_bits & 0x00000004u) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteInt32ToArray(4, this->_internal_end(), target); + } + + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + target = ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( + _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.GeneratedCodeInfo.Annotation) + return target; +} + +size_t GeneratedCodeInfo_Annotation::ByteSizeLong() const { +// @@protoc_insertion_point(message_byte_size_start:google.protobuf.GeneratedCodeInfo.Annotation) + size_t total_size = 0; + + uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + // repeated int32 path = 1 [packed = true]; + { + size_t data_size = ::_pbi::WireFormatLite:: + Int32Size(this->_impl_.path_); + if (data_size > 0) { + total_size += 1 + + ::_pbi::WireFormatLite::Int32Size(static_cast<int32_t>(data_size)); + } + int cached_size = ::_pbi::ToCachedSize(data_size); + _impl_._path_cached_byte_size_.store(cached_size, + std::memory_order_relaxed); + total_size += data_size; + } + + cached_has_bits = _impl_._has_bits_[0]; + if (cached_has_bits & 0x00000007u) { + // optional string source_file = 2; + if (cached_has_bits & 0x00000001u) { + total_size += 1 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize( + this->_internal_source_file()); + } + + // optional int32 begin = 3; + if (cached_has_bits & 0x00000002u) { + total_size += ::_pbi::WireFormatLite::Int32SizePlusOne(this->_internal_begin()); + } + + // optional int32 end = 4; + if (cached_has_bits & 0x00000004u) { + total_size += ::_pbi::WireFormatLite::Int32SizePlusOne(this->_internal_end()); + } + + } + return MaybeComputeUnknownFieldsSize(total_size, &_impl_._cached_size_); +} + +const ::PROTOBUF_NAMESPACE_ID::Message::ClassData GeneratedCodeInfo_Annotation::_class_data_ = { + ::PROTOBUF_NAMESPACE_ID::Message::CopyWithSourceCheck, + GeneratedCodeInfo_Annotation::MergeImpl +}; +const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*GeneratedCodeInfo_Annotation::GetClassData() const { return &_class_data_; } + + +void GeneratedCodeInfo_Annotation::MergeImpl(::PROTOBUF_NAMESPACE_ID::Message& to_msg, const ::PROTOBUF_NAMESPACE_ID::Message& from_msg) { + auto* const _this = static_cast<GeneratedCodeInfo_Annotation*>(&to_msg); + auto& from = static_cast<const GeneratedCodeInfo_Annotation&>(from_msg); + // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.GeneratedCodeInfo.Annotation) + GOOGLE_DCHECK_NE(&from, _this); + uint32_t cached_has_bits = 0; + (void) cached_has_bits; + + _this->_impl_.path_.MergeFrom(from._impl_.path_); + cached_has_bits = from._impl_._has_bits_[0]; + if (cached_has_bits & 0x00000007u) { + if (cached_has_bits & 0x00000001u) { + _this->_internal_set_source_file(from._internal_source_file()); + } + if (cached_has_bits & 0x00000002u) { + _this->_impl_.begin_ = from._impl_.begin_; + } + if (cached_has_bits & 0x00000004u) { + _this->_impl_.end_ = from._impl_.end_; + } + _this->_impl_._has_bits_[0] |= cached_has_bits; + } + _this->_internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); +} + +void GeneratedCodeInfo_Annotation::CopyFrom(const GeneratedCodeInfo_Annotation& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.GeneratedCodeInfo.Annotation) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool GeneratedCodeInfo_Annotation::IsInitialized() const { + return true; +} + +void GeneratedCodeInfo_Annotation::InternalSwap(GeneratedCodeInfo_Annotation* other) { + using std::swap; + auto* lhs_arena = GetArenaForAllocation(); + auto* rhs_arena = other->GetArenaForAllocation(); + _internal_metadata_.InternalSwap(&other->_internal_metadata_); + swap(_impl_._has_bits_[0], other->_impl_._has_bits_[0]); + _impl_.path_.InternalSwap(&other->_impl_.path_); + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::InternalSwap( + &_impl_.source_file_, lhs_arena, + &other->_impl_.source_file_, rhs_arena + ); + ::PROTOBUF_NAMESPACE_ID::internal::memswap< + PROTOBUF_FIELD_OFFSET(GeneratedCodeInfo_Annotation, _impl_.end_) + + sizeof(GeneratedCodeInfo_Annotation::_impl_.end_) + - PROTOBUF_FIELD_OFFSET(GeneratedCodeInfo_Annotation, _impl_.begin_)>( + reinterpret_cast<char*>(&_impl_.begin_), + reinterpret_cast<char*>(&other->_impl_.begin_)); +} + +::PROTOBUF_NAMESPACE_ID::Metadata GeneratedCodeInfo_Annotation::GetMetadata() const { + return ::_pbi::AssignDescriptors( + &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_getter, &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_once, + file_level_metadata_google_2fprotobuf_2fdescriptor_2eproto[25]); +} + +// =================================================================== + +class GeneratedCodeInfo::_Internal { + public: +}; + +GeneratedCodeInfo::GeneratedCodeInfo(::PROTOBUF_NAMESPACE_ID::Arena* arena, + bool is_message_owned) + : ::PROTOBUF_NAMESPACE_ID::Message(arena, is_message_owned) { + SharedCtor(arena, is_message_owned); + // @@protoc_insertion_point(arena_constructor:google.protobuf.GeneratedCodeInfo) +} +GeneratedCodeInfo::GeneratedCodeInfo(const GeneratedCodeInfo& from) + : ::PROTOBUF_NAMESPACE_ID::Message() { + GeneratedCodeInfo* const _this = this; (void)_this; + new (&_impl_) Impl_{ + decltype(_impl_.annotation_){from._impl_.annotation_} + , /*decltype(_impl_._cached_size_)*/{}}; + + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); + // @@protoc_insertion_point(copy_constructor:google.protobuf.GeneratedCodeInfo) +} + +inline void GeneratedCodeInfo::SharedCtor( + ::_pb::Arena* arena, bool is_message_owned) { + (void)arena; + (void)is_message_owned; + new (&_impl_) Impl_{ + decltype(_impl_.annotation_){arena} + , /*decltype(_impl_._cached_size_)*/{} + }; +} + +GeneratedCodeInfo::~GeneratedCodeInfo() { + // @@protoc_insertion_point(destructor:google.protobuf.GeneratedCodeInfo) + if (auto *arena = _internal_metadata_.DeleteReturnArena<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>()) { + (void)arena; + return; + } + SharedDtor(); +} + +inline void GeneratedCodeInfo::SharedDtor() { + GOOGLE_DCHECK(GetArenaForAllocation() == nullptr); + _impl_.annotation_.~RepeatedPtrField(); +} + +void GeneratedCodeInfo::SetCachedSize(int size) const { + _impl_._cached_size_.Set(size); +} + +void GeneratedCodeInfo::Clear() { +// @@protoc_insertion_point(message_clear_start:google.protobuf.GeneratedCodeInfo) + uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + _impl_.annotation_.Clear(); + _internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); +} + +const char* GeneratedCodeInfo::_InternalParse(const char* ptr, ::_pbi::ParseContext* ctx) { +#define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure + while (!ctx->Done(&ptr)) { + uint32_t tag; + ptr = ::_pbi::ReadTag(ptr, &tag); + switch (tag >> 3) { + // repeated .google.protobuf.GeneratedCodeInfo.Annotation annotation = 1; + case 1: + if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 10)) { + ptr -= 1; + do { + ptr += 1; + ptr = ctx->ParseMessage(_internal_add_annotation(), ptr); + CHK_(ptr); + if (!ctx->DataAvailable(ptr)) break; + } while (::PROTOBUF_NAMESPACE_ID::internal::ExpectTag<10>(ptr)); + } else + goto handle_unusual; + continue; + default: + goto handle_unusual; + } // switch + handle_unusual: + if ((tag == 0) || ((tag & 7) == 4)) { + CHK_(ptr); + ctx->SetLastTag(tag); + goto message_done; + } + ptr = UnknownFieldParse( + tag, + _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(), + ptr, ctx); + CHK_(ptr != nullptr); + } // while +message_done: + return ptr; +failure: + ptr = nullptr; + goto message_done; +#undef CHK_ +} + +uint8_t* GeneratedCodeInfo::_InternalSerialize( + uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const { + // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.GeneratedCodeInfo) + uint32_t cached_has_bits = 0; + (void) cached_has_bits; + + // repeated .google.protobuf.GeneratedCodeInfo.Annotation annotation = 1; + for (unsigned i = 0, + n = static_cast<unsigned>(this->_internal_annotation_size()); i < n; i++) { + const auto& repfield = this->_internal_annotation(i); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite:: + InternalWriteMessage(1, repfield, repfield.GetCachedSize(), target, stream); + } + + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + target = ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( + _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.GeneratedCodeInfo) + return target; +} + +size_t GeneratedCodeInfo::ByteSizeLong() const { +// @@protoc_insertion_point(message_byte_size_start:google.protobuf.GeneratedCodeInfo) + size_t total_size = 0; + + uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + // repeated .google.protobuf.GeneratedCodeInfo.Annotation annotation = 1; + total_size += 1UL * this->_internal_annotation_size(); + for (const auto& msg : this->_impl_.annotation_) { + total_size += + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::MessageSize(msg); + } + + return MaybeComputeUnknownFieldsSize(total_size, &_impl_._cached_size_); +} + +const ::PROTOBUF_NAMESPACE_ID::Message::ClassData GeneratedCodeInfo::_class_data_ = { + ::PROTOBUF_NAMESPACE_ID::Message::CopyWithSourceCheck, + GeneratedCodeInfo::MergeImpl +}; +const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*GeneratedCodeInfo::GetClassData() const { return &_class_data_; } + + +void GeneratedCodeInfo::MergeImpl(::PROTOBUF_NAMESPACE_ID::Message& to_msg, const ::PROTOBUF_NAMESPACE_ID::Message& from_msg) { + auto* const _this = static_cast<GeneratedCodeInfo*>(&to_msg); + auto& from = static_cast<const GeneratedCodeInfo&>(from_msg); + // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.GeneratedCodeInfo) + GOOGLE_DCHECK_NE(&from, _this); + uint32_t cached_has_bits = 0; + (void) cached_has_bits; + + _this->_impl_.annotation_.MergeFrom(from._impl_.annotation_); + _this->_internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); +} + +void GeneratedCodeInfo::CopyFrom(const GeneratedCodeInfo& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.GeneratedCodeInfo) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool GeneratedCodeInfo::IsInitialized() const { + return true; +} + +void GeneratedCodeInfo::InternalSwap(GeneratedCodeInfo* other) { + using std::swap; + _internal_metadata_.InternalSwap(&other->_internal_metadata_); + _impl_.annotation_.InternalSwap(&other->_impl_.annotation_); +} + +::PROTOBUF_NAMESPACE_ID::Metadata GeneratedCodeInfo::GetMetadata() const { + return ::_pbi::AssignDescriptors( + &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_getter, &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_once, + file_level_metadata_google_2fprotobuf_2fdescriptor_2eproto[26]); +} + +// @@protoc_insertion_point(namespace_scope) +PROTOBUF_NAMESPACE_CLOSE +PROTOBUF_NAMESPACE_OPEN +template<> PROTOBUF_NOINLINE ::PROTOBUF_NAMESPACE_ID::FileDescriptorSet* +Arena::CreateMaybeMessage< ::PROTOBUF_NAMESPACE_ID::FileDescriptorSet >(Arena* arena) { + return Arena::CreateMessageInternal< ::PROTOBUF_NAMESPACE_ID::FileDescriptorSet >(arena); +} +template<> PROTOBUF_NOINLINE ::PROTOBUF_NAMESPACE_ID::FileDescriptorProto* +Arena::CreateMaybeMessage< ::PROTOBUF_NAMESPACE_ID::FileDescriptorProto >(Arena* arena) { + return Arena::CreateMessageInternal< ::PROTOBUF_NAMESPACE_ID::FileDescriptorProto >(arena); +} +template<> PROTOBUF_NOINLINE ::PROTOBUF_NAMESPACE_ID::DescriptorProto_ExtensionRange* +Arena::CreateMaybeMessage< ::PROTOBUF_NAMESPACE_ID::DescriptorProto_ExtensionRange >(Arena* arena) { + return Arena::CreateMessageInternal< ::PROTOBUF_NAMESPACE_ID::DescriptorProto_ExtensionRange >(arena); +} +template<> PROTOBUF_NOINLINE ::PROTOBUF_NAMESPACE_ID::DescriptorProto_ReservedRange* +Arena::CreateMaybeMessage< ::PROTOBUF_NAMESPACE_ID::DescriptorProto_ReservedRange >(Arena* arena) { + return Arena::CreateMessageInternal< ::PROTOBUF_NAMESPACE_ID::DescriptorProto_ReservedRange >(arena); +} +template<> PROTOBUF_NOINLINE ::PROTOBUF_NAMESPACE_ID::DescriptorProto* +Arena::CreateMaybeMessage< ::PROTOBUF_NAMESPACE_ID::DescriptorProto >(Arena* arena) { + return Arena::CreateMessageInternal< ::PROTOBUF_NAMESPACE_ID::DescriptorProto >(arena); +} +template<> PROTOBUF_NOINLINE ::PROTOBUF_NAMESPACE_ID::ExtensionRangeOptions* +Arena::CreateMaybeMessage< ::PROTOBUF_NAMESPACE_ID::ExtensionRangeOptions >(Arena* arena) { + return Arena::CreateMessageInternal< ::PROTOBUF_NAMESPACE_ID::ExtensionRangeOptions >(arena); +} +template<> PROTOBUF_NOINLINE ::PROTOBUF_NAMESPACE_ID::FieldDescriptorProto* +Arena::CreateMaybeMessage< ::PROTOBUF_NAMESPACE_ID::FieldDescriptorProto >(Arena* arena) { + return Arena::CreateMessageInternal< ::PROTOBUF_NAMESPACE_ID::FieldDescriptorProto >(arena); +} +template<> PROTOBUF_NOINLINE ::PROTOBUF_NAMESPACE_ID::OneofDescriptorProto* +Arena::CreateMaybeMessage< ::PROTOBUF_NAMESPACE_ID::OneofDescriptorProto >(Arena* arena) { + return Arena::CreateMessageInternal< ::PROTOBUF_NAMESPACE_ID::OneofDescriptorProto >(arena); +} +template<> PROTOBUF_NOINLINE ::PROTOBUF_NAMESPACE_ID::EnumDescriptorProto_EnumReservedRange* +Arena::CreateMaybeMessage< ::PROTOBUF_NAMESPACE_ID::EnumDescriptorProto_EnumReservedRange >(Arena* arena) { + return Arena::CreateMessageInternal< ::PROTOBUF_NAMESPACE_ID::EnumDescriptorProto_EnumReservedRange >(arena); +} +template<> PROTOBUF_NOINLINE ::PROTOBUF_NAMESPACE_ID::EnumDescriptorProto* +Arena::CreateMaybeMessage< ::PROTOBUF_NAMESPACE_ID::EnumDescriptorProto >(Arena* arena) { + return Arena::CreateMessageInternal< ::PROTOBUF_NAMESPACE_ID::EnumDescriptorProto >(arena); +} +template<> PROTOBUF_NOINLINE ::PROTOBUF_NAMESPACE_ID::EnumValueDescriptorProto* +Arena::CreateMaybeMessage< ::PROTOBUF_NAMESPACE_ID::EnumValueDescriptorProto >(Arena* arena) { + return Arena::CreateMessageInternal< ::PROTOBUF_NAMESPACE_ID::EnumValueDescriptorProto >(arena); +} +template<> PROTOBUF_NOINLINE ::PROTOBUF_NAMESPACE_ID::ServiceDescriptorProto* +Arena::CreateMaybeMessage< ::PROTOBUF_NAMESPACE_ID::ServiceDescriptorProto >(Arena* arena) { + return Arena::CreateMessageInternal< ::PROTOBUF_NAMESPACE_ID::ServiceDescriptorProto >(arena); +} +template<> PROTOBUF_NOINLINE ::PROTOBUF_NAMESPACE_ID::MethodDescriptorProto* +Arena::CreateMaybeMessage< ::PROTOBUF_NAMESPACE_ID::MethodDescriptorProto >(Arena* arena) { + return Arena::CreateMessageInternal< ::PROTOBUF_NAMESPACE_ID::MethodDescriptorProto >(arena); +} +template<> PROTOBUF_NOINLINE ::PROTOBUF_NAMESPACE_ID::FileOptions* +Arena::CreateMaybeMessage< ::PROTOBUF_NAMESPACE_ID::FileOptions >(Arena* arena) { + return Arena::CreateMessageInternal< ::PROTOBUF_NAMESPACE_ID::FileOptions >(arena); +} +template<> PROTOBUF_NOINLINE ::PROTOBUF_NAMESPACE_ID::MessageOptions* +Arena::CreateMaybeMessage< ::PROTOBUF_NAMESPACE_ID::MessageOptions >(Arena* arena) { + return Arena::CreateMessageInternal< ::PROTOBUF_NAMESPACE_ID::MessageOptions >(arena); +} +template<> PROTOBUF_NOINLINE ::PROTOBUF_NAMESPACE_ID::FieldOptions* +Arena::CreateMaybeMessage< ::PROTOBUF_NAMESPACE_ID::FieldOptions >(Arena* arena) { + return Arena::CreateMessageInternal< ::PROTOBUF_NAMESPACE_ID::FieldOptions >(arena); +} +template<> PROTOBUF_NOINLINE ::PROTOBUF_NAMESPACE_ID::OneofOptions* +Arena::CreateMaybeMessage< ::PROTOBUF_NAMESPACE_ID::OneofOptions >(Arena* arena) { + return Arena::CreateMessageInternal< ::PROTOBUF_NAMESPACE_ID::OneofOptions >(arena); +} +template<> PROTOBUF_NOINLINE ::PROTOBUF_NAMESPACE_ID::EnumOptions* +Arena::CreateMaybeMessage< ::PROTOBUF_NAMESPACE_ID::EnumOptions >(Arena* arena) { + return Arena::CreateMessageInternal< ::PROTOBUF_NAMESPACE_ID::EnumOptions >(arena); +} +template<> PROTOBUF_NOINLINE ::PROTOBUF_NAMESPACE_ID::EnumValueOptions* +Arena::CreateMaybeMessage< ::PROTOBUF_NAMESPACE_ID::EnumValueOptions >(Arena* arena) { + return Arena::CreateMessageInternal< ::PROTOBUF_NAMESPACE_ID::EnumValueOptions >(arena); +} +template<> PROTOBUF_NOINLINE ::PROTOBUF_NAMESPACE_ID::ServiceOptions* +Arena::CreateMaybeMessage< ::PROTOBUF_NAMESPACE_ID::ServiceOptions >(Arena* arena) { + return Arena::CreateMessageInternal< ::PROTOBUF_NAMESPACE_ID::ServiceOptions >(arena); +} +template<> PROTOBUF_NOINLINE ::PROTOBUF_NAMESPACE_ID::MethodOptions* +Arena::CreateMaybeMessage< ::PROTOBUF_NAMESPACE_ID::MethodOptions >(Arena* arena) { + return Arena::CreateMessageInternal< ::PROTOBUF_NAMESPACE_ID::MethodOptions >(arena); +} +template<> PROTOBUF_NOINLINE ::PROTOBUF_NAMESPACE_ID::UninterpretedOption_NamePart* +Arena::CreateMaybeMessage< ::PROTOBUF_NAMESPACE_ID::UninterpretedOption_NamePart >(Arena* arena) { + return Arena::CreateMessageInternal< ::PROTOBUF_NAMESPACE_ID::UninterpretedOption_NamePart >(arena); +} +template<> PROTOBUF_NOINLINE ::PROTOBUF_NAMESPACE_ID::UninterpretedOption* +Arena::CreateMaybeMessage< ::PROTOBUF_NAMESPACE_ID::UninterpretedOption >(Arena* arena) { + return Arena::CreateMessageInternal< ::PROTOBUF_NAMESPACE_ID::UninterpretedOption >(arena); +} +template<> PROTOBUF_NOINLINE ::PROTOBUF_NAMESPACE_ID::SourceCodeInfo_Location* +Arena::CreateMaybeMessage< ::PROTOBUF_NAMESPACE_ID::SourceCodeInfo_Location >(Arena* arena) { + return Arena::CreateMessageInternal< ::PROTOBUF_NAMESPACE_ID::SourceCodeInfo_Location >(arena); +} +template<> PROTOBUF_NOINLINE ::PROTOBUF_NAMESPACE_ID::SourceCodeInfo* +Arena::CreateMaybeMessage< ::PROTOBUF_NAMESPACE_ID::SourceCodeInfo >(Arena* arena) { + return Arena::CreateMessageInternal< ::PROTOBUF_NAMESPACE_ID::SourceCodeInfo >(arena); +} +template<> PROTOBUF_NOINLINE ::PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo_Annotation* +Arena::CreateMaybeMessage< ::PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo_Annotation >(Arena* arena) { + return Arena::CreateMessageInternal< ::PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo_Annotation >(arena); +} +template<> PROTOBUF_NOINLINE ::PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo* +Arena::CreateMaybeMessage< ::PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo >(Arena* arena) { + return Arena::CreateMessageInternal< ::PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo >(arena); +} +PROTOBUF_NAMESPACE_CLOSE + +// @@protoc_insertion_point(global_scope) +#include <google/protobuf/port_undef.inc> diff --git a/toolkit/components/protobuf/src/google/protobuf/descriptor.pb.h b/toolkit/components/protobuf/src/google/protobuf/descriptor.pb.h new file mode 100644 index 0000000000..2d9c790f57 --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/descriptor.pb.h @@ -0,0 +1,14821 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: google/protobuf/descriptor.proto + +#ifndef GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2fdescriptor_2eproto +#define GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2fdescriptor_2eproto + +#include <limits> +#include <string> + +#include <google/protobuf/port_def.inc> +#if PROTOBUF_VERSION < 3021000 +#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 3021006 < 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. +#endif + +#include <google/protobuf/port_undef.inc> +#include <google/protobuf/io/coded_stream.h> +#include <google/protobuf/arena.h> +#include <google/protobuf/arenastring.h> +#include <google/protobuf/generated_message_util.h> +#include <google/protobuf/metadata_lite.h> +#include <google/protobuf/generated_message_reflection.h> +#include <google/protobuf/message.h> +#include <google/protobuf/repeated_field.h> // IWYU pragma: export +#include <google/protobuf/extension_set.h> // IWYU pragma: export +#include <google/protobuf/generated_enum_reflection.h> +#include <google/protobuf/unknown_field_set.h> +// @@protoc_insertion_point(includes) +#include <google/protobuf/port_def.inc> +#define PROTOBUF_INTERNAL_EXPORT_google_2fprotobuf_2fdescriptor_2eproto PROTOBUF_EXPORT +PROTOBUF_NAMESPACE_OPEN +namespace internal { +class AnyMetadata; +} // namespace internal +PROTOBUF_NAMESPACE_CLOSE + +// Internal implementation detail -- do not use these members. +struct PROTOBUF_EXPORT TableStruct_google_2fprotobuf_2fdescriptor_2eproto { + static const uint32_t offsets[]; +}; +PROTOBUF_EXPORT extern const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable descriptor_table_google_2fprotobuf_2fdescriptor_2eproto; +PROTOBUF_NAMESPACE_OPEN +class DescriptorProto; +struct DescriptorProtoDefaultTypeInternal; +PROTOBUF_EXPORT extern DescriptorProtoDefaultTypeInternal _DescriptorProto_default_instance_; +class DescriptorProto_ExtensionRange; +struct DescriptorProto_ExtensionRangeDefaultTypeInternal; +PROTOBUF_EXPORT extern DescriptorProto_ExtensionRangeDefaultTypeInternal _DescriptorProto_ExtensionRange_default_instance_; +class DescriptorProto_ReservedRange; +struct DescriptorProto_ReservedRangeDefaultTypeInternal; +PROTOBUF_EXPORT extern DescriptorProto_ReservedRangeDefaultTypeInternal _DescriptorProto_ReservedRange_default_instance_; +class EnumDescriptorProto; +struct EnumDescriptorProtoDefaultTypeInternal; +PROTOBUF_EXPORT extern EnumDescriptorProtoDefaultTypeInternal _EnumDescriptorProto_default_instance_; +class EnumDescriptorProto_EnumReservedRange; +struct EnumDescriptorProto_EnumReservedRangeDefaultTypeInternal; +PROTOBUF_EXPORT extern EnumDescriptorProto_EnumReservedRangeDefaultTypeInternal _EnumDescriptorProto_EnumReservedRange_default_instance_; +class EnumOptions; +struct EnumOptionsDefaultTypeInternal; +PROTOBUF_EXPORT extern EnumOptionsDefaultTypeInternal _EnumOptions_default_instance_; +class EnumValueDescriptorProto; +struct EnumValueDescriptorProtoDefaultTypeInternal; +PROTOBUF_EXPORT extern EnumValueDescriptorProtoDefaultTypeInternal _EnumValueDescriptorProto_default_instance_; +class EnumValueOptions; +struct EnumValueOptionsDefaultTypeInternal; +PROTOBUF_EXPORT extern EnumValueOptionsDefaultTypeInternal _EnumValueOptions_default_instance_; +class ExtensionRangeOptions; +struct ExtensionRangeOptionsDefaultTypeInternal; +PROTOBUF_EXPORT extern ExtensionRangeOptionsDefaultTypeInternal _ExtensionRangeOptions_default_instance_; +class FieldDescriptorProto; +struct FieldDescriptorProtoDefaultTypeInternal; +PROTOBUF_EXPORT extern FieldDescriptorProtoDefaultTypeInternal _FieldDescriptorProto_default_instance_; +class FieldOptions; +struct FieldOptionsDefaultTypeInternal; +PROTOBUF_EXPORT extern FieldOptionsDefaultTypeInternal _FieldOptions_default_instance_; +class FileDescriptorProto; +struct FileDescriptorProtoDefaultTypeInternal; +PROTOBUF_EXPORT extern FileDescriptorProtoDefaultTypeInternal _FileDescriptorProto_default_instance_; +class FileDescriptorSet; +struct FileDescriptorSetDefaultTypeInternal; +PROTOBUF_EXPORT extern FileDescriptorSetDefaultTypeInternal _FileDescriptorSet_default_instance_; +class FileOptions; +struct FileOptionsDefaultTypeInternal; +PROTOBUF_EXPORT extern FileOptionsDefaultTypeInternal _FileOptions_default_instance_; +class GeneratedCodeInfo; +struct GeneratedCodeInfoDefaultTypeInternal; +PROTOBUF_EXPORT extern GeneratedCodeInfoDefaultTypeInternal _GeneratedCodeInfo_default_instance_; +class GeneratedCodeInfo_Annotation; +struct GeneratedCodeInfo_AnnotationDefaultTypeInternal; +PROTOBUF_EXPORT extern GeneratedCodeInfo_AnnotationDefaultTypeInternal _GeneratedCodeInfo_Annotation_default_instance_; +class MessageOptions; +struct MessageOptionsDefaultTypeInternal; +PROTOBUF_EXPORT extern MessageOptionsDefaultTypeInternal _MessageOptions_default_instance_; +class MethodDescriptorProto; +struct MethodDescriptorProtoDefaultTypeInternal; +PROTOBUF_EXPORT extern MethodDescriptorProtoDefaultTypeInternal _MethodDescriptorProto_default_instance_; +class MethodOptions; +struct MethodOptionsDefaultTypeInternal; +PROTOBUF_EXPORT extern MethodOptionsDefaultTypeInternal _MethodOptions_default_instance_; +class OneofDescriptorProto; +struct OneofDescriptorProtoDefaultTypeInternal; +PROTOBUF_EXPORT extern OneofDescriptorProtoDefaultTypeInternal _OneofDescriptorProto_default_instance_; +class OneofOptions; +struct OneofOptionsDefaultTypeInternal; +PROTOBUF_EXPORT extern OneofOptionsDefaultTypeInternal _OneofOptions_default_instance_; +class ServiceDescriptorProto; +struct ServiceDescriptorProtoDefaultTypeInternal; +PROTOBUF_EXPORT extern ServiceDescriptorProtoDefaultTypeInternal _ServiceDescriptorProto_default_instance_; +class ServiceOptions; +struct ServiceOptionsDefaultTypeInternal; +PROTOBUF_EXPORT extern ServiceOptionsDefaultTypeInternal _ServiceOptions_default_instance_; +class SourceCodeInfo; +struct SourceCodeInfoDefaultTypeInternal; +PROTOBUF_EXPORT extern SourceCodeInfoDefaultTypeInternal _SourceCodeInfo_default_instance_; +class SourceCodeInfo_Location; +struct SourceCodeInfo_LocationDefaultTypeInternal; +PROTOBUF_EXPORT extern SourceCodeInfo_LocationDefaultTypeInternal _SourceCodeInfo_Location_default_instance_; +class UninterpretedOption; +struct UninterpretedOptionDefaultTypeInternal; +PROTOBUF_EXPORT extern UninterpretedOptionDefaultTypeInternal _UninterpretedOption_default_instance_; +class UninterpretedOption_NamePart; +struct UninterpretedOption_NamePartDefaultTypeInternal; +PROTOBUF_EXPORT extern UninterpretedOption_NamePartDefaultTypeInternal _UninterpretedOption_NamePart_default_instance_; +PROTOBUF_NAMESPACE_CLOSE +PROTOBUF_NAMESPACE_OPEN +template<> PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::DescriptorProto* Arena::CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::DescriptorProto>(Arena*); +template<> PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::DescriptorProto_ExtensionRange* Arena::CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::DescriptorProto_ExtensionRange>(Arena*); +template<> PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::DescriptorProto_ReservedRange* Arena::CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::DescriptorProto_ReservedRange>(Arena*); +template<> PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::EnumDescriptorProto* Arena::CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::EnumDescriptorProto>(Arena*); +template<> PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::EnumDescriptorProto_EnumReservedRange* Arena::CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::EnumDescriptorProto_EnumReservedRange>(Arena*); +template<> PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::EnumOptions* Arena::CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::EnumOptions>(Arena*); +template<> PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::EnumValueDescriptorProto* Arena::CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::EnumValueDescriptorProto>(Arena*); +template<> PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::EnumValueOptions* Arena::CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::EnumValueOptions>(Arena*); +template<> PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::ExtensionRangeOptions* Arena::CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::ExtensionRangeOptions>(Arena*); +template<> PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::FieldDescriptorProto* Arena::CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::FieldDescriptorProto>(Arena*); +template<> PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::FieldOptions* Arena::CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::FieldOptions>(Arena*); +template<> PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::FileDescriptorProto* Arena::CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::FileDescriptorProto>(Arena*); +template<> PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::FileDescriptorSet* Arena::CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::FileDescriptorSet>(Arena*); +template<> PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::FileOptions* Arena::CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::FileOptions>(Arena*); +template<> PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo* Arena::CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo>(Arena*); +template<> PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo_Annotation* Arena::CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo_Annotation>(Arena*); +template<> PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::MessageOptions* Arena::CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::MessageOptions>(Arena*); +template<> PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::MethodDescriptorProto* Arena::CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::MethodDescriptorProto>(Arena*); +template<> PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::MethodOptions* Arena::CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::MethodOptions>(Arena*); +template<> PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::OneofDescriptorProto* Arena::CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::OneofDescriptorProto>(Arena*); +template<> PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::OneofOptions* Arena::CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::OneofOptions>(Arena*); +template<> PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::ServiceDescriptorProto* Arena::CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::ServiceDescriptorProto>(Arena*); +template<> PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::ServiceOptions* Arena::CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::ServiceOptions>(Arena*); +template<> PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::SourceCodeInfo* Arena::CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::SourceCodeInfo>(Arena*); +template<> PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::SourceCodeInfo_Location* Arena::CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::SourceCodeInfo_Location>(Arena*); +template<> PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::UninterpretedOption* Arena::CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::UninterpretedOption>(Arena*); +template<> PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::UninterpretedOption_NamePart* Arena::CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::UninterpretedOption_NamePart>(Arena*); +PROTOBUF_NAMESPACE_CLOSE +PROTOBUF_NAMESPACE_OPEN + +enum FieldDescriptorProto_Type : int { + FieldDescriptorProto_Type_TYPE_DOUBLE = 1, + FieldDescriptorProto_Type_TYPE_FLOAT = 2, + FieldDescriptorProto_Type_TYPE_INT64 = 3, + FieldDescriptorProto_Type_TYPE_UINT64 = 4, + FieldDescriptorProto_Type_TYPE_INT32 = 5, + FieldDescriptorProto_Type_TYPE_FIXED64 = 6, + FieldDescriptorProto_Type_TYPE_FIXED32 = 7, + FieldDescriptorProto_Type_TYPE_BOOL = 8, + FieldDescriptorProto_Type_TYPE_STRING = 9, + FieldDescriptorProto_Type_TYPE_GROUP = 10, + FieldDescriptorProto_Type_TYPE_MESSAGE = 11, + FieldDescriptorProto_Type_TYPE_BYTES = 12, + FieldDescriptorProto_Type_TYPE_UINT32 = 13, + FieldDescriptorProto_Type_TYPE_ENUM = 14, + FieldDescriptorProto_Type_TYPE_SFIXED32 = 15, + FieldDescriptorProto_Type_TYPE_SFIXED64 = 16, + FieldDescriptorProto_Type_TYPE_SINT32 = 17, + FieldDescriptorProto_Type_TYPE_SINT64 = 18 +}; +PROTOBUF_EXPORT bool FieldDescriptorProto_Type_IsValid(int value); +constexpr FieldDescriptorProto_Type FieldDescriptorProto_Type_Type_MIN = FieldDescriptorProto_Type_TYPE_DOUBLE; +constexpr FieldDescriptorProto_Type FieldDescriptorProto_Type_Type_MAX = FieldDescriptorProto_Type_TYPE_SINT64; +constexpr int FieldDescriptorProto_Type_Type_ARRAYSIZE = FieldDescriptorProto_Type_Type_MAX + 1; + +PROTOBUF_EXPORT const ::PROTOBUF_NAMESPACE_ID::EnumDescriptor* FieldDescriptorProto_Type_descriptor(); +template<typename T> +inline const std::string& FieldDescriptorProto_Type_Name(T enum_t_value) { + static_assert(::std::is_same<T, FieldDescriptorProto_Type>::value || + ::std::is_integral<T>::value, + "Incorrect type passed to function FieldDescriptorProto_Type_Name."); + return ::PROTOBUF_NAMESPACE_ID::internal::NameOfEnum( + FieldDescriptorProto_Type_descriptor(), enum_t_value); +} +inline bool FieldDescriptorProto_Type_Parse( + ::PROTOBUF_NAMESPACE_ID::ConstStringParam name, FieldDescriptorProto_Type* value) { + return ::PROTOBUF_NAMESPACE_ID::internal::ParseNamedEnum<FieldDescriptorProto_Type>( + FieldDescriptorProto_Type_descriptor(), name, value); +} +enum FieldDescriptorProto_Label : int { + FieldDescriptorProto_Label_LABEL_OPTIONAL = 1, + FieldDescriptorProto_Label_LABEL_REQUIRED = 2, + FieldDescriptorProto_Label_LABEL_REPEATED = 3 +}; +PROTOBUF_EXPORT bool FieldDescriptorProto_Label_IsValid(int value); +constexpr FieldDescriptorProto_Label FieldDescriptorProto_Label_Label_MIN = FieldDescriptorProto_Label_LABEL_OPTIONAL; +constexpr FieldDescriptorProto_Label FieldDescriptorProto_Label_Label_MAX = FieldDescriptorProto_Label_LABEL_REPEATED; +constexpr int FieldDescriptorProto_Label_Label_ARRAYSIZE = FieldDescriptorProto_Label_Label_MAX + 1; + +PROTOBUF_EXPORT const ::PROTOBUF_NAMESPACE_ID::EnumDescriptor* FieldDescriptorProto_Label_descriptor(); +template<typename T> +inline const std::string& FieldDescriptorProto_Label_Name(T enum_t_value) { + static_assert(::std::is_same<T, FieldDescriptorProto_Label>::value || + ::std::is_integral<T>::value, + "Incorrect type passed to function FieldDescriptorProto_Label_Name."); + return ::PROTOBUF_NAMESPACE_ID::internal::NameOfEnum( + FieldDescriptorProto_Label_descriptor(), enum_t_value); +} +inline bool FieldDescriptorProto_Label_Parse( + ::PROTOBUF_NAMESPACE_ID::ConstStringParam name, FieldDescriptorProto_Label* value) { + return ::PROTOBUF_NAMESPACE_ID::internal::ParseNamedEnum<FieldDescriptorProto_Label>( + FieldDescriptorProto_Label_descriptor(), name, value); +} +enum FileOptions_OptimizeMode : int { + FileOptions_OptimizeMode_SPEED = 1, + FileOptions_OptimizeMode_CODE_SIZE = 2, + FileOptions_OptimizeMode_LITE_RUNTIME = 3 +}; +PROTOBUF_EXPORT bool FileOptions_OptimizeMode_IsValid(int value); +constexpr FileOptions_OptimizeMode FileOptions_OptimizeMode_OptimizeMode_MIN = FileOptions_OptimizeMode_SPEED; +constexpr FileOptions_OptimizeMode FileOptions_OptimizeMode_OptimizeMode_MAX = FileOptions_OptimizeMode_LITE_RUNTIME; +constexpr int FileOptions_OptimizeMode_OptimizeMode_ARRAYSIZE = FileOptions_OptimizeMode_OptimizeMode_MAX + 1; + +PROTOBUF_EXPORT const ::PROTOBUF_NAMESPACE_ID::EnumDescriptor* FileOptions_OptimizeMode_descriptor(); +template<typename T> +inline const std::string& FileOptions_OptimizeMode_Name(T enum_t_value) { + static_assert(::std::is_same<T, FileOptions_OptimizeMode>::value || + ::std::is_integral<T>::value, + "Incorrect type passed to function FileOptions_OptimizeMode_Name."); + return ::PROTOBUF_NAMESPACE_ID::internal::NameOfEnum( + FileOptions_OptimizeMode_descriptor(), enum_t_value); +} +inline bool FileOptions_OptimizeMode_Parse( + ::PROTOBUF_NAMESPACE_ID::ConstStringParam name, FileOptions_OptimizeMode* value) { + return ::PROTOBUF_NAMESPACE_ID::internal::ParseNamedEnum<FileOptions_OptimizeMode>( + FileOptions_OptimizeMode_descriptor(), name, value); +} +enum FieldOptions_CType : int { + FieldOptions_CType_STRING = 0, + FieldOptions_CType_CORD = 1, + FieldOptions_CType_STRING_PIECE = 2 +}; +PROTOBUF_EXPORT bool FieldOptions_CType_IsValid(int value); +constexpr FieldOptions_CType FieldOptions_CType_CType_MIN = FieldOptions_CType_STRING; +constexpr FieldOptions_CType FieldOptions_CType_CType_MAX = FieldOptions_CType_STRING_PIECE; +constexpr int FieldOptions_CType_CType_ARRAYSIZE = FieldOptions_CType_CType_MAX + 1; + +PROTOBUF_EXPORT const ::PROTOBUF_NAMESPACE_ID::EnumDescriptor* FieldOptions_CType_descriptor(); +template<typename T> +inline const std::string& FieldOptions_CType_Name(T enum_t_value) { + static_assert(::std::is_same<T, FieldOptions_CType>::value || + ::std::is_integral<T>::value, + "Incorrect type passed to function FieldOptions_CType_Name."); + return ::PROTOBUF_NAMESPACE_ID::internal::NameOfEnum( + FieldOptions_CType_descriptor(), enum_t_value); +} +inline bool FieldOptions_CType_Parse( + ::PROTOBUF_NAMESPACE_ID::ConstStringParam name, FieldOptions_CType* value) { + return ::PROTOBUF_NAMESPACE_ID::internal::ParseNamedEnum<FieldOptions_CType>( + FieldOptions_CType_descriptor(), name, value); +} +enum FieldOptions_JSType : int { + FieldOptions_JSType_JS_NORMAL = 0, + FieldOptions_JSType_JS_STRING = 1, + FieldOptions_JSType_JS_NUMBER = 2 +}; +PROTOBUF_EXPORT bool FieldOptions_JSType_IsValid(int value); +constexpr FieldOptions_JSType FieldOptions_JSType_JSType_MIN = FieldOptions_JSType_JS_NORMAL; +constexpr FieldOptions_JSType FieldOptions_JSType_JSType_MAX = FieldOptions_JSType_JS_NUMBER; +constexpr int FieldOptions_JSType_JSType_ARRAYSIZE = FieldOptions_JSType_JSType_MAX + 1; + +PROTOBUF_EXPORT const ::PROTOBUF_NAMESPACE_ID::EnumDescriptor* FieldOptions_JSType_descriptor(); +template<typename T> +inline const std::string& FieldOptions_JSType_Name(T enum_t_value) { + static_assert(::std::is_same<T, FieldOptions_JSType>::value || + ::std::is_integral<T>::value, + "Incorrect type passed to function FieldOptions_JSType_Name."); + return ::PROTOBUF_NAMESPACE_ID::internal::NameOfEnum( + FieldOptions_JSType_descriptor(), enum_t_value); +} +inline bool FieldOptions_JSType_Parse( + ::PROTOBUF_NAMESPACE_ID::ConstStringParam name, FieldOptions_JSType* value) { + return ::PROTOBUF_NAMESPACE_ID::internal::ParseNamedEnum<FieldOptions_JSType>( + FieldOptions_JSType_descriptor(), name, value); +} +enum MethodOptions_IdempotencyLevel : int { + MethodOptions_IdempotencyLevel_IDEMPOTENCY_UNKNOWN = 0, + MethodOptions_IdempotencyLevel_NO_SIDE_EFFECTS = 1, + MethodOptions_IdempotencyLevel_IDEMPOTENT = 2 +}; +PROTOBUF_EXPORT bool MethodOptions_IdempotencyLevel_IsValid(int value); +constexpr MethodOptions_IdempotencyLevel MethodOptions_IdempotencyLevel_IdempotencyLevel_MIN = MethodOptions_IdempotencyLevel_IDEMPOTENCY_UNKNOWN; +constexpr MethodOptions_IdempotencyLevel MethodOptions_IdempotencyLevel_IdempotencyLevel_MAX = MethodOptions_IdempotencyLevel_IDEMPOTENT; +constexpr int MethodOptions_IdempotencyLevel_IdempotencyLevel_ARRAYSIZE = MethodOptions_IdempotencyLevel_IdempotencyLevel_MAX + 1; + +PROTOBUF_EXPORT const ::PROTOBUF_NAMESPACE_ID::EnumDescriptor* MethodOptions_IdempotencyLevel_descriptor(); +template<typename T> +inline const std::string& MethodOptions_IdempotencyLevel_Name(T enum_t_value) { + static_assert(::std::is_same<T, MethodOptions_IdempotencyLevel>::value || + ::std::is_integral<T>::value, + "Incorrect type passed to function MethodOptions_IdempotencyLevel_Name."); + return ::PROTOBUF_NAMESPACE_ID::internal::NameOfEnum( + MethodOptions_IdempotencyLevel_descriptor(), enum_t_value); +} +inline bool MethodOptions_IdempotencyLevel_Parse( + ::PROTOBUF_NAMESPACE_ID::ConstStringParam name, MethodOptions_IdempotencyLevel* value) { + return ::PROTOBUF_NAMESPACE_ID::internal::ParseNamedEnum<MethodOptions_IdempotencyLevel>( + MethodOptions_IdempotencyLevel_descriptor(), name, value); +} +// =================================================================== + +class PROTOBUF_EXPORT FileDescriptorSet final : + public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.FileDescriptorSet) */ { + public: + inline FileDescriptorSet() : FileDescriptorSet(nullptr) {} + ~FileDescriptorSet() override; + explicit PROTOBUF_CONSTEXPR FileDescriptorSet(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized); + + FileDescriptorSet(const FileDescriptorSet& from); + FileDescriptorSet(FileDescriptorSet&& from) noexcept + : FileDescriptorSet() { + *this = ::std::move(from); + } + + inline FileDescriptorSet& operator=(const FileDescriptorSet& from) { + CopyFrom(from); + return *this; + } + inline FileDescriptorSet& operator=(FileDescriptorSet&& from) noexcept { + if (this == &from) return *this; + if (GetOwningArena() == from.GetOwningArena() + #ifdef PROTOBUF_FORCE_COPY_IN_MOVE + && GetOwningArena() != nullptr + #endif // !PROTOBUF_FORCE_COPY_IN_MOVE + ) { + InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + inline const ::PROTOBUF_NAMESPACE_ID::UnknownFieldSet& unknown_fields() const { + return _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance); + } + inline ::PROTOBUF_NAMESPACE_ID::UnknownFieldSet* mutable_unknown_fields() { + return _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); + } + + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* descriptor() { + return GetDescriptor(); + } + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() { + return default_instance().GetMetadata().descriptor; + } + static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() { + return default_instance().GetMetadata().reflection; + } + static const FileDescriptorSet& default_instance() { + return *internal_default_instance(); + } + static inline const FileDescriptorSet* internal_default_instance() { + return reinterpret_cast<const FileDescriptorSet*>( + &_FileDescriptorSet_default_instance_); + } + static constexpr int kIndexInFileMessages = + 0; + + friend void swap(FileDescriptorSet& a, FileDescriptorSet& b) { + a.Swap(&b); + } + inline void Swap(FileDescriptorSet* other) { + if (other == this) return; + #ifdef PROTOBUF_FORCE_COPY_IN_SWAP + if (GetOwningArena() != nullptr && + GetOwningArena() == other->GetOwningArena()) { + #else // PROTOBUF_FORCE_COPY_IN_SWAP + if (GetOwningArena() == other->GetOwningArena()) { + #endif // !PROTOBUF_FORCE_COPY_IN_SWAP + InternalSwap(other); + } else { + ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(FileDescriptorSet* other) { + if (other == this) return; + GOOGLE_DCHECK(GetOwningArena() == other->GetOwningArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + FileDescriptorSet* New(::PROTOBUF_NAMESPACE_ID::Arena* arena = nullptr) const final { + return CreateMaybeMessage<FileDescriptorSet>(arena); + } + using ::PROTOBUF_NAMESPACE_ID::Message::CopyFrom; + void CopyFrom(const FileDescriptorSet& from); + using ::PROTOBUF_NAMESPACE_ID::Message::MergeFrom; + void MergeFrom( const FileDescriptorSet& from) { + FileDescriptorSet::MergeImpl(*this, from); + } + private: + static void MergeImpl(::PROTOBUF_NAMESPACE_ID::Message& to_msg, const ::PROTOBUF_NAMESPACE_ID::Message& from_msg); + public: + PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + bool IsInitialized() const final; + + size_t ByteSizeLong() const final; + const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final; + uint8_t* _InternalSerialize( + uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final; + int GetCachedSize() const final { return _impl_._cached_size_.Get(); } + + private: + void SharedCtor(::PROTOBUF_NAMESPACE_ID::Arena* arena, bool is_message_owned); + void SharedDtor(); + void SetCachedSize(int size) const final; + void InternalSwap(FileDescriptorSet* other); + + private: + friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata; + static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() { + return "google.protobuf.FileDescriptorSet"; + } + protected: + explicit FileDescriptorSet(::PROTOBUF_NAMESPACE_ID::Arena* arena, + bool is_message_owned = false); + public: + + static const ClassData _class_data_; + const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*GetClassData() const final; + + ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final; + + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + + enum : int { + kFileFieldNumber = 1, + }; + // repeated .google.protobuf.FileDescriptorProto file = 1; + int file_size() const; + private: + int _internal_file_size() const; + public: + void clear_file(); + ::PROTOBUF_NAMESPACE_ID::FileDescriptorProto* mutable_file(int index); + ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::FileDescriptorProto >* + mutable_file(); + private: + const ::PROTOBUF_NAMESPACE_ID::FileDescriptorProto& _internal_file(int index) const; + ::PROTOBUF_NAMESPACE_ID::FileDescriptorProto* _internal_add_file(); + public: + const ::PROTOBUF_NAMESPACE_ID::FileDescriptorProto& file(int index) const; + ::PROTOBUF_NAMESPACE_ID::FileDescriptorProto* add_file(); + const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::FileDescriptorProto >& + file() const; + + // @@protoc_insertion_point(class_scope:google.protobuf.FileDescriptorSet) + private: + class _Internal; + + template <typename T> friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper; + typedef void InternalArenaConstructable_; + typedef void DestructorSkippable_; + struct Impl_ { + ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::FileDescriptorProto > file_; + mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_; + }; + union { Impl_ _impl_; }; + friend struct ::TableStruct_google_2fprotobuf_2fdescriptor_2eproto; +}; +// ------------------------------------------------------------------- + +class PROTOBUF_EXPORT FileDescriptorProto final : + public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.FileDescriptorProto) */ { + public: + inline FileDescriptorProto() : FileDescriptorProto(nullptr) {} + ~FileDescriptorProto() override; + explicit PROTOBUF_CONSTEXPR FileDescriptorProto(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized); + + FileDescriptorProto(const FileDescriptorProto& from); + FileDescriptorProto(FileDescriptorProto&& from) noexcept + : FileDescriptorProto() { + *this = ::std::move(from); + } + + inline FileDescriptorProto& operator=(const FileDescriptorProto& from) { + CopyFrom(from); + return *this; + } + inline FileDescriptorProto& operator=(FileDescriptorProto&& from) noexcept { + if (this == &from) return *this; + if (GetOwningArena() == from.GetOwningArena() + #ifdef PROTOBUF_FORCE_COPY_IN_MOVE + && GetOwningArena() != nullptr + #endif // !PROTOBUF_FORCE_COPY_IN_MOVE + ) { + InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + inline const ::PROTOBUF_NAMESPACE_ID::UnknownFieldSet& unknown_fields() const { + return _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance); + } + inline ::PROTOBUF_NAMESPACE_ID::UnknownFieldSet* mutable_unknown_fields() { + return _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); + } + + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* descriptor() { + return GetDescriptor(); + } + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() { + return default_instance().GetMetadata().descriptor; + } + static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() { + return default_instance().GetMetadata().reflection; + } + static const FileDescriptorProto& default_instance() { + return *internal_default_instance(); + } + static inline const FileDescriptorProto* internal_default_instance() { + return reinterpret_cast<const FileDescriptorProto*>( + &_FileDescriptorProto_default_instance_); + } + static constexpr int kIndexInFileMessages = + 1; + + friend void swap(FileDescriptorProto& a, FileDescriptorProto& b) { + a.Swap(&b); + } + inline void Swap(FileDescriptorProto* other) { + if (other == this) return; + #ifdef PROTOBUF_FORCE_COPY_IN_SWAP + if (GetOwningArena() != nullptr && + GetOwningArena() == other->GetOwningArena()) { + #else // PROTOBUF_FORCE_COPY_IN_SWAP + if (GetOwningArena() == other->GetOwningArena()) { + #endif // !PROTOBUF_FORCE_COPY_IN_SWAP + InternalSwap(other); + } else { + ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(FileDescriptorProto* other) { + if (other == this) return; + GOOGLE_DCHECK(GetOwningArena() == other->GetOwningArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + FileDescriptorProto* New(::PROTOBUF_NAMESPACE_ID::Arena* arena = nullptr) const final { + return CreateMaybeMessage<FileDescriptorProto>(arena); + } + using ::PROTOBUF_NAMESPACE_ID::Message::CopyFrom; + void CopyFrom(const FileDescriptorProto& from); + using ::PROTOBUF_NAMESPACE_ID::Message::MergeFrom; + void MergeFrom( const FileDescriptorProto& from) { + FileDescriptorProto::MergeImpl(*this, from); + } + private: + static void MergeImpl(::PROTOBUF_NAMESPACE_ID::Message& to_msg, const ::PROTOBUF_NAMESPACE_ID::Message& from_msg); + public: + PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + bool IsInitialized() const final; + + size_t ByteSizeLong() const final; + const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final; + uint8_t* _InternalSerialize( + uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final; + int GetCachedSize() const final { return _impl_._cached_size_.Get(); } + + private: + void SharedCtor(::PROTOBUF_NAMESPACE_ID::Arena* arena, bool is_message_owned); + void SharedDtor(); + void SetCachedSize(int size) const final; + void InternalSwap(FileDescriptorProto* other); + + private: + friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata; + static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() { + return "google.protobuf.FileDescriptorProto"; + } + protected: + explicit FileDescriptorProto(::PROTOBUF_NAMESPACE_ID::Arena* arena, + bool is_message_owned = false); + public: + + static const ClassData _class_data_; + const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*GetClassData() const final; + + ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final; + + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + + enum : int { + kDependencyFieldNumber = 3, + kMessageTypeFieldNumber = 4, + kEnumTypeFieldNumber = 5, + kServiceFieldNumber = 6, + kExtensionFieldNumber = 7, + kPublicDependencyFieldNumber = 10, + kWeakDependencyFieldNumber = 11, + kNameFieldNumber = 1, + kPackageFieldNumber = 2, + kSyntaxFieldNumber = 12, + kOptionsFieldNumber = 8, + kSourceCodeInfoFieldNumber = 9, + }; + // repeated string dependency = 3; + int dependency_size() const; + private: + int _internal_dependency_size() const; + public: + void clear_dependency(); + const std::string& dependency(int index) const; + std::string* mutable_dependency(int index); + void set_dependency(int index, const std::string& value); + void set_dependency(int index, std::string&& value); + void set_dependency(int index, const char* value); + void set_dependency(int index, const char* value, size_t size); + std::string* add_dependency(); + void add_dependency(const std::string& value); + void add_dependency(std::string&& value); + void add_dependency(const char* value); + void add_dependency(const char* value, size_t size); + const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField<std::string>& dependency() const; + ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField<std::string>* mutable_dependency(); + private: + const std::string& _internal_dependency(int index) const; + std::string* _internal_add_dependency(); + public: + + // repeated .google.protobuf.DescriptorProto message_type = 4; + int message_type_size() const; + private: + int _internal_message_type_size() const; + public: + void clear_message_type(); + ::PROTOBUF_NAMESPACE_ID::DescriptorProto* mutable_message_type(int index); + ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::DescriptorProto >* + mutable_message_type(); + private: + const ::PROTOBUF_NAMESPACE_ID::DescriptorProto& _internal_message_type(int index) const; + ::PROTOBUF_NAMESPACE_ID::DescriptorProto* _internal_add_message_type(); + public: + const ::PROTOBUF_NAMESPACE_ID::DescriptorProto& message_type(int index) const; + ::PROTOBUF_NAMESPACE_ID::DescriptorProto* add_message_type(); + const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::DescriptorProto >& + message_type() const; + + // repeated .google.protobuf.EnumDescriptorProto enum_type = 5; + int enum_type_size() const; + private: + int _internal_enum_type_size() const; + public: + void clear_enum_type(); + ::PROTOBUF_NAMESPACE_ID::EnumDescriptorProto* mutable_enum_type(int index); + ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::EnumDescriptorProto >* + mutable_enum_type(); + private: + const ::PROTOBUF_NAMESPACE_ID::EnumDescriptorProto& _internal_enum_type(int index) const; + ::PROTOBUF_NAMESPACE_ID::EnumDescriptorProto* _internal_add_enum_type(); + public: + const ::PROTOBUF_NAMESPACE_ID::EnumDescriptorProto& enum_type(int index) const; + ::PROTOBUF_NAMESPACE_ID::EnumDescriptorProto* add_enum_type(); + const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::EnumDescriptorProto >& + enum_type() const; + + // repeated .google.protobuf.ServiceDescriptorProto service = 6; + int service_size() const; + private: + int _internal_service_size() const; + public: + void clear_service(); + ::PROTOBUF_NAMESPACE_ID::ServiceDescriptorProto* mutable_service(int index); + ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::ServiceDescriptorProto >* + mutable_service(); + private: + const ::PROTOBUF_NAMESPACE_ID::ServiceDescriptorProto& _internal_service(int index) const; + ::PROTOBUF_NAMESPACE_ID::ServiceDescriptorProto* _internal_add_service(); + public: + const ::PROTOBUF_NAMESPACE_ID::ServiceDescriptorProto& service(int index) const; + ::PROTOBUF_NAMESPACE_ID::ServiceDescriptorProto* add_service(); + const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::ServiceDescriptorProto >& + service() const; + + // repeated .google.protobuf.FieldDescriptorProto extension = 7; + int extension_size() const; + private: + int _internal_extension_size() const; + public: + void clear_extension(); + ::PROTOBUF_NAMESPACE_ID::FieldDescriptorProto* mutable_extension(int index); + ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::FieldDescriptorProto >* + mutable_extension(); + private: + const ::PROTOBUF_NAMESPACE_ID::FieldDescriptorProto& _internal_extension(int index) const; + ::PROTOBUF_NAMESPACE_ID::FieldDescriptorProto* _internal_add_extension(); + public: + const ::PROTOBUF_NAMESPACE_ID::FieldDescriptorProto& extension(int index) const; + ::PROTOBUF_NAMESPACE_ID::FieldDescriptorProto* add_extension(); + const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::FieldDescriptorProto >& + extension() const; + + // repeated int32 public_dependency = 10; + int public_dependency_size() const; + private: + int _internal_public_dependency_size() const; + public: + void clear_public_dependency(); + private: + int32_t _internal_public_dependency(int index) const; + const ::PROTOBUF_NAMESPACE_ID::RepeatedField< int32_t >& + _internal_public_dependency() const; + void _internal_add_public_dependency(int32_t value); + ::PROTOBUF_NAMESPACE_ID::RepeatedField< int32_t >* + _internal_mutable_public_dependency(); + public: + int32_t public_dependency(int index) const; + void set_public_dependency(int index, int32_t value); + void add_public_dependency(int32_t value); + const ::PROTOBUF_NAMESPACE_ID::RepeatedField< int32_t >& + public_dependency() const; + ::PROTOBUF_NAMESPACE_ID::RepeatedField< int32_t >* + mutable_public_dependency(); + + // repeated int32 weak_dependency = 11; + int weak_dependency_size() const; + private: + int _internal_weak_dependency_size() const; + public: + void clear_weak_dependency(); + private: + int32_t _internal_weak_dependency(int index) const; + const ::PROTOBUF_NAMESPACE_ID::RepeatedField< int32_t >& + _internal_weak_dependency() const; + void _internal_add_weak_dependency(int32_t value); + ::PROTOBUF_NAMESPACE_ID::RepeatedField< int32_t >* + _internal_mutable_weak_dependency(); + public: + int32_t weak_dependency(int index) const; + void set_weak_dependency(int index, int32_t value); + void add_weak_dependency(int32_t value); + const ::PROTOBUF_NAMESPACE_ID::RepeatedField< int32_t >& + weak_dependency() const; + ::PROTOBUF_NAMESPACE_ID::RepeatedField< int32_t >* + mutable_weak_dependency(); + + // optional string name = 1; + bool has_name() const; + private: + bool _internal_has_name() const; + public: + void clear_name(); + const std::string& name() const; + template <typename ArgT0 = const std::string&, typename... ArgT> + void set_name(ArgT0&& arg0, ArgT... args); + std::string* mutable_name(); + PROTOBUF_NODISCARD std::string* release_name(); + void set_allocated_name(std::string* name); + private: + const std::string& _internal_name() const; + inline PROTOBUF_ALWAYS_INLINE void _internal_set_name(const std::string& value); + std::string* _internal_mutable_name(); + public: + + // optional string package = 2; + bool has_package() const; + private: + bool _internal_has_package() const; + public: + void clear_package(); + const std::string& package() const; + template <typename ArgT0 = const std::string&, typename... ArgT> + void set_package(ArgT0&& arg0, ArgT... args); + std::string* mutable_package(); + PROTOBUF_NODISCARD std::string* release_package(); + void set_allocated_package(std::string* package); + private: + const std::string& _internal_package() const; + inline PROTOBUF_ALWAYS_INLINE void _internal_set_package(const std::string& value); + std::string* _internal_mutable_package(); + public: + + // optional string syntax = 12; + bool has_syntax() const; + private: + bool _internal_has_syntax() const; + public: + void clear_syntax(); + const std::string& syntax() const; + template <typename ArgT0 = const std::string&, typename... ArgT> + void set_syntax(ArgT0&& arg0, ArgT... args); + std::string* mutable_syntax(); + PROTOBUF_NODISCARD std::string* release_syntax(); + void set_allocated_syntax(std::string* syntax); + private: + const std::string& _internal_syntax() const; + inline PROTOBUF_ALWAYS_INLINE void _internal_set_syntax(const std::string& value); + std::string* _internal_mutable_syntax(); + public: + + // optional .google.protobuf.FileOptions options = 8; + bool has_options() const; + private: + bool _internal_has_options() const; + public: + void clear_options(); + const ::PROTOBUF_NAMESPACE_ID::FileOptions& options() const; + PROTOBUF_NODISCARD ::PROTOBUF_NAMESPACE_ID::FileOptions* release_options(); + ::PROTOBUF_NAMESPACE_ID::FileOptions* mutable_options(); + void set_allocated_options(::PROTOBUF_NAMESPACE_ID::FileOptions* options); + private: + const ::PROTOBUF_NAMESPACE_ID::FileOptions& _internal_options() const; + ::PROTOBUF_NAMESPACE_ID::FileOptions* _internal_mutable_options(); + public: + void unsafe_arena_set_allocated_options( + ::PROTOBUF_NAMESPACE_ID::FileOptions* options); + ::PROTOBUF_NAMESPACE_ID::FileOptions* unsafe_arena_release_options(); + + // optional .google.protobuf.SourceCodeInfo source_code_info = 9; + bool has_source_code_info() const; + private: + bool _internal_has_source_code_info() const; + public: + void clear_source_code_info(); + const ::PROTOBUF_NAMESPACE_ID::SourceCodeInfo& source_code_info() const; + PROTOBUF_NODISCARD ::PROTOBUF_NAMESPACE_ID::SourceCodeInfo* release_source_code_info(); + ::PROTOBUF_NAMESPACE_ID::SourceCodeInfo* mutable_source_code_info(); + void set_allocated_source_code_info(::PROTOBUF_NAMESPACE_ID::SourceCodeInfo* source_code_info); + private: + const ::PROTOBUF_NAMESPACE_ID::SourceCodeInfo& _internal_source_code_info() const; + ::PROTOBUF_NAMESPACE_ID::SourceCodeInfo* _internal_mutable_source_code_info(); + public: + void unsafe_arena_set_allocated_source_code_info( + ::PROTOBUF_NAMESPACE_ID::SourceCodeInfo* source_code_info); + ::PROTOBUF_NAMESPACE_ID::SourceCodeInfo* unsafe_arena_release_source_code_info(); + + // @@protoc_insertion_point(class_scope:google.protobuf.FileDescriptorProto) + private: + class _Internal; + + template <typename T> friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper; + typedef void InternalArenaConstructable_; + typedef void DestructorSkippable_; + struct Impl_ { + ::PROTOBUF_NAMESPACE_ID::internal::HasBits<1> _has_bits_; + mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_; + ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField<std::string> dependency_; + ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::DescriptorProto > message_type_; + ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::EnumDescriptorProto > enum_type_; + ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::ServiceDescriptorProto > service_; + ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::FieldDescriptorProto > extension_; + ::PROTOBUF_NAMESPACE_ID::RepeatedField< int32_t > public_dependency_; + ::PROTOBUF_NAMESPACE_ID::RepeatedField< int32_t > weak_dependency_; + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr name_; + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr package_; + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr syntax_; + ::PROTOBUF_NAMESPACE_ID::FileOptions* options_; + ::PROTOBUF_NAMESPACE_ID::SourceCodeInfo* source_code_info_; + }; + union { Impl_ _impl_; }; + friend struct ::TableStruct_google_2fprotobuf_2fdescriptor_2eproto; +}; +// ------------------------------------------------------------------- + +class PROTOBUF_EXPORT DescriptorProto_ExtensionRange final : + public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.DescriptorProto.ExtensionRange) */ { + public: + inline DescriptorProto_ExtensionRange() : DescriptorProto_ExtensionRange(nullptr) {} + ~DescriptorProto_ExtensionRange() override; + explicit PROTOBUF_CONSTEXPR DescriptorProto_ExtensionRange(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized); + + DescriptorProto_ExtensionRange(const DescriptorProto_ExtensionRange& from); + DescriptorProto_ExtensionRange(DescriptorProto_ExtensionRange&& from) noexcept + : DescriptorProto_ExtensionRange() { + *this = ::std::move(from); + } + + inline DescriptorProto_ExtensionRange& operator=(const DescriptorProto_ExtensionRange& from) { + CopyFrom(from); + return *this; + } + inline DescriptorProto_ExtensionRange& operator=(DescriptorProto_ExtensionRange&& from) noexcept { + if (this == &from) return *this; + if (GetOwningArena() == from.GetOwningArena() + #ifdef PROTOBUF_FORCE_COPY_IN_MOVE + && GetOwningArena() != nullptr + #endif // !PROTOBUF_FORCE_COPY_IN_MOVE + ) { + InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + inline const ::PROTOBUF_NAMESPACE_ID::UnknownFieldSet& unknown_fields() const { + return _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance); + } + inline ::PROTOBUF_NAMESPACE_ID::UnknownFieldSet* mutable_unknown_fields() { + return _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); + } + + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* descriptor() { + return GetDescriptor(); + } + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() { + return default_instance().GetMetadata().descriptor; + } + static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() { + return default_instance().GetMetadata().reflection; + } + static const DescriptorProto_ExtensionRange& default_instance() { + return *internal_default_instance(); + } + static inline const DescriptorProto_ExtensionRange* internal_default_instance() { + return reinterpret_cast<const DescriptorProto_ExtensionRange*>( + &_DescriptorProto_ExtensionRange_default_instance_); + } + static constexpr int kIndexInFileMessages = + 2; + + friend void swap(DescriptorProto_ExtensionRange& a, DescriptorProto_ExtensionRange& b) { + a.Swap(&b); + } + inline void Swap(DescriptorProto_ExtensionRange* other) { + if (other == this) return; + #ifdef PROTOBUF_FORCE_COPY_IN_SWAP + if (GetOwningArena() != nullptr && + GetOwningArena() == other->GetOwningArena()) { + #else // PROTOBUF_FORCE_COPY_IN_SWAP + if (GetOwningArena() == other->GetOwningArena()) { + #endif // !PROTOBUF_FORCE_COPY_IN_SWAP + InternalSwap(other); + } else { + ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(DescriptorProto_ExtensionRange* other) { + if (other == this) return; + GOOGLE_DCHECK(GetOwningArena() == other->GetOwningArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + DescriptorProto_ExtensionRange* New(::PROTOBUF_NAMESPACE_ID::Arena* arena = nullptr) const final { + return CreateMaybeMessage<DescriptorProto_ExtensionRange>(arena); + } + using ::PROTOBUF_NAMESPACE_ID::Message::CopyFrom; + void CopyFrom(const DescriptorProto_ExtensionRange& from); + using ::PROTOBUF_NAMESPACE_ID::Message::MergeFrom; + void MergeFrom( const DescriptorProto_ExtensionRange& from) { + DescriptorProto_ExtensionRange::MergeImpl(*this, from); + } + private: + static void MergeImpl(::PROTOBUF_NAMESPACE_ID::Message& to_msg, const ::PROTOBUF_NAMESPACE_ID::Message& from_msg); + public: + PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + bool IsInitialized() const final; + + size_t ByteSizeLong() const final; + const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final; + uint8_t* _InternalSerialize( + uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final; + int GetCachedSize() const final { return _impl_._cached_size_.Get(); } + + private: + void SharedCtor(::PROTOBUF_NAMESPACE_ID::Arena* arena, bool is_message_owned); + void SharedDtor(); + void SetCachedSize(int size) const final; + void InternalSwap(DescriptorProto_ExtensionRange* other); + + private: + friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata; + static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() { + return "google.protobuf.DescriptorProto.ExtensionRange"; + } + protected: + explicit DescriptorProto_ExtensionRange(::PROTOBUF_NAMESPACE_ID::Arena* arena, + bool is_message_owned = false); + public: + + static const ClassData _class_data_; + const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*GetClassData() const final; + + ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final; + + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + + enum : int { + kOptionsFieldNumber = 3, + kStartFieldNumber = 1, + kEndFieldNumber = 2, + }; + // optional .google.protobuf.ExtensionRangeOptions options = 3; + bool has_options() const; + private: + bool _internal_has_options() const; + public: + void clear_options(); + const ::PROTOBUF_NAMESPACE_ID::ExtensionRangeOptions& options() const; + PROTOBUF_NODISCARD ::PROTOBUF_NAMESPACE_ID::ExtensionRangeOptions* release_options(); + ::PROTOBUF_NAMESPACE_ID::ExtensionRangeOptions* mutable_options(); + void set_allocated_options(::PROTOBUF_NAMESPACE_ID::ExtensionRangeOptions* options); + private: + const ::PROTOBUF_NAMESPACE_ID::ExtensionRangeOptions& _internal_options() const; + ::PROTOBUF_NAMESPACE_ID::ExtensionRangeOptions* _internal_mutable_options(); + public: + void unsafe_arena_set_allocated_options( + ::PROTOBUF_NAMESPACE_ID::ExtensionRangeOptions* options); + ::PROTOBUF_NAMESPACE_ID::ExtensionRangeOptions* unsafe_arena_release_options(); + + // optional int32 start = 1; + bool has_start() const; + private: + bool _internal_has_start() const; + public: + void clear_start(); + int32_t start() const; + void set_start(int32_t value); + private: + int32_t _internal_start() const; + void _internal_set_start(int32_t value); + public: + + // optional int32 end = 2; + bool has_end() const; + private: + bool _internal_has_end() const; + public: + void clear_end(); + int32_t end() const; + void set_end(int32_t value); + private: + int32_t _internal_end() const; + void _internal_set_end(int32_t value); + public: + + // @@protoc_insertion_point(class_scope:google.protobuf.DescriptorProto.ExtensionRange) + private: + class _Internal; + + template <typename T> friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper; + typedef void InternalArenaConstructable_; + typedef void DestructorSkippable_; + struct Impl_ { + ::PROTOBUF_NAMESPACE_ID::internal::HasBits<1> _has_bits_; + mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_; + ::PROTOBUF_NAMESPACE_ID::ExtensionRangeOptions* options_; + int32_t start_; + int32_t end_; + }; + union { Impl_ _impl_; }; + friend struct ::TableStruct_google_2fprotobuf_2fdescriptor_2eproto; +}; +// ------------------------------------------------------------------- + +class PROTOBUF_EXPORT DescriptorProto_ReservedRange final : + public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.DescriptorProto.ReservedRange) */ { + public: + inline DescriptorProto_ReservedRange() : DescriptorProto_ReservedRange(nullptr) {} + ~DescriptorProto_ReservedRange() override; + explicit PROTOBUF_CONSTEXPR DescriptorProto_ReservedRange(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized); + + DescriptorProto_ReservedRange(const DescriptorProto_ReservedRange& from); + DescriptorProto_ReservedRange(DescriptorProto_ReservedRange&& from) noexcept + : DescriptorProto_ReservedRange() { + *this = ::std::move(from); + } + + inline DescriptorProto_ReservedRange& operator=(const DescriptorProto_ReservedRange& from) { + CopyFrom(from); + return *this; + } + inline DescriptorProto_ReservedRange& operator=(DescriptorProto_ReservedRange&& from) noexcept { + if (this == &from) return *this; + if (GetOwningArena() == from.GetOwningArena() + #ifdef PROTOBUF_FORCE_COPY_IN_MOVE + && GetOwningArena() != nullptr + #endif // !PROTOBUF_FORCE_COPY_IN_MOVE + ) { + InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + inline const ::PROTOBUF_NAMESPACE_ID::UnknownFieldSet& unknown_fields() const { + return _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance); + } + inline ::PROTOBUF_NAMESPACE_ID::UnknownFieldSet* mutable_unknown_fields() { + return _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); + } + + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* descriptor() { + return GetDescriptor(); + } + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() { + return default_instance().GetMetadata().descriptor; + } + static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() { + return default_instance().GetMetadata().reflection; + } + static const DescriptorProto_ReservedRange& default_instance() { + return *internal_default_instance(); + } + static inline const DescriptorProto_ReservedRange* internal_default_instance() { + return reinterpret_cast<const DescriptorProto_ReservedRange*>( + &_DescriptorProto_ReservedRange_default_instance_); + } + static constexpr int kIndexInFileMessages = + 3; + + friend void swap(DescriptorProto_ReservedRange& a, DescriptorProto_ReservedRange& b) { + a.Swap(&b); + } + inline void Swap(DescriptorProto_ReservedRange* other) { + if (other == this) return; + #ifdef PROTOBUF_FORCE_COPY_IN_SWAP + if (GetOwningArena() != nullptr && + GetOwningArena() == other->GetOwningArena()) { + #else // PROTOBUF_FORCE_COPY_IN_SWAP + if (GetOwningArena() == other->GetOwningArena()) { + #endif // !PROTOBUF_FORCE_COPY_IN_SWAP + InternalSwap(other); + } else { + ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(DescriptorProto_ReservedRange* other) { + if (other == this) return; + GOOGLE_DCHECK(GetOwningArena() == other->GetOwningArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + DescriptorProto_ReservedRange* New(::PROTOBUF_NAMESPACE_ID::Arena* arena = nullptr) const final { + return CreateMaybeMessage<DescriptorProto_ReservedRange>(arena); + } + using ::PROTOBUF_NAMESPACE_ID::Message::CopyFrom; + void CopyFrom(const DescriptorProto_ReservedRange& from); + using ::PROTOBUF_NAMESPACE_ID::Message::MergeFrom; + void MergeFrom( const DescriptorProto_ReservedRange& from) { + DescriptorProto_ReservedRange::MergeImpl(*this, from); + } + private: + static void MergeImpl(::PROTOBUF_NAMESPACE_ID::Message& to_msg, const ::PROTOBUF_NAMESPACE_ID::Message& from_msg); + public: + PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + bool IsInitialized() const final; + + size_t ByteSizeLong() const final; + const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final; + uint8_t* _InternalSerialize( + uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final; + int GetCachedSize() const final { return _impl_._cached_size_.Get(); } + + private: + void SharedCtor(::PROTOBUF_NAMESPACE_ID::Arena* arena, bool is_message_owned); + void SharedDtor(); + void SetCachedSize(int size) const final; + void InternalSwap(DescriptorProto_ReservedRange* other); + + private: + friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata; + static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() { + return "google.protobuf.DescriptorProto.ReservedRange"; + } + protected: + explicit DescriptorProto_ReservedRange(::PROTOBUF_NAMESPACE_ID::Arena* arena, + bool is_message_owned = false); + public: + + static const ClassData _class_data_; + const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*GetClassData() const final; + + ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final; + + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + + enum : int { + kStartFieldNumber = 1, + kEndFieldNumber = 2, + }; + // optional int32 start = 1; + bool has_start() const; + private: + bool _internal_has_start() const; + public: + void clear_start(); + int32_t start() const; + void set_start(int32_t value); + private: + int32_t _internal_start() const; + void _internal_set_start(int32_t value); + public: + + // optional int32 end = 2; + bool has_end() const; + private: + bool _internal_has_end() const; + public: + void clear_end(); + int32_t end() const; + void set_end(int32_t value); + private: + int32_t _internal_end() const; + void _internal_set_end(int32_t value); + public: + + // @@protoc_insertion_point(class_scope:google.protobuf.DescriptorProto.ReservedRange) + private: + class _Internal; + + template <typename T> friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper; + typedef void InternalArenaConstructable_; + typedef void DestructorSkippable_; + struct Impl_ { + ::PROTOBUF_NAMESPACE_ID::internal::HasBits<1> _has_bits_; + mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_; + int32_t start_; + int32_t end_; + }; + union { Impl_ _impl_; }; + friend struct ::TableStruct_google_2fprotobuf_2fdescriptor_2eproto; +}; +// ------------------------------------------------------------------- + +class PROTOBUF_EXPORT DescriptorProto final : + public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.DescriptorProto) */ { + public: + inline DescriptorProto() : DescriptorProto(nullptr) {} + ~DescriptorProto() override; + explicit PROTOBUF_CONSTEXPR DescriptorProto(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized); + + DescriptorProto(const DescriptorProto& from); + DescriptorProto(DescriptorProto&& from) noexcept + : DescriptorProto() { + *this = ::std::move(from); + } + + inline DescriptorProto& operator=(const DescriptorProto& from) { + CopyFrom(from); + return *this; + } + inline DescriptorProto& operator=(DescriptorProto&& from) noexcept { + if (this == &from) return *this; + if (GetOwningArena() == from.GetOwningArena() + #ifdef PROTOBUF_FORCE_COPY_IN_MOVE + && GetOwningArena() != nullptr + #endif // !PROTOBUF_FORCE_COPY_IN_MOVE + ) { + InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + inline const ::PROTOBUF_NAMESPACE_ID::UnknownFieldSet& unknown_fields() const { + return _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance); + } + inline ::PROTOBUF_NAMESPACE_ID::UnknownFieldSet* mutable_unknown_fields() { + return _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); + } + + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* descriptor() { + return GetDescriptor(); + } + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() { + return default_instance().GetMetadata().descriptor; + } + static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() { + return default_instance().GetMetadata().reflection; + } + static const DescriptorProto& default_instance() { + return *internal_default_instance(); + } + static inline const DescriptorProto* internal_default_instance() { + return reinterpret_cast<const DescriptorProto*>( + &_DescriptorProto_default_instance_); + } + static constexpr int kIndexInFileMessages = + 4; + + friend void swap(DescriptorProto& a, DescriptorProto& b) { + a.Swap(&b); + } + inline void Swap(DescriptorProto* other) { + if (other == this) return; + #ifdef PROTOBUF_FORCE_COPY_IN_SWAP + if (GetOwningArena() != nullptr && + GetOwningArena() == other->GetOwningArena()) { + #else // PROTOBUF_FORCE_COPY_IN_SWAP + if (GetOwningArena() == other->GetOwningArena()) { + #endif // !PROTOBUF_FORCE_COPY_IN_SWAP + InternalSwap(other); + } else { + ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(DescriptorProto* other) { + if (other == this) return; + GOOGLE_DCHECK(GetOwningArena() == other->GetOwningArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + DescriptorProto* New(::PROTOBUF_NAMESPACE_ID::Arena* arena = nullptr) const final { + return CreateMaybeMessage<DescriptorProto>(arena); + } + using ::PROTOBUF_NAMESPACE_ID::Message::CopyFrom; + void CopyFrom(const DescriptorProto& from); + using ::PROTOBUF_NAMESPACE_ID::Message::MergeFrom; + void MergeFrom( const DescriptorProto& from) { + DescriptorProto::MergeImpl(*this, from); + } + private: + static void MergeImpl(::PROTOBUF_NAMESPACE_ID::Message& to_msg, const ::PROTOBUF_NAMESPACE_ID::Message& from_msg); + public: + PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + bool IsInitialized() const final; + + size_t ByteSizeLong() const final; + const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final; + uint8_t* _InternalSerialize( + uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final; + int GetCachedSize() const final { return _impl_._cached_size_.Get(); } + + private: + void SharedCtor(::PROTOBUF_NAMESPACE_ID::Arena* arena, bool is_message_owned); + void SharedDtor(); + void SetCachedSize(int size) const final; + void InternalSwap(DescriptorProto* other); + + private: + friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata; + static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() { + return "google.protobuf.DescriptorProto"; + } + protected: + explicit DescriptorProto(::PROTOBUF_NAMESPACE_ID::Arena* arena, + bool is_message_owned = false); + public: + + static const ClassData _class_data_; + const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*GetClassData() const final; + + ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final; + + // nested types ---------------------------------------------------- + + typedef DescriptorProto_ExtensionRange ExtensionRange; + typedef DescriptorProto_ReservedRange ReservedRange; + + // accessors ------------------------------------------------------- + + enum : int { + kFieldFieldNumber = 2, + kNestedTypeFieldNumber = 3, + kEnumTypeFieldNumber = 4, + kExtensionRangeFieldNumber = 5, + kExtensionFieldNumber = 6, + kOneofDeclFieldNumber = 8, + kReservedRangeFieldNumber = 9, + kReservedNameFieldNumber = 10, + kNameFieldNumber = 1, + kOptionsFieldNumber = 7, + }; + // repeated .google.protobuf.FieldDescriptorProto field = 2; + int field_size() const; + private: + int _internal_field_size() const; + public: + void clear_field(); + ::PROTOBUF_NAMESPACE_ID::FieldDescriptorProto* mutable_field(int index); + ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::FieldDescriptorProto >* + mutable_field(); + private: + const ::PROTOBUF_NAMESPACE_ID::FieldDescriptorProto& _internal_field(int index) const; + ::PROTOBUF_NAMESPACE_ID::FieldDescriptorProto* _internal_add_field(); + public: + const ::PROTOBUF_NAMESPACE_ID::FieldDescriptorProto& field(int index) const; + ::PROTOBUF_NAMESPACE_ID::FieldDescriptorProto* add_field(); + const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::FieldDescriptorProto >& + field() const; + + // repeated .google.protobuf.DescriptorProto nested_type = 3; + int nested_type_size() const; + private: + int _internal_nested_type_size() const; + public: + void clear_nested_type(); + ::PROTOBUF_NAMESPACE_ID::DescriptorProto* mutable_nested_type(int index); + ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::DescriptorProto >* + mutable_nested_type(); + private: + const ::PROTOBUF_NAMESPACE_ID::DescriptorProto& _internal_nested_type(int index) const; + ::PROTOBUF_NAMESPACE_ID::DescriptorProto* _internal_add_nested_type(); + public: + const ::PROTOBUF_NAMESPACE_ID::DescriptorProto& nested_type(int index) const; + ::PROTOBUF_NAMESPACE_ID::DescriptorProto* add_nested_type(); + const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::DescriptorProto >& + nested_type() const; + + // repeated .google.protobuf.EnumDescriptorProto enum_type = 4; + int enum_type_size() const; + private: + int _internal_enum_type_size() const; + public: + void clear_enum_type(); + ::PROTOBUF_NAMESPACE_ID::EnumDescriptorProto* mutable_enum_type(int index); + ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::EnumDescriptorProto >* + mutable_enum_type(); + private: + const ::PROTOBUF_NAMESPACE_ID::EnumDescriptorProto& _internal_enum_type(int index) const; + ::PROTOBUF_NAMESPACE_ID::EnumDescriptorProto* _internal_add_enum_type(); + public: + const ::PROTOBUF_NAMESPACE_ID::EnumDescriptorProto& enum_type(int index) const; + ::PROTOBUF_NAMESPACE_ID::EnumDescriptorProto* add_enum_type(); + const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::EnumDescriptorProto >& + enum_type() const; + + // repeated .google.protobuf.DescriptorProto.ExtensionRange extension_range = 5; + int extension_range_size() const; + private: + int _internal_extension_range_size() const; + public: + void clear_extension_range(); + ::PROTOBUF_NAMESPACE_ID::DescriptorProto_ExtensionRange* mutable_extension_range(int index); + ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::DescriptorProto_ExtensionRange >* + mutable_extension_range(); + private: + const ::PROTOBUF_NAMESPACE_ID::DescriptorProto_ExtensionRange& _internal_extension_range(int index) const; + ::PROTOBUF_NAMESPACE_ID::DescriptorProto_ExtensionRange* _internal_add_extension_range(); + public: + const ::PROTOBUF_NAMESPACE_ID::DescriptorProto_ExtensionRange& extension_range(int index) const; + ::PROTOBUF_NAMESPACE_ID::DescriptorProto_ExtensionRange* add_extension_range(); + const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::DescriptorProto_ExtensionRange >& + extension_range() const; + + // repeated .google.protobuf.FieldDescriptorProto extension = 6; + int extension_size() const; + private: + int _internal_extension_size() const; + public: + void clear_extension(); + ::PROTOBUF_NAMESPACE_ID::FieldDescriptorProto* mutable_extension(int index); + ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::FieldDescriptorProto >* + mutable_extension(); + private: + const ::PROTOBUF_NAMESPACE_ID::FieldDescriptorProto& _internal_extension(int index) const; + ::PROTOBUF_NAMESPACE_ID::FieldDescriptorProto* _internal_add_extension(); + public: + const ::PROTOBUF_NAMESPACE_ID::FieldDescriptorProto& extension(int index) const; + ::PROTOBUF_NAMESPACE_ID::FieldDescriptorProto* add_extension(); + const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::FieldDescriptorProto >& + extension() const; + + // repeated .google.protobuf.OneofDescriptorProto oneof_decl = 8; + int oneof_decl_size() const; + private: + int _internal_oneof_decl_size() const; + public: + void clear_oneof_decl(); + ::PROTOBUF_NAMESPACE_ID::OneofDescriptorProto* mutable_oneof_decl(int index); + ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::OneofDescriptorProto >* + mutable_oneof_decl(); + private: + const ::PROTOBUF_NAMESPACE_ID::OneofDescriptorProto& _internal_oneof_decl(int index) const; + ::PROTOBUF_NAMESPACE_ID::OneofDescriptorProto* _internal_add_oneof_decl(); + public: + const ::PROTOBUF_NAMESPACE_ID::OneofDescriptorProto& oneof_decl(int index) const; + ::PROTOBUF_NAMESPACE_ID::OneofDescriptorProto* add_oneof_decl(); + const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::OneofDescriptorProto >& + oneof_decl() const; + + // repeated .google.protobuf.DescriptorProto.ReservedRange reserved_range = 9; + int reserved_range_size() const; + private: + int _internal_reserved_range_size() const; + public: + void clear_reserved_range(); + ::PROTOBUF_NAMESPACE_ID::DescriptorProto_ReservedRange* mutable_reserved_range(int index); + ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::DescriptorProto_ReservedRange >* + mutable_reserved_range(); + private: + const ::PROTOBUF_NAMESPACE_ID::DescriptorProto_ReservedRange& _internal_reserved_range(int index) const; + ::PROTOBUF_NAMESPACE_ID::DescriptorProto_ReservedRange* _internal_add_reserved_range(); + public: + const ::PROTOBUF_NAMESPACE_ID::DescriptorProto_ReservedRange& reserved_range(int index) const; + ::PROTOBUF_NAMESPACE_ID::DescriptorProto_ReservedRange* add_reserved_range(); + const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::DescriptorProto_ReservedRange >& + reserved_range() const; + + // repeated string reserved_name = 10; + int reserved_name_size() const; + private: + int _internal_reserved_name_size() const; + public: + void clear_reserved_name(); + const std::string& reserved_name(int index) const; + std::string* mutable_reserved_name(int index); + void set_reserved_name(int index, const std::string& value); + void set_reserved_name(int index, std::string&& value); + void set_reserved_name(int index, const char* value); + void set_reserved_name(int index, const char* value, size_t size); + std::string* add_reserved_name(); + void add_reserved_name(const std::string& value); + void add_reserved_name(std::string&& value); + void add_reserved_name(const char* value); + void add_reserved_name(const char* value, size_t size); + const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField<std::string>& reserved_name() const; + ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField<std::string>* mutable_reserved_name(); + private: + const std::string& _internal_reserved_name(int index) const; + std::string* _internal_add_reserved_name(); + public: + + // optional string name = 1; + bool has_name() const; + private: + bool _internal_has_name() const; + public: + void clear_name(); + const std::string& name() const; + template <typename ArgT0 = const std::string&, typename... ArgT> + void set_name(ArgT0&& arg0, ArgT... args); + std::string* mutable_name(); + PROTOBUF_NODISCARD std::string* release_name(); + void set_allocated_name(std::string* name); + private: + const std::string& _internal_name() const; + inline PROTOBUF_ALWAYS_INLINE void _internal_set_name(const std::string& value); + std::string* _internal_mutable_name(); + public: + + // optional .google.protobuf.MessageOptions options = 7; + bool has_options() const; + private: + bool _internal_has_options() const; + public: + void clear_options(); + const ::PROTOBUF_NAMESPACE_ID::MessageOptions& options() const; + PROTOBUF_NODISCARD ::PROTOBUF_NAMESPACE_ID::MessageOptions* release_options(); + ::PROTOBUF_NAMESPACE_ID::MessageOptions* mutable_options(); + void set_allocated_options(::PROTOBUF_NAMESPACE_ID::MessageOptions* options); + private: + const ::PROTOBUF_NAMESPACE_ID::MessageOptions& _internal_options() const; + ::PROTOBUF_NAMESPACE_ID::MessageOptions* _internal_mutable_options(); + public: + void unsafe_arena_set_allocated_options( + ::PROTOBUF_NAMESPACE_ID::MessageOptions* options); + ::PROTOBUF_NAMESPACE_ID::MessageOptions* unsafe_arena_release_options(); + + // @@protoc_insertion_point(class_scope:google.protobuf.DescriptorProto) + private: + class _Internal; + + template <typename T> friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper; + typedef void InternalArenaConstructable_; + typedef void DestructorSkippable_; + struct Impl_ { + ::PROTOBUF_NAMESPACE_ID::internal::HasBits<1> _has_bits_; + mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_; + ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::FieldDescriptorProto > field_; + ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::DescriptorProto > nested_type_; + ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::EnumDescriptorProto > enum_type_; + ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::DescriptorProto_ExtensionRange > extension_range_; + ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::FieldDescriptorProto > extension_; + ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::OneofDescriptorProto > oneof_decl_; + ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::DescriptorProto_ReservedRange > reserved_range_; + ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField<std::string> reserved_name_; + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr name_; + ::PROTOBUF_NAMESPACE_ID::MessageOptions* options_; + }; + union { Impl_ _impl_; }; + friend struct ::TableStruct_google_2fprotobuf_2fdescriptor_2eproto; +}; +// ------------------------------------------------------------------- + +class PROTOBUF_EXPORT ExtensionRangeOptions final : + public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.ExtensionRangeOptions) */ { + public: + inline ExtensionRangeOptions() : ExtensionRangeOptions(nullptr) {} + ~ExtensionRangeOptions() override; + explicit PROTOBUF_CONSTEXPR ExtensionRangeOptions(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized); + + ExtensionRangeOptions(const ExtensionRangeOptions& from); + ExtensionRangeOptions(ExtensionRangeOptions&& from) noexcept + : ExtensionRangeOptions() { + *this = ::std::move(from); + } + + inline ExtensionRangeOptions& operator=(const ExtensionRangeOptions& from) { + CopyFrom(from); + return *this; + } + inline ExtensionRangeOptions& operator=(ExtensionRangeOptions&& from) noexcept { + if (this == &from) return *this; + if (GetOwningArena() == from.GetOwningArena() + #ifdef PROTOBUF_FORCE_COPY_IN_MOVE + && GetOwningArena() != nullptr + #endif // !PROTOBUF_FORCE_COPY_IN_MOVE + ) { + InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + inline const ::PROTOBUF_NAMESPACE_ID::UnknownFieldSet& unknown_fields() const { + return _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance); + } + inline ::PROTOBUF_NAMESPACE_ID::UnknownFieldSet* mutable_unknown_fields() { + return _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); + } + + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* descriptor() { + return GetDescriptor(); + } + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() { + return default_instance().GetMetadata().descriptor; + } + static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() { + return default_instance().GetMetadata().reflection; + } + static const ExtensionRangeOptions& default_instance() { + return *internal_default_instance(); + } + static inline const ExtensionRangeOptions* internal_default_instance() { + return reinterpret_cast<const ExtensionRangeOptions*>( + &_ExtensionRangeOptions_default_instance_); + } + static constexpr int kIndexInFileMessages = + 5; + + friend void swap(ExtensionRangeOptions& a, ExtensionRangeOptions& b) { + a.Swap(&b); + } + inline void Swap(ExtensionRangeOptions* other) { + if (other == this) return; + #ifdef PROTOBUF_FORCE_COPY_IN_SWAP + if (GetOwningArena() != nullptr && + GetOwningArena() == other->GetOwningArena()) { + #else // PROTOBUF_FORCE_COPY_IN_SWAP + if (GetOwningArena() == other->GetOwningArena()) { + #endif // !PROTOBUF_FORCE_COPY_IN_SWAP + InternalSwap(other); + } else { + ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(ExtensionRangeOptions* other) { + if (other == this) return; + GOOGLE_DCHECK(GetOwningArena() == other->GetOwningArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + ExtensionRangeOptions* New(::PROTOBUF_NAMESPACE_ID::Arena* arena = nullptr) const final { + return CreateMaybeMessage<ExtensionRangeOptions>(arena); + } + using ::PROTOBUF_NAMESPACE_ID::Message::CopyFrom; + void CopyFrom(const ExtensionRangeOptions& from); + using ::PROTOBUF_NAMESPACE_ID::Message::MergeFrom; + void MergeFrom( const ExtensionRangeOptions& from) { + ExtensionRangeOptions::MergeImpl(*this, from); + } + private: + static void MergeImpl(::PROTOBUF_NAMESPACE_ID::Message& to_msg, const ::PROTOBUF_NAMESPACE_ID::Message& from_msg); + public: + PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + bool IsInitialized() const final; + + size_t ByteSizeLong() const final; + const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final; + uint8_t* _InternalSerialize( + uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final; + int GetCachedSize() const final { return _impl_._cached_size_.Get(); } + + private: + void SharedCtor(::PROTOBUF_NAMESPACE_ID::Arena* arena, bool is_message_owned); + void SharedDtor(); + void SetCachedSize(int size) const final; + void InternalSwap(ExtensionRangeOptions* other); + + private: + friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata; + static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() { + return "google.protobuf.ExtensionRangeOptions"; + } + protected: + explicit ExtensionRangeOptions(::PROTOBUF_NAMESPACE_ID::Arena* arena, + bool is_message_owned = false); + public: + + static const ClassData _class_data_; + const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*GetClassData() const final; + + ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final; + + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + + enum : int { + kUninterpretedOptionFieldNumber = 999, + }; + // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; + int uninterpreted_option_size() const; + private: + int _internal_uninterpreted_option_size() const; + public: + void clear_uninterpreted_option(); + ::PROTOBUF_NAMESPACE_ID::UninterpretedOption* mutable_uninterpreted_option(int index); + ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::UninterpretedOption >* + mutable_uninterpreted_option(); + private: + const ::PROTOBUF_NAMESPACE_ID::UninterpretedOption& _internal_uninterpreted_option(int index) const; + ::PROTOBUF_NAMESPACE_ID::UninterpretedOption* _internal_add_uninterpreted_option(); + public: + const ::PROTOBUF_NAMESPACE_ID::UninterpretedOption& uninterpreted_option(int index) const; + ::PROTOBUF_NAMESPACE_ID::UninterpretedOption* add_uninterpreted_option(); + const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::UninterpretedOption >& + uninterpreted_option() const; + + + template <typename _proto_TypeTraits, + ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type, + bool _is_packed> + inline bool HasExtension( + const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier< + ExtensionRangeOptions, _proto_TypeTraits, _field_type, _is_packed>& id) const { + + return _impl_._extensions_.Has(id.number()); + } + + template <typename _proto_TypeTraits, + ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type, + bool _is_packed> + inline void ClearExtension( + const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier< + ExtensionRangeOptions, _proto_TypeTraits, _field_type, _is_packed>& id) { + _impl_._extensions_.ClearExtension(id.number()); + + } + + template <typename _proto_TypeTraits, + ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type, + bool _is_packed> + inline int ExtensionSize( + const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier< + ExtensionRangeOptions, _proto_TypeTraits, _field_type, _is_packed>& id) const { + + return _impl_._extensions_.ExtensionSize(id.number()); + } + + template <typename _proto_TypeTraits, + ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type, + bool _is_packed> + inline typename _proto_TypeTraits::Singular::ConstType GetExtension( + const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier< + ExtensionRangeOptions, _proto_TypeTraits, _field_type, _is_packed>& id) const { + + return _proto_TypeTraits::Get(id.number(), _impl_._extensions_, + id.default_value()); + } + + template <typename _proto_TypeTraits, + ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type, + bool _is_packed> + inline typename _proto_TypeTraits::Singular::MutableType MutableExtension( + const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier< + ExtensionRangeOptions, _proto_TypeTraits, _field_type, _is_packed>& id) { + + return _proto_TypeTraits::Mutable(id.number(), _field_type, + &_impl_._extensions_); + } + + template <typename _proto_TypeTraits, + ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type, + bool _is_packed> + inline void SetExtension( + const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier< + ExtensionRangeOptions, _proto_TypeTraits, _field_type, _is_packed>& id, + typename _proto_TypeTraits::Singular::ConstType value) { + _proto_TypeTraits::Set(id.number(), _field_type, value, &_impl_._extensions_); + + } + + template <typename _proto_TypeTraits, + ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type, + bool _is_packed> + inline void SetAllocatedExtension( + const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier< + ExtensionRangeOptions, _proto_TypeTraits, _field_type, _is_packed>& id, + typename _proto_TypeTraits::Singular::MutableType value) { + _proto_TypeTraits::SetAllocated(id.number(), _field_type, value, + &_impl_._extensions_); + + } + template <typename _proto_TypeTraits, + ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type, + bool _is_packed> + inline void UnsafeArenaSetAllocatedExtension( + const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier< + ExtensionRangeOptions, _proto_TypeTraits, _field_type, _is_packed>& id, + typename _proto_TypeTraits::Singular::MutableType value) { + _proto_TypeTraits::UnsafeArenaSetAllocated(id.number(), _field_type, + value, &_impl_._extensions_); + + } + template <typename _proto_TypeTraits, + ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type, + bool _is_packed> + PROTOBUF_NODISCARD inline + typename _proto_TypeTraits::Singular::MutableType + ReleaseExtension( + const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier< + ExtensionRangeOptions, _proto_TypeTraits, _field_type, _is_packed>& id) { + + return _proto_TypeTraits::Release(id.number(), _field_type, + &_impl_._extensions_); + } + template <typename _proto_TypeTraits, + ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type, + bool _is_packed> + inline typename _proto_TypeTraits::Singular::MutableType + UnsafeArenaReleaseExtension( + const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier< + ExtensionRangeOptions, _proto_TypeTraits, _field_type, _is_packed>& id) { + + return _proto_TypeTraits::UnsafeArenaRelease(id.number(), _field_type, + &_impl_._extensions_); + } + + template <typename _proto_TypeTraits, + ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type, + bool _is_packed> + inline typename _proto_TypeTraits::Repeated::ConstType GetExtension( + const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier< + ExtensionRangeOptions, _proto_TypeTraits, _field_type, _is_packed>& id, + int index) const { + + return _proto_TypeTraits::Get(id.number(), _impl_._extensions_, index); + } + + template <typename _proto_TypeTraits, + ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type, + bool _is_packed> + inline typename _proto_TypeTraits::Repeated::MutableType MutableExtension( + const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier< + ExtensionRangeOptions, _proto_TypeTraits, _field_type, _is_packed>& id, + int index) { + + return _proto_TypeTraits::Mutable(id.number(), index, &_impl_._extensions_); + } + + template <typename _proto_TypeTraits, + ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type, + bool _is_packed> + inline void SetExtension( + const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier< + ExtensionRangeOptions, _proto_TypeTraits, _field_type, _is_packed>& id, + int index, typename _proto_TypeTraits::Repeated::ConstType value) { + _proto_TypeTraits::Set(id.number(), index, value, &_impl_._extensions_); + + } + + template <typename _proto_TypeTraits, + ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type, + bool _is_packed> + inline typename _proto_TypeTraits::Repeated::MutableType AddExtension( + const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier< + ExtensionRangeOptions, _proto_TypeTraits, _field_type, _is_packed>& id) { + typename _proto_TypeTraits::Repeated::MutableType to_add = + _proto_TypeTraits::Add(id.number(), _field_type, &_impl_._extensions_); + + return to_add; + } + + template <typename _proto_TypeTraits, + ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type, + bool _is_packed> + inline void AddExtension( + const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier< + ExtensionRangeOptions, _proto_TypeTraits, _field_type, _is_packed>& id, + typename _proto_TypeTraits::Repeated::ConstType value) { + _proto_TypeTraits::Add(id.number(), _field_type, _is_packed, value, + &_impl_._extensions_); + + } + + template <typename _proto_TypeTraits, + ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type, + bool _is_packed> + inline const typename _proto_TypeTraits::Repeated::RepeatedFieldType& + GetRepeatedExtension( + const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier< + ExtensionRangeOptions, _proto_TypeTraits, _field_type, _is_packed>& id) const { + + return _proto_TypeTraits::GetRepeated(id.number(), _impl_._extensions_); + } + + template <typename _proto_TypeTraits, + ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type, + bool _is_packed> + inline typename _proto_TypeTraits::Repeated::RepeatedFieldType* + MutableRepeatedExtension( + const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier< + ExtensionRangeOptions, _proto_TypeTraits, _field_type, _is_packed>& id) { + + return _proto_TypeTraits::MutableRepeated(id.number(), _field_type, + _is_packed, &_impl_._extensions_); + } + + // @@protoc_insertion_point(class_scope:google.protobuf.ExtensionRangeOptions) + private: + class _Internal; + + template <typename T> friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper; + typedef void InternalArenaConstructable_; + typedef void DestructorSkippable_; + struct Impl_ { + ::PROTOBUF_NAMESPACE_ID::internal::ExtensionSet _extensions_; + + ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::UninterpretedOption > uninterpreted_option_; + mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_; + }; + union { Impl_ _impl_; }; + friend struct ::TableStruct_google_2fprotobuf_2fdescriptor_2eproto; +}; +// ------------------------------------------------------------------- + +class PROTOBUF_EXPORT FieldDescriptorProto final : + public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.FieldDescriptorProto) */ { + public: + inline FieldDescriptorProto() : FieldDescriptorProto(nullptr) {} + ~FieldDescriptorProto() override; + explicit PROTOBUF_CONSTEXPR FieldDescriptorProto(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized); + + FieldDescriptorProto(const FieldDescriptorProto& from); + FieldDescriptorProto(FieldDescriptorProto&& from) noexcept + : FieldDescriptorProto() { + *this = ::std::move(from); + } + + inline FieldDescriptorProto& operator=(const FieldDescriptorProto& from) { + CopyFrom(from); + return *this; + } + inline FieldDescriptorProto& operator=(FieldDescriptorProto&& from) noexcept { + if (this == &from) return *this; + if (GetOwningArena() == from.GetOwningArena() + #ifdef PROTOBUF_FORCE_COPY_IN_MOVE + && GetOwningArena() != nullptr + #endif // !PROTOBUF_FORCE_COPY_IN_MOVE + ) { + InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + inline const ::PROTOBUF_NAMESPACE_ID::UnknownFieldSet& unknown_fields() const { + return _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance); + } + inline ::PROTOBUF_NAMESPACE_ID::UnknownFieldSet* mutable_unknown_fields() { + return _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); + } + + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* descriptor() { + return GetDescriptor(); + } + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() { + return default_instance().GetMetadata().descriptor; + } + static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() { + return default_instance().GetMetadata().reflection; + } + static const FieldDescriptorProto& default_instance() { + return *internal_default_instance(); + } + static inline const FieldDescriptorProto* internal_default_instance() { + return reinterpret_cast<const FieldDescriptorProto*>( + &_FieldDescriptorProto_default_instance_); + } + static constexpr int kIndexInFileMessages = + 6; + + friend void swap(FieldDescriptorProto& a, FieldDescriptorProto& b) { + a.Swap(&b); + } + inline void Swap(FieldDescriptorProto* other) { + if (other == this) return; + #ifdef PROTOBUF_FORCE_COPY_IN_SWAP + if (GetOwningArena() != nullptr && + GetOwningArena() == other->GetOwningArena()) { + #else // PROTOBUF_FORCE_COPY_IN_SWAP + if (GetOwningArena() == other->GetOwningArena()) { + #endif // !PROTOBUF_FORCE_COPY_IN_SWAP + InternalSwap(other); + } else { + ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(FieldDescriptorProto* other) { + if (other == this) return; + GOOGLE_DCHECK(GetOwningArena() == other->GetOwningArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + FieldDescriptorProto* New(::PROTOBUF_NAMESPACE_ID::Arena* arena = nullptr) const final { + return CreateMaybeMessage<FieldDescriptorProto>(arena); + } + using ::PROTOBUF_NAMESPACE_ID::Message::CopyFrom; + void CopyFrom(const FieldDescriptorProto& from); + using ::PROTOBUF_NAMESPACE_ID::Message::MergeFrom; + void MergeFrom( const FieldDescriptorProto& from) { + FieldDescriptorProto::MergeImpl(*this, from); + } + private: + static void MergeImpl(::PROTOBUF_NAMESPACE_ID::Message& to_msg, const ::PROTOBUF_NAMESPACE_ID::Message& from_msg); + public: + PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + bool IsInitialized() const final; + + size_t ByteSizeLong() const final; + const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final; + uint8_t* _InternalSerialize( + uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final; + int GetCachedSize() const final { return _impl_._cached_size_.Get(); } + + private: + void SharedCtor(::PROTOBUF_NAMESPACE_ID::Arena* arena, bool is_message_owned); + void SharedDtor(); + void SetCachedSize(int size) const final; + void InternalSwap(FieldDescriptorProto* other); + + private: + friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata; + static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() { + return "google.protobuf.FieldDescriptorProto"; + } + protected: + explicit FieldDescriptorProto(::PROTOBUF_NAMESPACE_ID::Arena* arena, + bool is_message_owned = false); + public: + + static const ClassData _class_data_; + const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*GetClassData() const final; + + ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final; + + // nested types ---------------------------------------------------- + + typedef FieldDescriptorProto_Type Type; + static constexpr Type TYPE_DOUBLE = + FieldDescriptorProto_Type_TYPE_DOUBLE; + static constexpr Type TYPE_FLOAT = + FieldDescriptorProto_Type_TYPE_FLOAT; + static constexpr Type TYPE_INT64 = + FieldDescriptorProto_Type_TYPE_INT64; + static constexpr Type TYPE_UINT64 = + FieldDescriptorProto_Type_TYPE_UINT64; + static constexpr Type TYPE_INT32 = + FieldDescriptorProto_Type_TYPE_INT32; + static constexpr Type TYPE_FIXED64 = + FieldDescriptorProto_Type_TYPE_FIXED64; + static constexpr Type TYPE_FIXED32 = + FieldDescriptorProto_Type_TYPE_FIXED32; + static constexpr Type TYPE_BOOL = + FieldDescriptorProto_Type_TYPE_BOOL; + static constexpr Type TYPE_STRING = + FieldDescriptorProto_Type_TYPE_STRING; + static constexpr Type TYPE_GROUP = + FieldDescriptorProto_Type_TYPE_GROUP; + static constexpr Type TYPE_MESSAGE = + FieldDescriptorProto_Type_TYPE_MESSAGE; + static constexpr Type TYPE_BYTES = + FieldDescriptorProto_Type_TYPE_BYTES; + static constexpr Type TYPE_UINT32 = + FieldDescriptorProto_Type_TYPE_UINT32; + static constexpr Type TYPE_ENUM = + FieldDescriptorProto_Type_TYPE_ENUM; + static constexpr Type TYPE_SFIXED32 = + FieldDescriptorProto_Type_TYPE_SFIXED32; + static constexpr Type TYPE_SFIXED64 = + FieldDescriptorProto_Type_TYPE_SFIXED64; + static constexpr Type TYPE_SINT32 = + FieldDescriptorProto_Type_TYPE_SINT32; + static constexpr Type TYPE_SINT64 = + FieldDescriptorProto_Type_TYPE_SINT64; + static inline bool Type_IsValid(int value) { + return FieldDescriptorProto_Type_IsValid(value); + } + static constexpr Type Type_MIN = + FieldDescriptorProto_Type_Type_MIN; + static constexpr Type Type_MAX = + FieldDescriptorProto_Type_Type_MAX; + static constexpr int Type_ARRAYSIZE = + FieldDescriptorProto_Type_Type_ARRAYSIZE; + static inline const ::PROTOBUF_NAMESPACE_ID::EnumDescriptor* + Type_descriptor() { + return FieldDescriptorProto_Type_descriptor(); + } + template<typename T> + static inline const std::string& Type_Name(T enum_t_value) { + static_assert(::std::is_same<T, Type>::value || + ::std::is_integral<T>::value, + "Incorrect type passed to function Type_Name."); + return FieldDescriptorProto_Type_Name(enum_t_value); + } + static inline bool Type_Parse(::PROTOBUF_NAMESPACE_ID::ConstStringParam name, + Type* value) { + return FieldDescriptorProto_Type_Parse(name, value); + } + + typedef FieldDescriptorProto_Label Label; + static constexpr Label LABEL_OPTIONAL = + FieldDescriptorProto_Label_LABEL_OPTIONAL; + static constexpr Label LABEL_REQUIRED = + FieldDescriptorProto_Label_LABEL_REQUIRED; + static constexpr Label LABEL_REPEATED = + FieldDescriptorProto_Label_LABEL_REPEATED; + static inline bool Label_IsValid(int value) { + return FieldDescriptorProto_Label_IsValid(value); + } + static constexpr Label Label_MIN = + FieldDescriptorProto_Label_Label_MIN; + static constexpr Label Label_MAX = + FieldDescriptorProto_Label_Label_MAX; + static constexpr int Label_ARRAYSIZE = + FieldDescriptorProto_Label_Label_ARRAYSIZE; + static inline const ::PROTOBUF_NAMESPACE_ID::EnumDescriptor* + Label_descriptor() { + return FieldDescriptorProto_Label_descriptor(); + } + template<typename T> + static inline const std::string& Label_Name(T enum_t_value) { + static_assert(::std::is_same<T, Label>::value || + ::std::is_integral<T>::value, + "Incorrect type passed to function Label_Name."); + return FieldDescriptorProto_Label_Name(enum_t_value); + } + static inline bool Label_Parse(::PROTOBUF_NAMESPACE_ID::ConstStringParam name, + Label* value) { + return FieldDescriptorProto_Label_Parse(name, value); + } + + // accessors ------------------------------------------------------- + + enum : int { + kNameFieldNumber = 1, + kExtendeeFieldNumber = 2, + kTypeNameFieldNumber = 6, + kDefaultValueFieldNumber = 7, + kJsonNameFieldNumber = 10, + kOptionsFieldNumber = 8, + kNumberFieldNumber = 3, + kOneofIndexFieldNumber = 9, + kProto3OptionalFieldNumber = 17, + kLabelFieldNumber = 4, + kTypeFieldNumber = 5, + }; + // optional string name = 1; + bool has_name() const; + private: + bool _internal_has_name() const; + public: + void clear_name(); + const std::string& name() const; + template <typename ArgT0 = const std::string&, typename... ArgT> + void set_name(ArgT0&& arg0, ArgT... args); + std::string* mutable_name(); + PROTOBUF_NODISCARD std::string* release_name(); + void set_allocated_name(std::string* name); + private: + const std::string& _internal_name() const; + inline PROTOBUF_ALWAYS_INLINE void _internal_set_name(const std::string& value); + std::string* _internal_mutable_name(); + public: + + // optional string extendee = 2; + bool has_extendee() const; + private: + bool _internal_has_extendee() const; + public: + void clear_extendee(); + const std::string& extendee() const; + template <typename ArgT0 = const std::string&, typename... ArgT> + void set_extendee(ArgT0&& arg0, ArgT... args); + std::string* mutable_extendee(); + PROTOBUF_NODISCARD std::string* release_extendee(); + void set_allocated_extendee(std::string* extendee); + private: + const std::string& _internal_extendee() const; + inline PROTOBUF_ALWAYS_INLINE void _internal_set_extendee(const std::string& value); + std::string* _internal_mutable_extendee(); + public: + + // optional string type_name = 6; + bool has_type_name() const; + private: + bool _internal_has_type_name() const; + public: + void clear_type_name(); + const std::string& type_name() const; + template <typename ArgT0 = const std::string&, typename... ArgT> + void set_type_name(ArgT0&& arg0, ArgT... args); + std::string* mutable_type_name(); + PROTOBUF_NODISCARD std::string* release_type_name(); + void set_allocated_type_name(std::string* type_name); + private: + const std::string& _internal_type_name() const; + inline PROTOBUF_ALWAYS_INLINE void _internal_set_type_name(const std::string& value); + std::string* _internal_mutable_type_name(); + public: + + // optional string default_value = 7; + bool has_default_value() const; + private: + bool _internal_has_default_value() const; + public: + void clear_default_value(); + const std::string& default_value() const; + template <typename ArgT0 = const std::string&, typename... ArgT> + void set_default_value(ArgT0&& arg0, ArgT... args); + std::string* mutable_default_value(); + PROTOBUF_NODISCARD std::string* release_default_value(); + void set_allocated_default_value(std::string* default_value); + private: + const std::string& _internal_default_value() const; + inline PROTOBUF_ALWAYS_INLINE void _internal_set_default_value(const std::string& value); + std::string* _internal_mutable_default_value(); + public: + + // optional string json_name = 10; + bool has_json_name() const; + private: + bool _internal_has_json_name() const; + public: + void clear_json_name(); + const std::string& json_name() const; + template <typename ArgT0 = const std::string&, typename... ArgT> + void set_json_name(ArgT0&& arg0, ArgT... args); + std::string* mutable_json_name(); + PROTOBUF_NODISCARD std::string* release_json_name(); + void set_allocated_json_name(std::string* json_name); + private: + const std::string& _internal_json_name() const; + inline PROTOBUF_ALWAYS_INLINE void _internal_set_json_name(const std::string& value); + std::string* _internal_mutable_json_name(); + public: + + // optional .google.protobuf.FieldOptions options = 8; + bool has_options() const; + private: + bool _internal_has_options() const; + public: + void clear_options(); + const ::PROTOBUF_NAMESPACE_ID::FieldOptions& options() const; + PROTOBUF_NODISCARD ::PROTOBUF_NAMESPACE_ID::FieldOptions* release_options(); + ::PROTOBUF_NAMESPACE_ID::FieldOptions* mutable_options(); + void set_allocated_options(::PROTOBUF_NAMESPACE_ID::FieldOptions* options); + private: + const ::PROTOBUF_NAMESPACE_ID::FieldOptions& _internal_options() const; + ::PROTOBUF_NAMESPACE_ID::FieldOptions* _internal_mutable_options(); + public: + void unsafe_arena_set_allocated_options( + ::PROTOBUF_NAMESPACE_ID::FieldOptions* options); + ::PROTOBUF_NAMESPACE_ID::FieldOptions* unsafe_arena_release_options(); + + // optional int32 number = 3; + bool has_number() const; + private: + bool _internal_has_number() const; + public: + void clear_number(); + int32_t number() const; + void set_number(int32_t value); + private: + int32_t _internal_number() const; + void _internal_set_number(int32_t value); + public: + + // optional int32 oneof_index = 9; + bool has_oneof_index() const; + private: + bool _internal_has_oneof_index() const; + public: + void clear_oneof_index(); + int32_t oneof_index() const; + void set_oneof_index(int32_t value); + private: + int32_t _internal_oneof_index() const; + void _internal_set_oneof_index(int32_t value); + public: + + // optional bool proto3_optional = 17; + bool has_proto3_optional() const; + private: + bool _internal_has_proto3_optional() const; + public: + void clear_proto3_optional(); + bool proto3_optional() const; + void set_proto3_optional(bool value); + private: + bool _internal_proto3_optional() const; + void _internal_set_proto3_optional(bool value); + public: + + // optional .google.protobuf.FieldDescriptorProto.Label label = 4; + bool has_label() const; + private: + bool _internal_has_label() const; + public: + void clear_label(); + ::PROTOBUF_NAMESPACE_ID::FieldDescriptorProto_Label label() const; + void set_label(::PROTOBUF_NAMESPACE_ID::FieldDescriptorProto_Label value); + private: + ::PROTOBUF_NAMESPACE_ID::FieldDescriptorProto_Label _internal_label() const; + void _internal_set_label(::PROTOBUF_NAMESPACE_ID::FieldDescriptorProto_Label value); + public: + + // optional .google.protobuf.FieldDescriptorProto.Type type = 5; + bool has_type() const; + private: + bool _internal_has_type() const; + public: + void clear_type(); + ::PROTOBUF_NAMESPACE_ID::FieldDescriptorProto_Type type() const; + void set_type(::PROTOBUF_NAMESPACE_ID::FieldDescriptorProto_Type value); + private: + ::PROTOBUF_NAMESPACE_ID::FieldDescriptorProto_Type _internal_type() const; + void _internal_set_type(::PROTOBUF_NAMESPACE_ID::FieldDescriptorProto_Type value); + public: + + // @@protoc_insertion_point(class_scope:google.protobuf.FieldDescriptorProto) + private: + class _Internal; + + template <typename T> friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper; + typedef void InternalArenaConstructable_; + typedef void DestructorSkippable_; + struct Impl_ { + ::PROTOBUF_NAMESPACE_ID::internal::HasBits<1> _has_bits_; + mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_; + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr name_; + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr extendee_; + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr type_name_; + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr default_value_; + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr json_name_; + ::PROTOBUF_NAMESPACE_ID::FieldOptions* options_; + int32_t number_; + int32_t oneof_index_; + bool proto3_optional_; + int label_; + int type_; + }; + union { Impl_ _impl_; }; + friend struct ::TableStruct_google_2fprotobuf_2fdescriptor_2eproto; +}; +// ------------------------------------------------------------------- + +class PROTOBUF_EXPORT OneofDescriptorProto final : + public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.OneofDescriptorProto) */ { + public: + inline OneofDescriptorProto() : OneofDescriptorProto(nullptr) {} + ~OneofDescriptorProto() override; + explicit PROTOBUF_CONSTEXPR OneofDescriptorProto(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized); + + OneofDescriptorProto(const OneofDescriptorProto& from); + OneofDescriptorProto(OneofDescriptorProto&& from) noexcept + : OneofDescriptorProto() { + *this = ::std::move(from); + } + + inline OneofDescriptorProto& operator=(const OneofDescriptorProto& from) { + CopyFrom(from); + return *this; + } + inline OneofDescriptorProto& operator=(OneofDescriptorProto&& from) noexcept { + if (this == &from) return *this; + if (GetOwningArena() == from.GetOwningArena() + #ifdef PROTOBUF_FORCE_COPY_IN_MOVE + && GetOwningArena() != nullptr + #endif // !PROTOBUF_FORCE_COPY_IN_MOVE + ) { + InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + inline const ::PROTOBUF_NAMESPACE_ID::UnknownFieldSet& unknown_fields() const { + return _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance); + } + inline ::PROTOBUF_NAMESPACE_ID::UnknownFieldSet* mutable_unknown_fields() { + return _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); + } + + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* descriptor() { + return GetDescriptor(); + } + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() { + return default_instance().GetMetadata().descriptor; + } + static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() { + return default_instance().GetMetadata().reflection; + } + static const OneofDescriptorProto& default_instance() { + return *internal_default_instance(); + } + static inline const OneofDescriptorProto* internal_default_instance() { + return reinterpret_cast<const OneofDescriptorProto*>( + &_OneofDescriptorProto_default_instance_); + } + static constexpr int kIndexInFileMessages = + 7; + + friend void swap(OneofDescriptorProto& a, OneofDescriptorProto& b) { + a.Swap(&b); + } + inline void Swap(OneofDescriptorProto* other) { + if (other == this) return; + #ifdef PROTOBUF_FORCE_COPY_IN_SWAP + if (GetOwningArena() != nullptr && + GetOwningArena() == other->GetOwningArena()) { + #else // PROTOBUF_FORCE_COPY_IN_SWAP + if (GetOwningArena() == other->GetOwningArena()) { + #endif // !PROTOBUF_FORCE_COPY_IN_SWAP + InternalSwap(other); + } else { + ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(OneofDescriptorProto* other) { + if (other == this) return; + GOOGLE_DCHECK(GetOwningArena() == other->GetOwningArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + OneofDescriptorProto* New(::PROTOBUF_NAMESPACE_ID::Arena* arena = nullptr) const final { + return CreateMaybeMessage<OneofDescriptorProto>(arena); + } + using ::PROTOBUF_NAMESPACE_ID::Message::CopyFrom; + void CopyFrom(const OneofDescriptorProto& from); + using ::PROTOBUF_NAMESPACE_ID::Message::MergeFrom; + void MergeFrom( const OneofDescriptorProto& from) { + OneofDescriptorProto::MergeImpl(*this, from); + } + private: + static void MergeImpl(::PROTOBUF_NAMESPACE_ID::Message& to_msg, const ::PROTOBUF_NAMESPACE_ID::Message& from_msg); + public: + PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + bool IsInitialized() const final; + + size_t ByteSizeLong() const final; + const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final; + uint8_t* _InternalSerialize( + uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final; + int GetCachedSize() const final { return _impl_._cached_size_.Get(); } + + private: + void SharedCtor(::PROTOBUF_NAMESPACE_ID::Arena* arena, bool is_message_owned); + void SharedDtor(); + void SetCachedSize(int size) const final; + void InternalSwap(OneofDescriptorProto* other); + + private: + friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata; + static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() { + return "google.protobuf.OneofDescriptorProto"; + } + protected: + explicit OneofDescriptorProto(::PROTOBUF_NAMESPACE_ID::Arena* arena, + bool is_message_owned = false); + public: + + static const ClassData _class_data_; + const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*GetClassData() const final; + + ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final; + + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + + enum : int { + kNameFieldNumber = 1, + kOptionsFieldNumber = 2, + }; + // optional string name = 1; + bool has_name() const; + private: + bool _internal_has_name() const; + public: + void clear_name(); + const std::string& name() const; + template <typename ArgT0 = const std::string&, typename... ArgT> + void set_name(ArgT0&& arg0, ArgT... args); + std::string* mutable_name(); + PROTOBUF_NODISCARD std::string* release_name(); + void set_allocated_name(std::string* name); + private: + const std::string& _internal_name() const; + inline PROTOBUF_ALWAYS_INLINE void _internal_set_name(const std::string& value); + std::string* _internal_mutable_name(); + public: + + // optional .google.protobuf.OneofOptions options = 2; + bool has_options() const; + private: + bool _internal_has_options() const; + public: + void clear_options(); + const ::PROTOBUF_NAMESPACE_ID::OneofOptions& options() const; + PROTOBUF_NODISCARD ::PROTOBUF_NAMESPACE_ID::OneofOptions* release_options(); + ::PROTOBUF_NAMESPACE_ID::OneofOptions* mutable_options(); + void set_allocated_options(::PROTOBUF_NAMESPACE_ID::OneofOptions* options); + private: + const ::PROTOBUF_NAMESPACE_ID::OneofOptions& _internal_options() const; + ::PROTOBUF_NAMESPACE_ID::OneofOptions* _internal_mutable_options(); + public: + void unsafe_arena_set_allocated_options( + ::PROTOBUF_NAMESPACE_ID::OneofOptions* options); + ::PROTOBUF_NAMESPACE_ID::OneofOptions* unsafe_arena_release_options(); + + // @@protoc_insertion_point(class_scope:google.protobuf.OneofDescriptorProto) + private: + class _Internal; + + template <typename T> friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper; + typedef void InternalArenaConstructable_; + typedef void DestructorSkippable_; + struct Impl_ { + ::PROTOBUF_NAMESPACE_ID::internal::HasBits<1> _has_bits_; + mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_; + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr name_; + ::PROTOBUF_NAMESPACE_ID::OneofOptions* options_; + }; + union { Impl_ _impl_; }; + friend struct ::TableStruct_google_2fprotobuf_2fdescriptor_2eproto; +}; +// ------------------------------------------------------------------- + +class PROTOBUF_EXPORT EnumDescriptorProto_EnumReservedRange final : + public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.EnumDescriptorProto.EnumReservedRange) */ { + public: + inline EnumDescriptorProto_EnumReservedRange() : EnumDescriptorProto_EnumReservedRange(nullptr) {} + ~EnumDescriptorProto_EnumReservedRange() override; + explicit PROTOBUF_CONSTEXPR EnumDescriptorProto_EnumReservedRange(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized); + + EnumDescriptorProto_EnumReservedRange(const EnumDescriptorProto_EnumReservedRange& from); + EnumDescriptorProto_EnumReservedRange(EnumDescriptorProto_EnumReservedRange&& from) noexcept + : EnumDescriptorProto_EnumReservedRange() { + *this = ::std::move(from); + } + + inline EnumDescriptorProto_EnumReservedRange& operator=(const EnumDescriptorProto_EnumReservedRange& from) { + CopyFrom(from); + return *this; + } + inline EnumDescriptorProto_EnumReservedRange& operator=(EnumDescriptorProto_EnumReservedRange&& from) noexcept { + if (this == &from) return *this; + if (GetOwningArena() == from.GetOwningArena() + #ifdef PROTOBUF_FORCE_COPY_IN_MOVE + && GetOwningArena() != nullptr + #endif // !PROTOBUF_FORCE_COPY_IN_MOVE + ) { + InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + inline const ::PROTOBUF_NAMESPACE_ID::UnknownFieldSet& unknown_fields() const { + return _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance); + } + inline ::PROTOBUF_NAMESPACE_ID::UnknownFieldSet* mutable_unknown_fields() { + return _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); + } + + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* descriptor() { + return GetDescriptor(); + } + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() { + return default_instance().GetMetadata().descriptor; + } + static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() { + return default_instance().GetMetadata().reflection; + } + static const EnumDescriptorProto_EnumReservedRange& default_instance() { + return *internal_default_instance(); + } + static inline const EnumDescriptorProto_EnumReservedRange* internal_default_instance() { + return reinterpret_cast<const EnumDescriptorProto_EnumReservedRange*>( + &_EnumDescriptorProto_EnumReservedRange_default_instance_); + } + static constexpr int kIndexInFileMessages = + 8; + + friend void swap(EnumDescriptorProto_EnumReservedRange& a, EnumDescriptorProto_EnumReservedRange& b) { + a.Swap(&b); + } + inline void Swap(EnumDescriptorProto_EnumReservedRange* other) { + if (other == this) return; + #ifdef PROTOBUF_FORCE_COPY_IN_SWAP + if (GetOwningArena() != nullptr && + GetOwningArena() == other->GetOwningArena()) { + #else // PROTOBUF_FORCE_COPY_IN_SWAP + if (GetOwningArena() == other->GetOwningArena()) { + #endif // !PROTOBUF_FORCE_COPY_IN_SWAP + InternalSwap(other); + } else { + ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(EnumDescriptorProto_EnumReservedRange* other) { + if (other == this) return; + GOOGLE_DCHECK(GetOwningArena() == other->GetOwningArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + EnumDescriptorProto_EnumReservedRange* New(::PROTOBUF_NAMESPACE_ID::Arena* arena = nullptr) const final { + return CreateMaybeMessage<EnumDescriptorProto_EnumReservedRange>(arena); + } + using ::PROTOBUF_NAMESPACE_ID::Message::CopyFrom; + void CopyFrom(const EnumDescriptorProto_EnumReservedRange& from); + using ::PROTOBUF_NAMESPACE_ID::Message::MergeFrom; + void MergeFrom( const EnumDescriptorProto_EnumReservedRange& from) { + EnumDescriptorProto_EnumReservedRange::MergeImpl(*this, from); + } + private: + static void MergeImpl(::PROTOBUF_NAMESPACE_ID::Message& to_msg, const ::PROTOBUF_NAMESPACE_ID::Message& from_msg); + public: + PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + bool IsInitialized() const final; + + size_t ByteSizeLong() const final; + const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final; + uint8_t* _InternalSerialize( + uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final; + int GetCachedSize() const final { return _impl_._cached_size_.Get(); } + + private: + void SharedCtor(::PROTOBUF_NAMESPACE_ID::Arena* arena, bool is_message_owned); + void SharedDtor(); + void SetCachedSize(int size) const final; + void InternalSwap(EnumDescriptorProto_EnumReservedRange* other); + + private: + friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata; + static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() { + return "google.protobuf.EnumDescriptorProto.EnumReservedRange"; + } + protected: + explicit EnumDescriptorProto_EnumReservedRange(::PROTOBUF_NAMESPACE_ID::Arena* arena, + bool is_message_owned = false); + public: + + static const ClassData _class_data_; + const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*GetClassData() const final; + + ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final; + + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + + enum : int { + kStartFieldNumber = 1, + kEndFieldNumber = 2, + }; + // optional int32 start = 1; + bool has_start() const; + private: + bool _internal_has_start() const; + public: + void clear_start(); + int32_t start() const; + void set_start(int32_t value); + private: + int32_t _internal_start() const; + void _internal_set_start(int32_t value); + public: + + // optional int32 end = 2; + bool has_end() const; + private: + bool _internal_has_end() const; + public: + void clear_end(); + int32_t end() const; + void set_end(int32_t value); + private: + int32_t _internal_end() const; + void _internal_set_end(int32_t value); + public: + + // @@protoc_insertion_point(class_scope:google.protobuf.EnumDescriptorProto.EnumReservedRange) + private: + class _Internal; + + template <typename T> friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper; + typedef void InternalArenaConstructable_; + typedef void DestructorSkippable_; + struct Impl_ { + ::PROTOBUF_NAMESPACE_ID::internal::HasBits<1> _has_bits_; + mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_; + int32_t start_; + int32_t end_; + }; + union { Impl_ _impl_; }; + friend struct ::TableStruct_google_2fprotobuf_2fdescriptor_2eproto; +}; +// ------------------------------------------------------------------- + +class PROTOBUF_EXPORT EnumDescriptorProto final : + public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.EnumDescriptorProto) */ { + public: + inline EnumDescriptorProto() : EnumDescriptorProto(nullptr) {} + ~EnumDescriptorProto() override; + explicit PROTOBUF_CONSTEXPR EnumDescriptorProto(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized); + + EnumDescriptorProto(const EnumDescriptorProto& from); + EnumDescriptorProto(EnumDescriptorProto&& from) noexcept + : EnumDescriptorProto() { + *this = ::std::move(from); + } + + inline EnumDescriptorProto& operator=(const EnumDescriptorProto& from) { + CopyFrom(from); + return *this; + } + inline EnumDescriptorProto& operator=(EnumDescriptorProto&& from) noexcept { + if (this == &from) return *this; + if (GetOwningArena() == from.GetOwningArena() + #ifdef PROTOBUF_FORCE_COPY_IN_MOVE + && GetOwningArena() != nullptr + #endif // !PROTOBUF_FORCE_COPY_IN_MOVE + ) { + InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + inline const ::PROTOBUF_NAMESPACE_ID::UnknownFieldSet& unknown_fields() const { + return _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance); + } + inline ::PROTOBUF_NAMESPACE_ID::UnknownFieldSet* mutable_unknown_fields() { + return _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); + } + + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* descriptor() { + return GetDescriptor(); + } + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() { + return default_instance().GetMetadata().descriptor; + } + static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() { + return default_instance().GetMetadata().reflection; + } + static const EnumDescriptorProto& default_instance() { + return *internal_default_instance(); + } + static inline const EnumDescriptorProto* internal_default_instance() { + return reinterpret_cast<const EnumDescriptorProto*>( + &_EnumDescriptorProto_default_instance_); + } + static constexpr int kIndexInFileMessages = + 9; + + friend void swap(EnumDescriptorProto& a, EnumDescriptorProto& b) { + a.Swap(&b); + } + inline void Swap(EnumDescriptorProto* other) { + if (other == this) return; + #ifdef PROTOBUF_FORCE_COPY_IN_SWAP + if (GetOwningArena() != nullptr && + GetOwningArena() == other->GetOwningArena()) { + #else // PROTOBUF_FORCE_COPY_IN_SWAP + if (GetOwningArena() == other->GetOwningArena()) { + #endif // !PROTOBUF_FORCE_COPY_IN_SWAP + InternalSwap(other); + } else { + ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(EnumDescriptorProto* other) { + if (other == this) return; + GOOGLE_DCHECK(GetOwningArena() == other->GetOwningArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + EnumDescriptorProto* New(::PROTOBUF_NAMESPACE_ID::Arena* arena = nullptr) const final { + return CreateMaybeMessage<EnumDescriptorProto>(arena); + } + using ::PROTOBUF_NAMESPACE_ID::Message::CopyFrom; + void CopyFrom(const EnumDescriptorProto& from); + using ::PROTOBUF_NAMESPACE_ID::Message::MergeFrom; + void MergeFrom( const EnumDescriptorProto& from) { + EnumDescriptorProto::MergeImpl(*this, from); + } + private: + static void MergeImpl(::PROTOBUF_NAMESPACE_ID::Message& to_msg, const ::PROTOBUF_NAMESPACE_ID::Message& from_msg); + public: + PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + bool IsInitialized() const final; + + size_t ByteSizeLong() const final; + const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final; + uint8_t* _InternalSerialize( + uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final; + int GetCachedSize() const final { return _impl_._cached_size_.Get(); } + + private: + void SharedCtor(::PROTOBUF_NAMESPACE_ID::Arena* arena, bool is_message_owned); + void SharedDtor(); + void SetCachedSize(int size) const final; + void InternalSwap(EnumDescriptorProto* other); + + private: + friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata; + static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() { + return "google.protobuf.EnumDescriptorProto"; + } + protected: + explicit EnumDescriptorProto(::PROTOBUF_NAMESPACE_ID::Arena* arena, + bool is_message_owned = false); + public: + + static const ClassData _class_data_; + const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*GetClassData() const final; + + ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final; + + // nested types ---------------------------------------------------- + + typedef EnumDescriptorProto_EnumReservedRange EnumReservedRange; + + // accessors ------------------------------------------------------- + + enum : int { + kValueFieldNumber = 2, + kReservedRangeFieldNumber = 4, + kReservedNameFieldNumber = 5, + kNameFieldNumber = 1, + kOptionsFieldNumber = 3, + }; + // repeated .google.protobuf.EnumValueDescriptorProto value = 2; + int value_size() const; + private: + int _internal_value_size() const; + public: + void clear_value(); + ::PROTOBUF_NAMESPACE_ID::EnumValueDescriptorProto* mutable_value(int index); + ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::EnumValueDescriptorProto >* + mutable_value(); + private: + const ::PROTOBUF_NAMESPACE_ID::EnumValueDescriptorProto& _internal_value(int index) const; + ::PROTOBUF_NAMESPACE_ID::EnumValueDescriptorProto* _internal_add_value(); + public: + const ::PROTOBUF_NAMESPACE_ID::EnumValueDescriptorProto& value(int index) const; + ::PROTOBUF_NAMESPACE_ID::EnumValueDescriptorProto* add_value(); + const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::EnumValueDescriptorProto >& + value() const; + + // repeated .google.protobuf.EnumDescriptorProto.EnumReservedRange reserved_range = 4; + int reserved_range_size() const; + private: + int _internal_reserved_range_size() const; + public: + void clear_reserved_range(); + ::PROTOBUF_NAMESPACE_ID::EnumDescriptorProto_EnumReservedRange* mutable_reserved_range(int index); + ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::EnumDescriptorProto_EnumReservedRange >* + mutable_reserved_range(); + private: + const ::PROTOBUF_NAMESPACE_ID::EnumDescriptorProto_EnumReservedRange& _internal_reserved_range(int index) const; + ::PROTOBUF_NAMESPACE_ID::EnumDescriptorProto_EnumReservedRange* _internal_add_reserved_range(); + public: + const ::PROTOBUF_NAMESPACE_ID::EnumDescriptorProto_EnumReservedRange& reserved_range(int index) const; + ::PROTOBUF_NAMESPACE_ID::EnumDescriptorProto_EnumReservedRange* add_reserved_range(); + const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::EnumDescriptorProto_EnumReservedRange >& + reserved_range() const; + + // repeated string reserved_name = 5; + int reserved_name_size() const; + private: + int _internal_reserved_name_size() const; + public: + void clear_reserved_name(); + const std::string& reserved_name(int index) const; + std::string* mutable_reserved_name(int index); + void set_reserved_name(int index, const std::string& value); + void set_reserved_name(int index, std::string&& value); + void set_reserved_name(int index, const char* value); + void set_reserved_name(int index, const char* value, size_t size); + std::string* add_reserved_name(); + void add_reserved_name(const std::string& value); + void add_reserved_name(std::string&& value); + void add_reserved_name(const char* value); + void add_reserved_name(const char* value, size_t size); + const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField<std::string>& reserved_name() const; + ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField<std::string>* mutable_reserved_name(); + private: + const std::string& _internal_reserved_name(int index) const; + std::string* _internal_add_reserved_name(); + public: + + // optional string name = 1; + bool has_name() const; + private: + bool _internal_has_name() const; + public: + void clear_name(); + const std::string& name() const; + template <typename ArgT0 = const std::string&, typename... ArgT> + void set_name(ArgT0&& arg0, ArgT... args); + std::string* mutable_name(); + PROTOBUF_NODISCARD std::string* release_name(); + void set_allocated_name(std::string* name); + private: + const std::string& _internal_name() const; + inline PROTOBUF_ALWAYS_INLINE void _internal_set_name(const std::string& value); + std::string* _internal_mutable_name(); + public: + + // optional .google.protobuf.EnumOptions options = 3; + bool has_options() const; + private: + bool _internal_has_options() const; + public: + void clear_options(); + const ::PROTOBUF_NAMESPACE_ID::EnumOptions& options() const; + PROTOBUF_NODISCARD ::PROTOBUF_NAMESPACE_ID::EnumOptions* release_options(); + ::PROTOBUF_NAMESPACE_ID::EnumOptions* mutable_options(); + void set_allocated_options(::PROTOBUF_NAMESPACE_ID::EnumOptions* options); + private: + const ::PROTOBUF_NAMESPACE_ID::EnumOptions& _internal_options() const; + ::PROTOBUF_NAMESPACE_ID::EnumOptions* _internal_mutable_options(); + public: + void unsafe_arena_set_allocated_options( + ::PROTOBUF_NAMESPACE_ID::EnumOptions* options); + ::PROTOBUF_NAMESPACE_ID::EnumOptions* unsafe_arena_release_options(); + + // @@protoc_insertion_point(class_scope:google.protobuf.EnumDescriptorProto) + private: + class _Internal; + + template <typename T> friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper; + typedef void InternalArenaConstructable_; + typedef void DestructorSkippable_; + struct Impl_ { + ::PROTOBUF_NAMESPACE_ID::internal::HasBits<1> _has_bits_; + mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_; + ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::EnumValueDescriptorProto > value_; + ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::EnumDescriptorProto_EnumReservedRange > reserved_range_; + ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField<std::string> reserved_name_; + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr name_; + ::PROTOBUF_NAMESPACE_ID::EnumOptions* options_; + }; + union { Impl_ _impl_; }; + friend struct ::TableStruct_google_2fprotobuf_2fdescriptor_2eproto; +}; +// ------------------------------------------------------------------- + +class PROTOBUF_EXPORT EnumValueDescriptorProto final : + public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.EnumValueDescriptorProto) */ { + public: + inline EnumValueDescriptorProto() : EnumValueDescriptorProto(nullptr) {} + ~EnumValueDescriptorProto() override; + explicit PROTOBUF_CONSTEXPR EnumValueDescriptorProto(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized); + + EnumValueDescriptorProto(const EnumValueDescriptorProto& from); + EnumValueDescriptorProto(EnumValueDescriptorProto&& from) noexcept + : EnumValueDescriptorProto() { + *this = ::std::move(from); + } + + inline EnumValueDescriptorProto& operator=(const EnumValueDescriptorProto& from) { + CopyFrom(from); + return *this; + } + inline EnumValueDescriptorProto& operator=(EnumValueDescriptorProto&& from) noexcept { + if (this == &from) return *this; + if (GetOwningArena() == from.GetOwningArena() + #ifdef PROTOBUF_FORCE_COPY_IN_MOVE + && GetOwningArena() != nullptr + #endif // !PROTOBUF_FORCE_COPY_IN_MOVE + ) { + InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + inline const ::PROTOBUF_NAMESPACE_ID::UnknownFieldSet& unknown_fields() const { + return _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance); + } + inline ::PROTOBUF_NAMESPACE_ID::UnknownFieldSet* mutable_unknown_fields() { + return _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); + } + + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* descriptor() { + return GetDescriptor(); + } + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() { + return default_instance().GetMetadata().descriptor; + } + static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() { + return default_instance().GetMetadata().reflection; + } + static const EnumValueDescriptorProto& default_instance() { + return *internal_default_instance(); + } + static inline const EnumValueDescriptorProto* internal_default_instance() { + return reinterpret_cast<const EnumValueDescriptorProto*>( + &_EnumValueDescriptorProto_default_instance_); + } + static constexpr int kIndexInFileMessages = + 10; + + friend void swap(EnumValueDescriptorProto& a, EnumValueDescriptorProto& b) { + a.Swap(&b); + } + inline void Swap(EnumValueDescriptorProto* other) { + if (other == this) return; + #ifdef PROTOBUF_FORCE_COPY_IN_SWAP + if (GetOwningArena() != nullptr && + GetOwningArena() == other->GetOwningArena()) { + #else // PROTOBUF_FORCE_COPY_IN_SWAP + if (GetOwningArena() == other->GetOwningArena()) { + #endif // !PROTOBUF_FORCE_COPY_IN_SWAP + InternalSwap(other); + } else { + ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(EnumValueDescriptorProto* other) { + if (other == this) return; + GOOGLE_DCHECK(GetOwningArena() == other->GetOwningArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + EnumValueDescriptorProto* New(::PROTOBUF_NAMESPACE_ID::Arena* arena = nullptr) const final { + return CreateMaybeMessage<EnumValueDescriptorProto>(arena); + } + using ::PROTOBUF_NAMESPACE_ID::Message::CopyFrom; + void CopyFrom(const EnumValueDescriptorProto& from); + using ::PROTOBUF_NAMESPACE_ID::Message::MergeFrom; + void MergeFrom( const EnumValueDescriptorProto& from) { + EnumValueDescriptorProto::MergeImpl(*this, from); + } + private: + static void MergeImpl(::PROTOBUF_NAMESPACE_ID::Message& to_msg, const ::PROTOBUF_NAMESPACE_ID::Message& from_msg); + public: + PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + bool IsInitialized() const final; + + size_t ByteSizeLong() const final; + const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final; + uint8_t* _InternalSerialize( + uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final; + int GetCachedSize() const final { return _impl_._cached_size_.Get(); } + + private: + void SharedCtor(::PROTOBUF_NAMESPACE_ID::Arena* arena, bool is_message_owned); + void SharedDtor(); + void SetCachedSize(int size) const final; + void InternalSwap(EnumValueDescriptorProto* other); + + private: + friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata; + static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() { + return "google.protobuf.EnumValueDescriptorProto"; + } + protected: + explicit EnumValueDescriptorProto(::PROTOBUF_NAMESPACE_ID::Arena* arena, + bool is_message_owned = false); + public: + + static const ClassData _class_data_; + const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*GetClassData() const final; + + ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final; + + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + + enum : int { + kNameFieldNumber = 1, + kOptionsFieldNumber = 3, + kNumberFieldNumber = 2, + }; + // optional string name = 1; + bool has_name() const; + private: + bool _internal_has_name() const; + public: + void clear_name(); + const std::string& name() const; + template <typename ArgT0 = const std::string&, typename... ArgT> + void set_name(ArgT0&& arg0, ArgT... args); + std::string* mutable_name(); + PROTOBUF_NODISCARD std::string* release_name(); + void set_allocated_name(std::string* name); + private: + const std::string& _internal_name() const; + inline PROTOBUF_ALWAYS_INLINE void _internal_set_name(const std::string& value); + std::string* _internal_mutable_name(); + public: + + // optional .google.protobuf.EnumValueOptions options = 3; + bool has_options() const; + private: + bool _internal_has_options() const; + public: + void clear_options(); + const ::PROTOBUF_NAMESPACE_ID::EnumValueOptions& options() const; + PROTOBUF_NODISCARD ::PROTOBUF_NAMESPACE_ID::EnumValueOptions* release_options(); + ::PROTOBUF_NAMESPACE_ID::EnumValueOptions* mutable_options(); + void set_allocated_options(::PROTOBUF_NAMESPACE_ID::EnumValueOptions* options); + private: + const ::PROTOBUF_NAMESPACE_ID::EnumValueOptions& _internal_options() const; + ::PROTOBUF_NAMESPACE_ID::EnumValueOptions* _internal_mutable_options(); + public: + void unsafe_arena_set_allocated_options( + ::PROTOBUF_NAMESPACE_ID::EnumValueOptions* options); + ::PROTOBUF_NAMESPACE_ID::EnumValueOptions* unsafe_arena_release_options(); + + // optional int32 number = 2; + bool has_number() const; + private: + bool _internal_has_number() const; + public: + void clear_number(); + int32_t number() const; + void set_number(int32_t value); + private: + int32_t _internal_number() const; + void _internal_set_number(int32_t value); + public: + + // @@protoc_insertion_point(class_scope:google.protobuf.EnumValueDescriptorProto) + private: + class _Internal; + + template <typename T> friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper; + typedef void InternalArenaConstructable_; + typedef void DestructorSkippable_; + struct Impl_ { + ::PROTOBUF_NAMESPACE_ID::internal::HasBits<1> _has_bits_; + mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_; + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr name_; + ::PROTOBUF_NAMESPACE_ID::EnumValueOptions* options_; + int32_t number_; + }; + union { Impl_ _impl_; }; + friend struct ::TableStruct_google_2fprotobuf_2fdescriptor_2eproto; +}; +// ------------------------------------------------------------------- + +class PROTOBUF_EXPORT ServiceDescriptorProto final : + public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.ServiceDescriptorProto) */ { + public: + inline ServiceDescriptorProto() : ServiceDescriptorProto(nullptr) {} + ~ServiceDescriptorProto() override; + explicit PROTOBUF_CONSTEXPR ServiceDescriptorProto(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized); + + ServiceDescriptorProto(const ServiceDescriptorProto& from); + ServiceDescriptorProto(ServiceDescriptorProto&& from) noexcept + : ServiceDescriptorProto() { + *this = ::std::move(from); + } + + inline ServiceDescriptorProto& operator=(const ServiceDescriptorProto& from) { + CopyFrom(from); + return *this; + } + inline ServiceDescriptorProto& operator=(ServiceDescriptorProto&& from) noexcept { + if (this == &from) return *this; + if (GetOwningArena() == from.GetOwningArena() + #ifdef PROTOBUF_FORCE_COPY_IN_MOVE + && GetOwningArena() != nullptr + #endif // !PROTOBUF_FORCE_COPY_IN_MOVE + ) { + InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + inline const ::PROTOBUF_NAMESPACE_ID::UnknownFieldSet& unknown_fields() const { + return _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance); + } + inline ::PROTOBUF_NAMESPACE_ID::UnknownFieldSet* mutable_unknown_fields() { + return _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); + } + + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* descriptor() { + return GetDescriptor(); + } + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() { + return default_instance().GetMetadata().descriptor; + } + static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() { + return default_instance().GetMetadata().reflection; + } + static const ServiceDescriptorProto& default_instance() { + return *internal_default_instance(); + } + static inline const ServiceDescriptorProto* internal_default_instance() { + return reinterpret_cast<const ServiceDescriptorProto*>( + &_ServiceDescriptorProto_default_instance_); + } + static constexpr int kIndexInFileMessages = + 11; + + friend void swap(ServiceDescriptorProto& a, ServiceDescriptorProto& b) { + a.Swap(&b); + } + inline void Swap(ServiceDescriptorProto* other) { + if (other == this) return; + #ifdef PROTOBUF_FORCE_COPY_IN_SWAP + if (GetOwningArena() != nullptr && + GetOwningArena() == other->GetOwningArena()) { + #else // PROTOBUF_FORCE_COPY_IN_SWAP + if (GetOwningArena() == other->GetOwningArena()) { + #endif // !PROTOBUF_FORCE_COPY_IN_SWAP + InternalSwap(other); + } else { + ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(ServiceDescriptorProto* other) { + if (other == this) return; + GOOGLE_DCHECK(GetOwningArena() == other->GetOwningArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + ServiceDescriptorProto* New(::PROTOBUF_NAMESPACE_ID::Arena* arena = nullptr) const final { + return CreateMaybeMessage<ServiceDescriptorProto>(arena); + } + using ::PROTOBUF_NAMESPACE_ID::Message::CopyFrom; + void CopyFrom(const ServiceDescriptorProto& from); + using ::PROTOBUF_NAMESPACE_ID::Message::MergeFrom; + void MergeFrom( const ServiceDescriptorProto& from) { + ServiceDescriptorProto::MergeImpl(*this, from); + } + private: + static void MergeImpl(::PROTOBUF_NAMESPACE_ID::Message& to_msg, const ::PROTOBUF_NAMESPACE_ID::Message& from_msg); + public: + PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + bool IsInitialized() const final; + + size_t ByteSizeLong() const final; + const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final; + uint8_t* _InternalSerialize( + uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final; + int GetCachedSize() const final { return _impl_._cached_size_.Get(); } + + private: + void SharedCtor(::PROTOBUF_NAMESPACE_ID::Arena* arena, bool is_message_owned); + void SharedDtor(); + void SetCachedSize(int size) const final; + void InternalSwap(ServiceDescriptorProto* other); + + private: + friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata; + static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() { + return "google.protobuf.ServiceDescriptorProto"; + } + protected: + explicit ServiceDescriptorProto(::PROTOBUF_NAMESPACE_ID::Arena* arena, + bool is_message_owned = false); + public: + + static const ClassData _class_data_; + const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*GetClassData() const final; + + ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final; + + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + + enum : int { + kMethodFieldNumber = 2, + kNameFieldNumber = 1, + kOptionsFieldNumber = 3, + }; + // repeated .google.protobuf.MethodDescriptorProto method = 2; + int method_size() const; + private: + int _internal_method_size() const; + public: + void clear_method(); + ::PROTOBUF_NAMESPACE_ID::MethodDescriptorProto* mutable_method(int index); + ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::MethodDescriptorProto >* + mutable_method(); + private: + const ::PROTOBUF_NAMESPACE_ID::MethodDescriptorProto& _internal_method(int index) const; + ::PROTOBUF_NAMESPACE_ID::MethodDescriptorProto* _internal_add_method(); + public: + const ::PROTOBUF_NAMESPACE_ID::MethodDescriptorProto& method(int index) const; + ::PROTOBUF_NAMESPACE_ID::MethodDescriptorProto* add_method(); + const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::MethodDescriptorProto >& + method() const; + + // optional string name = 1; + bool has_name() const; + private: + bool _internal_has_name() const; + public: + void clear_name(); + const std::string& name() const; + template <typename ArgT0 = const std::string&, typename... ArgT> + void set_name(ArgT0&& arg0, ArgT... args); + std::string* mutable_name(); + PROTOBUF_NODISCARD std::string* release_name(); + void set_allocated_name(std::string* name); + private: + const std::string& _internal_name() const; + inline PROTOBUF_ALWAYS_INLINE void _internal_set_name(const std::string& value); + std::string* _internal_mutable_name(); + public: + + // optional .google.protobuf.ServiceOptions options = 3; + bool has_options() const; + private: + bool _internal_has_options() const; + public: + void clear_options(); + const ::PROTOBUF_NAMESPACE_ID::ServiceOptions& options() const; + PROTOBUF_NODISCARD ::PROTOBUF_NAMESPACE_ID::ServiceOptions* release_options(); + ::PROTOBUF_NAMESPACE_ID::ServiceOptions* mutable_options(); + void set_allocated_options(::PROTOBUF_NAMESPACE_ID::ServiceOptions* options); + private: + const ::PROTOBUF_NAMESPACE_ID::ServiceOptions& _internal_options() const; + ::PROTOBUF_NAMESPACE_ID::ServiceOptions* _internal_mutable_options(); + public: + void unsafe_arena_set_allocated_options( + ::PROTOBUF_NAMESPACE_ID::ServiceOptions* options); + ::PROTOBUF_NAMESPACE_ID::ServiceOptions* unsafe_arena_release_options(); + + // @@protoc_insertion_point(class_scope:google.protobuf.ServiceDescriptorProto) + private: + class _Internal; + + template <typename T> friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper; + typedef void InternalArenaConstructable_; + typedef void DestructorSkippable_; + struct Impl_ { + ::PROTOBUF_NAMESPACE_ID::internal::HasBits<1> _has_bits_; + mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_; + ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::MethodDescriptorProto > method_; + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr name_; + ::PROTOBUF_NAMESPACE_ID::ServiceOptions* options_; + }; + union { Impl_ _impl_; }; + friend struct ::TableStruct_google_2fprotobuf_2fdescriptor_2eproto; +}; +// ------------------------------------------------------------------- + +class PROTOBUF_EXPORT MethodDescriptorProto final : + public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.MethodDescriptorProto) */ { + public: + inline MethodDescriptorProto() : MethodDescriptorProto(nullptr) {} + ~MethodDescriptorProto() override; + explicit PROTOBUF_CONSTEXPR MethodDescriptorProto(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized); + + MethodDescriptorProto(const MethodDescriptorProto& from); + MethodDescriptorProto(MethodDescriptorProto&& from) noexcept + : MethodDescriptorProto() { + *this = ::std::move(from); + } + + inline MethodDescriptorProto& operator=(const MethodDescriptorProto& from) { + CopyFrom(from); + return *this; + } + inline MethodDescriptorProto& operator=(MethodDescriptorProto&& from) noexcept { + if (this == &from) return *this; + if (GetOwningArena() == from.GetOwningArena() + #ifdef PROTOBUF_FORCE_COPY_IN_MOVE + && GetOwningArena() != nullptr + #endif // !PROTOBUF_FORCE_COPY_IN_MOVE + ) { + InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + inline const ::PROTOBUF_NAMESPACE_ID::UnknownFieldSet& unknown_fields() const { + return _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance); + } + inline ::PROTOBUF_NAMESPACE_ID::UnknownFieldSet* mutable_unknown_fields() { + return _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); + } + + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* descriptor() { + return GetDescriptor(); + } + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() { + return default_instance().GetMetadata().descriptor; + } + static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() { + return default_instance().GetMetadata().reflection; + } + static const MethodDescriptorProto& default_instance() { + return *internal_default_instance(); + } + static inline const MethodDescriptorProto* internal_default_instance() { + return reinterpret_cast<const MethodDescriptorProto*>( + &_MethodDescriptorProto_default_instance_); + } + static constexpr int kIndexInFileMessages = + 12; + + friend void swap(MethodDescriptorProto& a, MethodDescriptorProto& b) { + a.Swap(&b); + } + inline void Swap(MethodDescriptorProto* other) { + if (other == this) return; + #ifdef PROTOBUF_FORCE_COPY_IN_SWAP + if (GetOwningArena() != nullptr && + GetOwningArena() == other->GetOwningArena()) { + #else // PROTOBUF_FORCE_COPY_IN_SWAP + if (GetOwningArena() == other->GetOwningArena()) { + #endif // !PROTOBUF_FORCE_COPY_IN_SWAP + InternalSwap(other); + } else { + ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(MethodDescriptorProto* other) { + if (other == this) return; + GOOGLE_DCHECK(GetOwningArena() == other->GetOwningArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + MethodDescriptorProto* New(::PROTOBUF_NAMESPACE_ID::Arena* arena = nullptr) const final { + return CreateMaybeMessage<MethodDescriptorProto>(arena); + } + using ::PROTOBUF_NAMESPACE_ID::Message::CopyFrom; + void CopyFrom(const MethodDescriptorProto& from); + using ::PROTOBUF_NAMESPACE_ID::Message::MergeFrom; + void MergeFrom( const MethodDescriptorProto& from) { + MethodDescriptorProto::MergeImpl(*this, from); + } + private: + static void MergeImpl(::PROTOBUF_NAMESPACE_ID::Message& to_msg, const ::PROTOBUF_NAMESPACE_ID::Message& from_msg); + public: + PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + bool IsInitialized() const final; + + size_t ByteSizeLong() const final; + const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final; + uint8_t* _InternalSerialize( + uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final; + int GetCachedSize() const final { return _impl_._cached_size_.Get(); } + + private: + void SharedCtor(::PROTOBUF_NAMESPACE_ID::Arena* arena, bool is_message_owned); + void SharedDtor(); + void SetCachedSize(int size) const final; + void InternalSwap(MethodDescriptorProto* other); + + private: + friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata; + static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() { + return "google.protobuf.MethodDescriptorProto"; + } + protected: + explicit MethodDescriptorProto(::PROTOBUF_NAMESPACE_ID::Arena* arena, + bool is_message_owned = false); + public: + + static const ClassData _class_data_; + const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*GetClassData() const final; + + ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final; + + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + + enum : int { + kNameFieldNumber = 1, + kInputTypeFieldNumber = 2, + kOutputTypeFieldNumber = 3, + kOptionsFieldNumber = 4, + kClientStreamingFieldNumber = 5, + kServerStreamingFieldNumber = 6, + }; + // optional string name = 1; + bool has_name() const; + private: + bool _internal_has_name() const; + public: + void clear_name(); + const std::string& name() const; + template <typename ArgT0 = const std::string&, typename... ArgT> + void set_name(ArgT0&& arg0, ArgT... args); + std::string* mutable_name(); + PROTOBUF_NODISCARD std::string* release_name(); + void set_allocated_name(std::string* name); + private: + const std::string& _internal_name() const; + inline PROTOBUF_ALWAYS_INLINE void _internal_set_name(const std::string& value); + std::string* _internal_mutable_name(); + public: + + // optional string input_type = 2; + bool has_input_type() const; + private: + bool _internal_has_input_type() const; + public: + void clear_input_type(); + const std::string& input_type() const; + template <typename ArgT0 = const std::string&, typename... ArgT> + void set_input_type(ArgT0&& arg0, ArgT... args); + std::string* mutable_input_type(); + PROTOBUF_NODISCARD std::string* release_input_type(); + void set_allocated_input_type(std::string* input_type); + private: + const std::string& _internal_input_type() const; + inline PROTOBUF_ALWAYS_INLINE void _internal_set_input_type(const std::string& value); + std::string* _internal_mutable_input_type(); + public: + + // optional string output_type = 3; + bool has_output_type() const; + private: + bool _internal_has_output_type() const; + public: + void clear_output_type(); + const std::string& output_type() const; + template <typename ArgT0 = const std::string&, typename... ArgT> + void set_output_type(ArgT0&& arg0, ArgT... args); + std::string* mutable_output_type(); + PROTOBUF_NODISCARD std::string* release_output_type(); + void set_allocated_output_type(std::string* output_type); + private: + const std::string& _internal_output_type() const; + inline PROTOBUF_ALWAYS_INLINE void _internal_set_output_type(const std::string& value); + std::string* _internal_mutable_output_type(); + public: + + // optional .google.protobuf.MethodOptions options = 4; + bool has_options() const; + private: + bool _internal_has_options() const; + public: + void clear_options(); + const ::PROTOBUF_NAMESPACE_ID::MethodOptions& options() const; + PROTOBUF_NODISCARD ::PROTOBUF_NAMESPACE_ID::MethodOptions* release_options(); + ::PROTOBUF_NAMESPACE_ID::MethodOptions* mutable_options(); + void set_allocated_options(::PROTOBUF_NAMESPACE_ID::MethodOptions* options); + private: + const ::PROTOBUF_NAMESPACE_ID::MethodOptions& _internal_options() const; + ::PROTOBUF_NAMESPACE_ID::MethodOptions* _internal_mutable_options(); + public: + void unsafe_arena_set_allocated_options( + ::PROTOBUF_NAMESPACE_ID::MethodOptions* options); + ::PROTOBUF_NAMESPACE_ID::MethodOptions* unsafe_arena_release_options(); + + // optional bool client_streaming = 5 [default = false]; + bool has_client_streaming() const; + private: + bool _internal_has_client_streaming() const; + public: + void clear_client_streaming(); + bool client_streaming() const; + void set_client_streaming(bool value); + private: + bool _internal_client_streaming() const; + void _internal_set_client_streaming(bool value); + public: + + // optional bool server_streaming = 6 [default = false]; + bool has_server_streaming() const; + private: + bool _internal_has_server_streaming() const; + public: + void clear_server_streaming(); + bool server_streaming() const; + void set_server_streaming(bool value); + private: + bool _internal_server_streaming() const; + void _internal_set_server_streaming(bool value); + public: + + // @@protoc_insertion_point(class_scope:google.protobuf.MethodDescriptorProto) + private: + class _Internal; + + template <typename T> friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper; + typedef void InternalArenaConstructable_; + typedef void DestructorSkippable_; + struct Impl_ { + ::PROTOBUF_NAMESPACE_ID::internal::HasBits<1> _has_bits_; + mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_; + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr name_; + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr input_type_; + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr output_type_; + ::PROTOBUF_NAMESPACE_ID::MethodOptions* options_; + bool client_streaming_; + bool server_streaming_; + }; + union { Impl_ _impl_; }; + friend struct ::TableStruct_google_2fprotobuf_2fdescriptor_2eproto; +}; +// ------------------------------------------------------------------- + +class PROTOBUF_EXPORT FileOptions final : + public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.FileOptions) */ { + public: + inline FileOptions() : FileOptions(nullptr) {} + ~FileOptions() override; + explicit PROTOBUF_CONSTEXPR FileOptions(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized); + + FileOptions(const FileOptions& from); + FileOptions(FileOptions&& from) noexcept + : FileOptions() { + *this = ::std::move(from); + } + + inline FileOptions& operator=(const FileOptions& from) { + CopyFrom(from); + return *this; + } + inline FileOptions& operator=(FileOptions&& from) noexcept { + if (this == &from) return *this; + if (GetOwningArena() == from.GetOwningArena() + #ifdef PROTOBUF_FORCE_COPY_IN_MOVE + && GetOwningArena() != nullptr + #endif // !PROTOBUF_FORCE_COPY_IN_MOVE + ) { + InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + inline const ::PROTOBUF_NAMESPACE_ID::UnknownFieldSet& unknown_fields() const { + return _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance); + } + inline ::PROTOBUF_NAMESPACE_ID::UnknownFieldSet* mutable_unknown_fields() { + return _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); + } + + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* descriptor() { + return GetDescriptor(); + } + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() { + return default_instance().GetMetadata().descriptor; + } + static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() { + return default_instance().GetMetadata().reflection; + } + static const FileOptions& default_instance() { + return *internal_default_instance(); + } + static inline const FileOptions* internal_default_instance() { + return reinterpret_cast<const FileOptions*>( + &_FileOptions_default_instance_); + } + static constexpr int kIndexInFileMessages = + 13; + + friend void swap(FileOptions& a, FileOptions& b) { + a.Swap(&b); + } + inline void Swap(FileOptions* other) { + if (other == this) return; + #ifdef PROTOBUF_FORCE_COPY_IN_SWAP + if (GetOwningArena() != nullptr && + GetOwningArena() == other->GetOwningArena()) { + #else // PROTOBUF_FORCE_COPY_IN_SWAP + if (GetOwningArena() == other->GetOwningArena()) { + #endif // !PROTOBUF_FORCE_COPY_IN_SWAP + InternalSwap(other); + } else { + ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(FileOptions* other) { + if (other == this) return; + GOOGLE_DCHECK(GetOwningArena() == other->GetOwningArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + FileOptions* New(::PROTOBUF_NAMESPACE_ID::Arena* arena = nullptr) const final { + return CreateMaybeMessage<FileOptions>(arena); + } + using ::PROTOBUF_NAMESPACE_ID::Message::CopyFrom; + void CopyFrom(const FileOptions& from); + using ::PROTOBUF_NAMESPACE_ID::Message::MergeFrom; + void MergeFrom( const FileOptions& from) { + FileOptions::MergeImpl(*this, from); + } + private: + static void MergeImpl(::PROTOBUF_NAMESPACE_ID::Message& to_msg, const ::PROTOBUF_NAMESPACE_ID::Message& from_msg); + public: + PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + bool IsInitialized() const final; + + size_t ByteSizeLong() const final; + const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final; + uint8_t* _InternalSerialize( + uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final; + int GetCachedSize() const final { return _impl_._cached_size_.Get(); } + + private: + void SharedCtor(::PROTOBUF_NAMESPACE_ID::Arena* arena, bool is_message_owned); + void SharedDtor(); + void SetCachedSize(int size) const final; + void InternalSwap(FileOptions* other); + + private: + friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata; + static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() { + return "google.protobuf.FileOptions"; + } + protected: + explicit FileOptions(::PROTOBUF_NAMESPACE_ID::Arena* arena, + bool is_message_owned = false); + public: + + static const ClassData _class_data_; + const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*GetClassData() const final; + + ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final; + + // nested types ---------------------------------------------------- + + typedef FileOptions_OptimizeMode OptimizeMode; + static constexpr OptimizeMode SPEED = + FileOptions_OptimizeMode_SPEED; + static constexpr OptimizeMode CODE_SIZE = + FileOptions_OptimizeMode_CODE_SIZE; + static constexpr OptimizeMode LITE_RUNTIME = + FileOptions_OptimizeMode_LITE_RUNTIME; + static inline bool OptimizeMode_IsValid(int value) { + return FileOptions_OptimizeMode_IsValid(value); + } + static constexpr OptimizeMode OptimizeMode_MIN = + FileOptions_OptimizeMode_OptimizeMode_MIN; + static constexpr OptimizeMode OptimizeMode_MAX = + FileOptions_OptimizeMode_OptimizeMode_MAX; + static constexpr int OptimizeMode_ARRAYSIZE = + FileOptions_OptimizeMode_OptimizeMode_ARRAYSIZE; + static inline const ::PROTOBUF_NAMESPACE_ID::EnumDescriptor* + OptimizeMode_descriptor() { + return FileOptions_OptimizeMode_descriptor(); + } + template<typename T> + static inline const std::string& OptimizeMode_Name(T enum_t_value) { + static_assert(::std::is_same<T, OptimizeMode>::value || + ::std::is_integral<T>::value, + "Incorrect type passed to function OptimizeMode_Name."); + return FileOptions_OptimizeMode_Name(enum_t_value); + } + static inline bool OptimizeMode_Parse(::PROTOBUF_NAMESPACE_ID::ConstStringParam name, + OptimizeMode* value) { + return FileOptions_OptimizeMode_Parse(name, value); + } + + // accessors ------------------------------------------------------- + + enum : int { + kUninterpretedOptionFieldNumber = 999, + kJavaPackageFieldNumber = 1, + kJavaOuterClassnameFieldNumber = 8, + kGoPackageFieldNumber = 11, + kObjcClassPrefixFieldNumber = 36, + kCsharpNamespaceFieldNumber = 37, + kSwiftPrefixFieldNumber = 39, + kPhpClassPrefixFieldNumber = 40, + kPhpNamespaceFieldNumber = 41, + kPhpMetadataNamespaceFieldNumber = 44, + kRubyPackageFieldNumber = 45, + kJavaMultipleFilesFieldNumber = 10, + kJavaGenerateEqualsAndHashFieldNumber = 20, + kJavaStringCheckUtf8FieldNumber = 27, + kCcGenericServicesFieldNumber = 16, + kJavaGenericServicesFieldNumber = 17, + kPyGenericServicesFieldNumber = 18, + kPhpGenericServicesFieldNumber = 42, + kDeprecatedFieldNumber = 23, + kOptimizeForFieldNumber = 9, + kCcEnableArenasFieldNumber = 31, + }; + // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; + int uninterpreted_option_size() const; + private: + int _internal_uninterpreted_option_size() const; + public: + void clear_uninterpreted_option(); + ::PROTOBUF_NAMESPACE_ID::UninterpretedOption* mutable_uninterpreted_option(int index); + ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::UninterpretedOption >* + mutable_uninterpreted_option(); + private: + const ::PROTOBUF_NAMESPACE_ID::UninterpretedOption& _internal_uninterpreted_option(int index) const; + ::PROTOBUF_NAMESPACE_ID::UninterpretedOption* _internal_add_uninterpreted_option(); + public: + const ::PROTOBUF_NAMESPACE_ID::UninterpretedOption& uninterpreted_option(int index) const; + ::PROTOBUF_NAMESPACE_ID::UninterpretedOption* add_uninterpreted_option(); + const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::UninterpretedOption >& + uninterpreted_option() const; + + // optional string java_package = 1; + bool has_java_package() const; + private: + bool _internal_has_java_package() const; + public: + void clear_java_package(); + const std::string& java_package() const; + template <typename ArgT0 = const std::string&, typename... ArgT> + void set_java_package(ArgT0&& arg0, ArgT... args); + std::string* mutable_java_package(); + PROTOBUF_NODISCARD std::string* release_java_package(); + void set_allocated_java_package(std::string* java_package); + private: + const std::string& _internal_java_package() const; + inline PROTOBUF_ALWAYS_INLINE void _internal_set_java_package(const std::string& value); + std::string* _internal_mutable_java_package(); + public: + + // optional string java_outer_classname = 8; + bool has_java_outer_classname() const; + private: + bool _internal_has_java_outer_classname() const; + public: + void clear_java_outer_classname(); + const std::string& java_outer_classname() const; + template <typename ArgT0 = const std::string&, typename... ArgT> + void set_java_outer_classname(ArgT0&& arg0, ArgT... args); + std::string* mutable_java_outer_classname(); + PROTOBUF_NODISCARD std::string* release_java_outer_classname(); + void set_allocated_java_outer_classname(std::string* java_outer_classname); + private: + const std::string& _internal_java_outer_classname() const; + inline PROTOBUF_ALWAYS_INLINE void _internal_set_java_outer_classname(const std::string& value); + std::string* _internal_mutable_java_outer_classname(); + public: + + // optional string go_package = 11; + bool has_go_package() const; + private: + bool _internal_has_go_package() const; + public: + void clear_go_package(); + const std::string& go_package() const; + template <typename ArgT0 = const std::string&, typename... ArgT> + void set_go_package(ArgT0&& arg0, ArgT... args); + std::string* mutable_go_package(); + PROTOBUF_NODISCARD std::string* release_go_package(); + void set_allocated_go_package(std::string* go_package); + private: + const std::string& _internal_go_package() const; + inline PROTOBUF_ALWAYS_INLINE void _internal_set_go_package(const std::string& value); + std::string* _internal_mutable_go_package(); + public: + + // optional string objc_class_prefix = 36; + bool has_objc_class_prefix() const; + private: + bool _internal_has_objc_class_prefix() const; + public: + void clear_objc_class_prefix(); + const std::string& objc_class_prefix() const; + template <typename ArgT0 = const std::string&, typename... ArgT> + void set_objc_class_prefix(ArgT0&& arg0, ArgT... args); + std::string* mutable_objc_class_prefix(); + PROTOBUF_NODISCARD std::string* release_objc_class_prefix(); + void set_allocated_objc_class_prefix(std::string* objc_class_prefix); + private: + const std::string& _internal_objc_class_prefix() const; + inline PROTOBUF_ALWAYS_INLINE void _internal_set_objc_class_prefix(const std::string& value); + std::string* _internal_mutable_objc_class_prefix(); + public: + + // optional string csharp_namespace = 37; + bool has_csharp_namespace() const; + private: + bool _internal_has_csharp_namespace() const; + public: + void clear_csharp_namespace(); + const std::string& csharp_namespace() const; + template <typename ArgT0 = const std::string&, typename... ArgT> + void set_csharp_namespace(ArgT0&& arg0, ArgT... args); + std::string* mutable_csharp_namespace(); + PROTOBUF_NODISCARD std::string* release_csharp_namespace(); + void set_allocated_csharp_namespace(std::string* csharp_namespace); + private: + const std::string& _internal_csharp_namespace() const; + inline PROTOBUF_ALWAYS_INLINE void _internal_set_csharp_namespace(const std::string& value); + std::string* _internal_mutable_csharp_namespace(); + public: + + // optional string swift_prefix = 39; + bool has_swift_prefix() const; + private: + bool _internal_has_swift_prefix() const; + public: + void clear_swift_prefix(); + const std::string& swift_prefix() const; + template <typename ArgT0 = const std::string&, typename... ArgT> + void set_swift_prefix(ArgT0&& arg0, ArgT... args); + std::string* mutable_swift_prefix(); + PROTOBUF_NODISCARD std::string* release_swift_prefix(); + void set_allocated_swift_prefix(std::string* swift_prefix); + private: + const std::string& _internal_swift_prefix() const; + inline PROTOBUF_ALWAYS_INLINE void _internal_set_swift_prefix(const std::string& value); + std::string* _internal_mutable_swift_prefix(); + public: + + // optional string php_class_prefix = 40; + bool has_php_class_prefix() const; + private: + bool _internal_has_php_class_prefix() const; + public: + void clear_php_class_prefix(); + const std::string& php_class_prefix() const; + template <typename ArgT0 = const std::string&, typename... ArgT> + void set_php_class_prefix(ArgT0&& arg0, ArgT... args); + std::string* mutable_php_class_prefix(); + PROTOBUF_NODISCARD std::string* release_php_class_prefix(); + void set_allocated_php_class_prefix(std::string* php_class_prefix); + private: + const std::string& _internal_php_class_prefix() const; + inline PROTOBUF_ALWAYS_INLINE void _internal_set_php_class_prefix(const std::string& value); + std::string* _internal_mutable_php_class_prefix(); + public: + + // optional string php_namespace = 41; + bool has_php_namespace() const; + private: + bool _internal_has_php_namespace() const; + public: + void clear_php_namespace(); + const std::string& php_namespace() const; + template <typename ArgT0 = const std::string&, typename... ArgT> + void set_php_namespace(ArgT0&& arg0, ArgT... args); + std::string* mutable_php_namespace(); + PROTOBUF_NODISCARD std::string* release_php_namespace(); + void set_allocated_php_namespace(std::string* php_namespace); + private: + const std::string& _internal_php_namespace() const; + inline PROTOBUF_ALWAYS_INLINE void _internal_set_php_namespace(const std::string& value); + std::string* _internal_mutable_php_namespace(); + public: + + // optional string php_metadata_namespace = 44; + bool has_php_metadata_namespace() const; + private: + bool _internal_has_php_metadata_namespace() const; + public: + void clear_php_metadata_namespace(); + const std::string& php_metadata_namespace() const; + template <typename ArgT0 = const std::string&, typename... ArgT> + void set_php_metadata_namespace(ArgT0&& arg0, ArgT... args); + std::string* mutable_php_metadata_namespace(); + PROTOBUF_NODISCARD std::string* release_php_metadata_namespace(); + void set_allocated_php_metadata_namespace(std::string* php_metadata_namespace); + private: + const std::string& _internal_php_metadata_namespace() const; + inline PROTOBUF_ALWAYS_INLINE void _internal_set_php_metadata_namespace(const std::string& value); + std::string* _internal_mutable_php_metadata_namespace(); + public: + + // optional string ruby_package = 45; + bool has_ruby_package() const; + private: + bool _internal_has_ruby_package() const; + public: + void clear_ruby_package(); + const std::string& ruby_package() const; + template <typename ArgT0 = const std::string&, typename... ArgT> + void set_ruby_package(ArgT0&& arg0, ArgT... args); + std::string* mutable_ruby_package(); + PROTOBUF_NODISCARD std::string* release_ruby_package(); + void set_allocated_ruby_package(std::string* ruby_package); + private: + const std::string& _internal_ruby_package() const; + inline PROTOBUF_ALWAYS_INLINE void _internal_set_ruby_package(const std::string& value); + std::string* _internal_mutable_ruby_package(); + public: + + // optional bool java_multiple_files = 10 [default = false]; + bool has_java_multiple_files() const; + private: + bool _internal_has_java_multiple_files() const; + public: + void clear_java_multiple_files(); + bool java_multiple_files() const; + void set_java_multiple_files(bool value); + private: + bool _internal_java_multiple_files() const; + void _internal_set_java_multiple_files(bool value); + public: + + // optional bool java_generate_equals_and_hash = 20 [deprecated = true]; + PROTOBUF_DEPRECATED bool has_java_generate_equals_and_hash() const; + private: + bool _internal_has_java_generate_equals_and_hash() const; + public: + PROTOBUF_DEPRECATED void clear_java_generate_equals_and_hash(); + PROTOBUF_DEPRECATED bool java_generate_equals_and_hash() const; + PROTOBUF_DEPRECATED void set_java_generate_equals_and_hash(bool value); + private: + bool _internal_java_generate_equals_and_hash() const; + void _internal_set_java_generate_equals_and_hash(bool value); + public: + + // optional bool java_string_check_utf8 = 27 [default = false]; + bool has_java_string_check_utf8() const; + private: + bool _internal_has_java_string_check_utf8() const; + public: + void clear_java_string_check_utf8(); + bool java_string_check_utf8() const; + void set_java_string_check_utf8(bool value); + private: + bool _internal_java_string_check_utf8() const; + void _internal_set_java_string_check_utf8(bool value); + public: + + // optional bool cc_generic_services = 16 [default = false]; + bool has_cc_generic_services() const; + private: + bool _internal_has_cc_generic_services() const; + public: + void clear_cc_generic_services(); + bool cc_generic_services() const; + void set_cc_generic_services(bool value); + private: + bool _internal_cc_generic_services() const; + void _internal_set_cc_generic_services(bool value); + public: + + // optional bool java_generic_services = 17 [default = false]; + bool has_java_generic_services() const; + private: + bool _internal_has_java_generic_services() const; + public: + void clear_java_generic_services(); + bool java_generic_services() const; + void set_java_generic_services(bool value); + private: + bool _internal_java_generic_services() const; + void _internal_set_java_generic_services(bool value); + public: + + // optional bool py_generic_services = 18 [default = false]; + bool has_py_generic_services() const; + private: + bool _internal_has_py_generic_services() const; + public: + void clear_py_generic_services(); + bool py_generic_services() const; + void set_py_generic_services(bool value); + private: + bool _internal_py_generic_services() const; + void _internal_set_py_generic_services(bool value); + public: + + // optional bool php_generic_services = 42 [default = false]; + bool has_php_generic_services() const; + private: + bool _internal_has_php_generic_services() const; + public: + void clear_php_generic_services(); + bool php_generic_services() const; + void set_php_generic_services(bool value); + private: + bool _internal_php_generic_services() const; + void _internal_set_php_generic_services(bool value); + public: + + // optional bool deprecated = 23 [default = false]; + bool has_deprecated() const; + private: + bool _internal_has_deprecated() const; + public: + void clear_deprecated(); + bool deprecated() const; + void set_deprecated(bool value); + private: + bool _internal_deprecated() const; + void _internal_set_deprecated(bool value); + public: + + // optional .google.protobuf.FileOptions.OptimizeMode optimize_for = 9 [default = SPEED]; + bool has_optimize_for() const; + private: + bool _internal_has_optimize_for() const; + public: + void clear_optimize_for(); + ::PROTOBUF_NAMESPACE_ID::FileOptions_OptimizeMode optimize_for() const; + void set_optimize_for(::PROTOBUF_NAMESPACE_ID::FileOptions_OptimizeMode value); + private: + ::PROTOBUF_NAMESPACE_ID::FileOptions_OptimizeMode _internal_optimize_for() const; + void _internal_set_optimize_for(::PROTOBUF_NAMESPACE_ID::FileOptions_OptimizeMode value); + public: + + // optional bool cc_enable_arenas = 31 [default = true]; + bool has_cc_enable_arenas() const; + private: + bool _internal_has_cc_enable_arenas() const; + public: + void clear_cc_enable_arenas(); + bool cc_enable_arenas() const; + void set_cc_enable_arenas(bool value); + private: + bool _internal_cc_enable_arenas() const; + void _internal_set_cc_enable_arenas(bool value); + public: + + + template <typename _proto_TypeTraits, + ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type, + bool _is_packed> + inline bool HasExtension( + const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier< + FileOptions, _proto_TypeTraits, _field_type, _is_packed>& id) const { + + return _impl_._extensions_.Has(id.number()); + } + + template <typename _proto_TypeTraits, + ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type, + bool _is_packed> + inline void ClearExtension( + const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier< + FileOptions, _proto_TypeTraits, _field_type, _is_packed>& id) { + _impl_._extensions_.ClearExtension(id.number()); + + } + + template <typename _proto_TypeTraits, + ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type, + bool _is_packed> + inline int ExtensionSize( + const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier< + FileOptions, _proto_TypeTraits, _field_type, _is_packed>& id) const { + + return _impl_._extensions_.ExtensionSize(id.number()); + } + + template <typename _proto_TypeTraits, + ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type, + bool _is_packed> + inline typename _proto_TypeTraits::Singular::ConstType GetExtension( + const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier< + FileOptions, _proto_TypeTraits, _field_type, _is_packed>& id) const { + + return _proto_TypeTraits::Get(id.number(), _impl_._extensions_, + id.default_value()); + } + + template <typename _proto_TypeTraits, + ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type, + bool _is_packed> + inline typename _proto_TypeTraits::Singular::MutableType MutableExtension( + const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier< + FileOptions, _proto_TypeTraits, _field_type, _is_packed>& id) { + + return _proto_TypeTraits::Mutable(id.number(), _field_type, + &_impl_._extensions_); + } + + template <typename _proto_TypeTraits, + ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type, + bool _is_packed> + inline void SetExtension( + const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier< + FileOptions, _proto_TypeTraits, _field_type, _is_packed>& id, + typename _proto_TypeTraits::Singular::ConstType value) { + _proto_TypeTraits::Set(id.number(), _field_type, value, &_impl_._extensions_); + + } + + template <typename _proto_TypeTraits, + ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type, + bool _is_packed> + inline void SetAllocatedExtension( + const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier< + FileOptions, _proto_TypeTraits, _field_type, _is_packed>& id, + typename _proto_TypeTraits::Singular::MutableType value) { + _proto_TypeTraits::SetAllocated(id.number(), _field_type, value, + &_impl_._extensions_); + + } + template <typename _proto_TypeTraits, + ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type, + bool _is_packed> + inline void UnsafeArenaSetAllocatedExtension( + const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier< + FileOptions, _proto_TypeTraits, _field_type, _is_packed>& id, + typename _proto_TypeTraits::Singular::MutableType value) { + _proto_TypeTraits::UnsafeArenaSetAllocated(id.number(), _field_type, + value, &_impl_._extensions_); + + } + template <typename _proto_TypeTraits, + ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type, + bool _is_packed> + PROTOBUF_NODISCARD inline + typename _proto_TypeTraits::Singular::MutableType + ReleaseExtension( + const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier< + FileOptions, _proto_TypeTraits, _field_type, _is_packed>& id) { + + return _proto_TypeTraits::Release(id.number(), _field_type, + &_impl_._extensions_); + } + template <typename _proto_TypeTraits, + ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type, + bool _is_packed> + inline typename _proto_TypeTraits::Singular::MutableType + UnsafeArenaReleaseExtension( + const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier< + FileOptions, _proto_TypeTraits, _field_type, _is_packed>& id) { + + return _proto_TypeTraits::UnsafeArenaRelease(id.number(), _field_type, + &_impl_._extensions_); + } + + template <typename _proto_TypeTraits, + ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type, + bool _is_packed> + inline typename _proto_TypeTraits::Repeated::ConstType GetExtension( + const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier< + FileOptions, _proto_TypeTraits, _field_type, _is_packed>& id, + int index) const { + + return _proto_TypeTraits::Get(id.number(), _impl_._extensions_, index); + } + + template <typename _proto_TypeTraits, + ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type, + bool _is_packed> + inline typename _proto_TypeTraits::Repeated::MutableType MutableExtension( + const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier< + FileOptions, _proto_TypeTraits, _field_type, _is_packed>& id, + int index) { + + return _proto_TypeTraits::Mutable(id.number(), index, &_impl_._extensions_); + } + + template <typename _proto_TypeTraits, + ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type, + bool _is_packed> + inline void SetExtension( + const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier< + FileOptions, _proto_TypeTraits, _field_type, _is_packed>& id, + int index, typename _proto_TypeTraits::Repeated::ConstType value) { + _proto_TypeTraits::Set(id.number(), index, value, &_impl_._extensions_); + + } + + template <typename _proto_TypeTraits, + ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type, + bool _is_packed> + inline typename _proto_TypeTraits::Repeated::MutableType AddExtension( + const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier< + FileOptions, _proto_TypeTraits, _field_type, _is_packed>& id) { + typename _proto_TypeTraits::Repeated::MutableType to_add = + _proto_TypeTraits::Add(id.number(), _field_type, &_impl_._extensions_); + + return to_add; + } + + template <typename _proto_TypeTraits, + ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type, + bool _is_packed> + inline void AddExtension( + const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier< + FileOptions, _proto_TypeTraits, _field_type, _is_packed>& id, + typename _proto_TypeTraits::Repeated::ConstType value) { + _proto_TypeTraits::Add(id.number(), _field_type, _is_packed, value, + &_impl_._extensions_); + + } + + template <typename _proto_TypeTraits, + ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type, + bool _is_packed> + inline const typename _proto_TypeTraits::Repeated::RepeatedFieldType& + GetRepeatedExtension( + const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier< + FileOptions, _proto_TypeTraits, _field_type, _is_packed>& id) const { + + return _proto_TypeTraits::GetRepeated(id.number(), _impl_._extensions_); + } + + template <typename _proto_TypeTraits, + ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type, + bool _is_packed> + inline typename _proto_TypeTraits::Repeated::RepeatedFieldType* + MutableRepeatedExtension( + const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier< + FileOptions, _proto_TypeTraits, _field_type, _is_packed>& id) { + + return _proto_TypeTraits::MutableRepeated(id.number(), _field_type, + _is_packed, &_impl_._extensions_); + } + + // @@protoc_insertion_point(class_scope:google.protobuf.FileOptions) + private: + class _Internal; + + template <typename T> friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper; + typedef void InternalArenaConstructable_; + typedef void DestructorSkippable_; + struct Impl_ { + ::PROTOBUF_NAMESPACE_ID::internal::ExtensionSet _extensions_; + + ::PROTOBUF_NAMESPACE_ID::internal::HasBits<1> _has_bits_; + mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_; + ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::UninterpretedOption > uninterpreted_option_; + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr java_package_; + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr java_outer_classname_; + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr go_package_; + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr objc_class_prefix_; + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr csharp_namespace_; + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr swift_prefix_; + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr php_class_prefix_; + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr php_namespace_; + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr php_metadata_namespace_; + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr ruby_package_; + bool java_multiple_files_; + bool java_generate_equals_and_hash_; + bool java_string_check_utf8_; + bool cc_generic_services_; + bool java_generic_services_; + bool py_generic_services_; + bool php_generic_services_; + bool deprecated_; + int optimize_for_; + bool cc_enable_arenas_; + }; + union { Impl_ _impl_; }; + friend struct ::TableStruct_google_2fprotobuf_2fdescriptor_2eproto; +}; +// ------------------------------------------------------------------- + +class PROTOBUF_EXPORT MessageOptions final : + public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.MessageOptions) */ { + public: + inline MessageOptions() : MessageOptions(nullptr) {} + ~MessageOptions() override; + explicit PROTOBUF_CONSTEXPR MessageOptions(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized); + + MessageOptions(const MessageOptions& from); + MessageOptions(MessageOptions&& from) noexcept + : MessageOptions() { + *this = ::std::move(from); + } + + inline MessageOptions& operator=(const MessageOptions& from) { + CopyFrom(from); + return *this; + } + inline MessageOptions& operator=(MessageOptions&& from) noexcept { + if (this == &from) return *this; + if (GetOwningArena() == from.GetOwningArena() + #ifdef PROTOBUF_FORCE_COPY_IN_MOVE + && GetOwningArena() != nullptr + #endif // !PROTOBUF_FORCE_COPY_IN_MOVE + ) { + InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + inline const ::PROTOBUF_NAMESPACE_ID::UnknownFieldSet& unknown_fields() const { + return _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance); + } + inline ::PROTOBUF_NAMESPACE_ID::UnknownFieldSet* mutable_unknown_fields() { + return _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); + } + + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* descriptor() { + return GetDescriptor(); + } + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() { + return default_instance().GetMetadata().descriptor; + } + static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() { + return default_instance().GetMetadata().reflection; + } + static const MessageOptions& default_instance() { + return *internal_default_instance(); + } + static inline const MessageOptions* internal_default_instance() { + return reinterpret_cast<const MessageOptions*>( + &_MessageOptions_default_instance_); + } + static constexpr int kIndexInFileMessages = + 14; + + friend void swap(MessageOptions& a, MessageOptions& b) { + a.Swap(&b); + } + inline void Swap(MessageOptions* other) { + if (other == this) return; + #ifdef PROTOBUF_FORCE_COPY_IN_SWAP + if (GetOwningArena() != nullptr && + GetOwningArena() == other->GetOwningArena()) { + #else // PROTOBUF_FORCE_COPY_IN_SWAP + if (GetOwningArena() == other->GetOwningArena()) { + #endif // !PROTOBUF_FORCE_COPY_IN_SWAP + InternalSwap(other); + } else { + ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(MessageOptions* other) { + if (other == this) return; + GOOGLE_DCHECK(GetOwningArena() == other->GetOwningArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + MessageOptions* New(::PROTOBUF_NAMESPACE_ID::Arena* arena = nullptr) const final { + return CreateMaybeMessage<MessageOptions>(arena); + } + using ::PROTOBUF_NAMESPACE_ID::Message::CopyFrom; + void CopyFrom(const MessageOptions& from); + using ::PROTOBUF_NAMESPACE_ID::Message::MergeFrom; + void MergeFrom( const MessageOptions& from) { + MessageOptions::MergeImpl(*this, from); + } + private: + static void MergeImpl(::PROTOBUF_NAMESPACE_ID::Message& to_msg, const ::PROTOBUF_NAMESPACE_ID::Message& from_msg); + public: + PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + bool IsInitialized() const final; + + size_t ByteSizeLong() const final; + const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final; + uint8_t* _InternalSerialize( + uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final; + int GetCachedSize() const final { return _impl_._cached_size_.Get(); } + + private: + void SharedCtor(::PROTOBUF_NAMESPACE_ID::Arena* arena, bool is_message_owned); + void SharedDtor(); + void SetCachedSize(int size) const final; + void InternalSwap(MessageOptions* other); + + private: + friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata; + static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() { + return "google.protobuf.MessageOptions"; + } + protected: + explicit MessageOptions(::PROTOBUF_NAMESPACE_ID::Arena* arena, + bool is_message_owned = false); + public: + + static const ClassData _class_data_; + const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*GetClassData() const final; + + ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final; + + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + + enum : int { + kUninterpretedOptionFieldNumber = 999, + kMessageSetWireFormatFieldNumber = 1, + kNoStandardDescriptorAccessorFieldNumber = 2, + kDeprecatedFieldNumber = 3, + kMapEntryFieldNumber = 7, + }; + // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; + int uninterpreted_option_size() const; + private: + int _internal_uninterpreted_option_size() const; + public: + void clear_uninterpreted_option(); + ::PROTOBUF_NAMESPACE_ID::UninterpretedOption* mutable_uninterpreted_option(int index); + ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::UninterpretedOption >* + mutable_uninterpreted_option(); + private: + const ::PROTOBUF_NAMESPACE_ID::UninterpretedOption& _internal_uninterpreted_option(int index) const; + ::PROTOBUF_NAMESPACE_ID::UninterpretedOption* _internal_add_uninterpreted_option(); + public: + const ::PROTOBUF_NAMESPACE_ID::UninterpretedOption& uninterpreted_option(int index) const; + ::PROTOBUF_NAMESPACE_ID::UninterpretedOption* add_uninterpreted_option(); + const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::UninterpretedOption >& + uninterpreted_option() const; + + // optional bool message_set_wire_format = 1 [default = false]; + bool has_message_set_wire_format() const; + private: + bool _internal_has_message_set_wire_format() const; + public: + void clear_message_set_wire_format(); + bool message_set_wire_format() const; + void set_message_set_wire_format(bool value); + private: + bool _internal_message_set_wire_format() const; + void _internal_set_message_set_wire_format(bool value); + public: + + // optional bool no_standard_descriptor_accessor = 2 [default = false]; + bool has_no_standard_descriptor_accessor() const; + private: + bool _internal_has_no_standard_descriptor_accessor() const; + public: + void clear_no_standard_descriptor_accessor(); + bool no_standard_descriptor_accessor() const; + void set_no_standard_descriptor_accessor(bool value); + private: + bool _internal_no_standard_descriptor_accessor() const; + void _internal_set_no_standard_descriptor_accessor(bool value); + public: + + // optional bool deprecated = 3 [default = false]; + bool has_deprecated() const; + private: + bool _internal_has_deprecated() const; + public: + void clear_deprecated(); + bool deprecated() const; + void set_deprecated(bool value); + private: + bool _internal_deprecated() const; + void _internal_set_deprecated(bool value); + public: + + // optional bool map_entry = 7; + bool has_map_entry() const; + private: + bool _internal_has_map_entry() const; + public: + void clear_map_entry(); + bool map_entry() const; + void set_map_entry(bool value); + private: + bool _internal_map_entry() const; + void _internal_set_map_entry(bool value); + public: + + + template <typename _proto_TypeTraits, + ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type, + bool _is_packed> + inline bool HasExtension( + const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier< + MessageOptions, _proto_TypeTraits, _field_type, _is_packed>& id) const { + + return _impl_._extensions_.Has(id.number()); + } + + template <typename _proto_TypeTraits, + ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type, + bool _is_packed> + inline void ClearExtension( + const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier< + MessageOptions, _proto_TypeTraits, _field_type, _is_packed>& id) { + _impl_._extensions_.ClearExtension(id.number()); + + } + + template <typename _proto_TypeTraits, + ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type, + bool _is_packed> + inline int ExtensionSize( + const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier< + MessageOptions, _proto_TypeTraits, _field_type, _is_packed>& id) const { + + return _impl_._extensions_.ExtensionSize(id.number()); + } + + template <typename _proto_TypeTraits, + ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type, + bool _is_packed> + inline typename _proto_TypeTraits::Singular::ConstType GetExtension( + const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier< + MessageOptions, _proto_TypeTraits, _field_type, _is_packed>& id) const { + + return _proto_TypeTraits::Get(id.number(), _impl_._extensions_, + id.default_value()); + } + + template <typename _proto_TypeTraits, + ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type, + bool _is_packed> + inline typename _proto_TypeTraits::Singular::MutableType MutableExtension( + const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier< + MessageOptions, _proto_TypeTraits, _field_type, _is_packed>& id) { + + return _proto_TypeTraits::Mutable(id.number(), _field_type, + &_impl_._extensions_); + } + + template <typename _proto_TypeTraits, + ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type, + bool _is_packed> + inline void SetExtension( + const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier< + MessageOptions, _proto_TypeTraits, _field_type, _is_packed>& id, + typename _proto_TypeTraits::Singular::ConstType value) { + _proto_TypeTraits::Set(id.number(), _field_type, value, &_impl_._extensions_); + + } + + template <typename _proto_TypeTraits, + ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type, + bool _is_packed> + inline void SetAllocatedExtension( + const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier< + MessageOptions, _proto_TypeTraits, _field_type, _is_packed>& id, + typename _proto_TypeTraits::Singular::MutableType value) { + _proto_TypeTraits::SetAllocated(id.number(), _field_type, value, + &_impl_._extensions_); + + } + template <typename _proto_TypeTraits, + ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type, + bool _is_packed> + inline void UnsafeArenaSetAllocatedExtension( + const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier< + MessageOptions, _proto_TypeTraits, _field_type, _is_packed>& id, + typename _proto_TypeTraits::Singular::MutableType value) { + _proto_TypeTraits::UnsafeArenaSetAllocated(id.number(), _field_type, + value, &_impl_._extensions_); + + } + template <typename _proto_TypeTraits, + ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type, + bool _is_packed> + PROTOBUF_NODISCARD inline + typename _proto_TypeTraits::Singular::MutableType + ReleaseExtension( + const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier< + MessageOptions, _proto_TypeTraits, _field_type, _is_packed>& id) { + + return _proto_TypeTraits::Release(id.number(), _field_type, + &_impl_._extensions_); + } + template <typename _proto_TypeTraits, + ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type, + bool _is_packed> + inline typename _proto_TypeTraits::Singular::MutableType + UnsafeArenaReleaseExtension( + const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier< + MessageOptions, _proto_TypeTraits, _field_type, _is_packed>& id) { + + return _proto_TypeTraits::UnsafeArenaRelease(id.number(), _field_type, + &_impl_._extensions_); + } + + template <typename _proto_TypeTraits, + ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type, + bool _is_packed> + inline typename _proto_TypeTraits::Repeated::ConstType GetExtension( + const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier< + MessageOptions, _proto_TypeTraits, _field_type, _is_packed>& id, + int index) const { + + return _proto_TypeTraits::Get(id.number(), _impl_._extensions_, index); + } + + template <typename _proto_TypeTraits, + ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type, + bool _is_packed> + inline typename _proto_TypeTraits::Repeated::MutableType MutableExtension( + const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier< + MessageOptions, _proto_TypeTraits, _field_type, _is_packed>& id, + int index) { + + return _proto_TypeTraits::Mutable(id.number(), index, &_impl_._extensions_); + } + + template <typename _proto_TypeTraits, + ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type, + bool _is_packed> + inline void SetExtension( + const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier< + MessageOptions, _proto_TypeTraits, _field_type, _is_packed>& id, + int index, typename _proto_TypeTraits::Repeated::ConstType value) { + _proto_TypeTraits::Set(id.number(), index, value, &_impl_._extensions_); + + } + + template <typename _proto_TypeTraits, + ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type, + bool _is_packed> + inline typename _proto_TypeTraits::Repeated::MutableType AddExtension( + const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier< + MessageOptions, _proto_TypeTraits, _field_type, _is_packed>& id) { + typename _proto_TypeTraits::Repeated::MutableType to_add = + _proto_TypeTraits::Add(id.number(), _field_type, &_impl_._extensions_); + + return to_add; + } + + template <typename _proto_TypeTraits, + ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type, + bool _is_packed> + inline void AddExtension( + const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier< + MessageOptions, _proto_TypeTraits, _field_type, _is_packed>& id, + typename _proto_TypeTraits::Repeated::ConstType value) { + _proto_TypeTraits::Add(id.number(), _field_type, _is_packed, value, + &_impl_._extensions_); + + } + + template <typename _proto_TypeTraits, + ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type, + bool _is_packed> + inline const typename _proto_TypeTraits::Repeated::RepeatedFieldType& + GetRepeatedExtension( + const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier< + MessageOptions, _proto_TypeTraits, _field_type, _is_packed>& id) const { + + return _proto_TypeTraits::GetRepeated(id.number(), _impl_._extensions_); + } + + template <typename _proto_TypeTraits, + ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type, + bool _is_packed> + inline typename _proto_TypeTraits::Repeated::RepeatedFieldType* + MutableRepeatedExtension( + const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier< + MessageOptions, _proto_TypeTraits, _field_type, _is_packed>& id) { + + return _proto_TypeTraits::MutableRepeated(id.number(), _field_type, + _is_packed, &_impl_._extensions_); + } + + // @@protoc_insertion_point(class_scope:google.protobuf.MessageOptions) + private: + class _Internal; + + template <typename T> friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper; + typedef void InternalArenaConstructable_; + typedef void DestructorSkippable_; + struct Impl_ { + ::PROTOBUF_NAMESPACE_ID::internal::ExtensionSet _extensions_; + + ::PROTOBUF_NAMESPACE_ID::internal::HasBits<1> _has_bits_; + mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_; + ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::UninterpretedOption > uninterpreted_option_; + bool message_set_wire_format_; + bool no_standard_descriptor_accessor_; + bool deprecated_; + bool map_entry_; + }; + union { Impl_ _impl_; }; + friend struct ::TableStruct_google_2fprotobuf_2fdescriptor_2eproto; +}; +// ------------------------------------------------------------------- + +class PROTOBUF_EXPORT FieldOptions final : + public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.FieldOptions) */ { + public: + inline FieldOptions() : FieldOptions(nullptr) {} + ~FieldOptions() override; + explicit PROTOBUF_CONSTEXPR FieldOptions(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized); + + FieldOptions(const FieldOptions& from); + FieldOptions(FieldOptions&& from) noexcept + : FieldOptions() { + *this = ::std::move(from); + } + + inline FieldOptions& operator=(const FieldOptions& from) { + CopyFrom(from); + return *this; + } + inline FieldOptions& operator=(FieldOptions&& from) noexcept { + if (this == &from) return *this; + if (GetOwningArena() == from.GetOwningArena() + #ifdef PROTOBUF_FORCE_COPY_IN_MOVE + && GetOwningArena() != nullptr + #endif // !PROTOBUF_FORCE_COPY_IN_MOVE + ) { + InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + inline const ::PROTOBUF_NAMESPACE_ID::UnknownFieldSet& unknown_fields() const { + return _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance); + } + inline ::PROTOBUF_NAMESPACE_ID::UnknownFieldSet* mutable_unknown_fields() { + return _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); + } + + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* descriptor() { + return GetDescriptor(); + } + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() { + return default_instance().GetMetadata().descriptor; + } + static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() { + return default_instance().GetMetadata().reflection; + } + static const FieldOptions& default_instance() { + return *internal_default_instance(); + } + static inline const FieldOptions* internal_default_instance() { + return reinterpret_cast<const FieldOptions*>( + &_FieldOptions_default_instance_); + } + static constexpr int kIndexInFileMessages = + 15; + + friend void swap(FieldOptions& a, FieldOptions& b) { + a.Swap(&b); + } + inline void Swap(FieldOptions* other) { + if (other == this) return; + #ifdef PROTOBUF_FORCE_COPY_IN_SWAP + if (GetOwningArena() != nullptr && + GetOwningArena() == other->GetOwningArena()) { + #else // PROTOBUF_FORCE_COPY_IN_SWAP + if (GetOwningArena() == other->GetOwningArena()) { + #endif // !PROTOBUF_FORCE_COPY_IN_SWAP + InternalSwap(other); + } else { + ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(FieldOptions* other) { + if (other == this) return; + GOOGLE_DCHECK(GetOwningArena() == other->GetOwningArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + FieldOptions* New(::PROTOBUF_NAMESPACE_ID::Arena* arena = nullptr) const final { + return CreateMaybeMessage<FieldOptions>(arena); + } + using ::PROTOBUF_NAMESPACE_ID::Message::CopyFrom; + void CopyFrom(const FieldOptions& from); + using ::PROTOBUF_NAMESPACE_ID::Message::MergeFrom; + void MergeFrom( const FieldOptions& from) { + FieldOptions::MergeImpl(*this, from); + } + private: + static void MergeImpl(::PROTOBUF_NAMESPACE_ID::Message& to_msg, const ::PROTOBUF_NAMESPACE_ID::Message& from_msg); + public: + PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + bool IsInitialized() const final; + + size_t ByteSizeLong() const final; + const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final; + uint8_t* _InternalSerialize( + uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final; + int GetCachedSize() const final { return _impl_._cached_size_.Get(); } + + private: + void SharedCtor(::PROTOBUF_NAMESPACE_ID::Arena* arena, bool is_message_owned); + void SharedDtor(); + void SetCachedSize(int size) const final; + void InternalSwap(FieldOptions* other); + + private: + friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata; + static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() { + return "google.protobuf.FieldOptions"; + } + protected: + explicit FieldOptions(::PROTOBUF_NAMESPACE_ID::Arena* arena, + bool is_message_owned = false); + public: + + static const ClassData _class_data_; + const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*GetClassData() const final; + + ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final; + + // nested types ---------------------------------------------------- + + typedef FieldOptions_CType CType; + static constexpr CType STRING = + FieldOptions_CType_STRING; + static constexpr CType CORD = + FieldOptions_CType_CORD; + static constexpr CType STRING_PIECE = + FieldOptions_CType_STRING_PIECE; + static inline bool CType_IsValid(int value) { + return FieldOptions_CType_IsValid(value); + } + static constexpr CType CType_MIN = + FieldOptions_CType_CType_MIN; + static constexpr CType CType_MAX = + FieldOptions_CType_CType_MAX; + static constexpr int CType_ARRAYSIZE = + FieldOptions_CType_CType_ARRAYSIZE; + static inline const ::PROTOBUF_NAMESPACE_ID::EnumDescriptor* + CType_descriptor() { + return FieldOptions_CType_descriptor(); + } + template<typename T> + static inline const std::string& CType_Name(T enum_t_value) { + static_assert(::std::is_same<T, CType>::value || + ::std::is_integral<T>::value, + "Incorrect type passed to function CType_Name."); + return FieldOptions_CType_Name(enum_t_value); + } + static inline bool CType_Parse(::PROTOBUF_NAMESPACE_ID::ConstStringParam name, + CType* value) { + return FieldOptions_CType_Parse(name, value); + } + + typedef FieldOptions_JSType JSType; + static constexpr JSType JS_NORMAL = + FieldOptions_JSType_JS_NORMAL; + static constexpr JSType JS_STRING = + FieldOptions_JSType_JS_STRING; + static constexpr JSType JS_NUMBER = + FieldOptions_JSType_JS_NUMBER; + static inline bool JSType_IsValid(int value) { + return FieldOptions_JSType_IsValid(value); + } + static constexpr JSType JSType_MIN = + FieldOptions_JSType_JSType_MIN; + static constexpr JSType JSType_MAX = + FieldOptions_JSType_JSType_MAX; + static constexpr int JSType_ARRAYSIZE = + FieldOptions_JSType_JSType_ARRAYSIZE; + static inline const ::PROTOBUF_NAMESPACE_ID::EnumDescriptor* + JSType_descriptor() { + return FieldOptions_JSType_descriptor(); + } + template<typename T> + static inline const std::string& JSType_Name(T enum_t_value) { + static_assert(::std::is_same<T, JSType>::value || + ::std::is_integral<T>::value, + "Incorrect type passed to function JSType_Name."); + return FieldOptions_JSType_Name(enum_t_value); + } + static inline bool JSType_Parse(::PROTOBUF_NAMESPACE_ID::ConstStringParam name, + JSType* value) { + return FieldOptions_JSType_Parse(name, value); + } + + // accessors ------------------------------------------------------- + + enum : int { + kUninterpretedOptionFieldNumber = 999, + kCtypeFieldNumber = 1, + kJstypeFieldNumber = 6, + kPackedFieldNumber = 2, + kLazyFieldNumber = 5, + kUnverifiedLazyFieldNumber = 15, + kDeprecatedFieldNumber = 3, + kWeakFieldNumber = 10, + }; + // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; + int uninterpreted_option_size() const; + private: + int _internal_uninterpreted_option_size() const; + public: + void clear_uninterpreted_option(); + ::PROTOBUF_NAMESPACE_ID::UninterpretedOption* mutable_uninterpreted_option(int index); + ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::UninterpretedOption >* + mutable_uninterpreted_option(); + private: + const ::PROTOBUF_NAMESPACE_ID::UninterpretedOption& _internal_uninterpreted_option(int index) const; + ::PROTOBUF_NAMESPACE_ID::UninterpretedOption* _internal_add_uninterpreted_option(); + public: + const ::PROTOBUF_NAMESPACE_ID::UninterpretedOption& uninterpreted_option(int index) const; + ::PROTOBUF_NAMESPACE_ID::UninterpretedOption* add_uninterpreted_option(); + const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::UninterpretedOption >& + uninterpreted_option() const; + + // optional .google.protobuf.FieldOptions.CType ctype = 1 [default = STRING]; + bool has_ctype() const; + private: + bool _internal_has_ctype() const; + public: + void clear_ctype(); + ::PROTOBUF_NAMESPACE_ID::FieldOptions_CType ctype() const; + void set_ctype(::PROTOBUF_NAMESPACE_ID::FieldOptions_CType value); + private: + ::PROTOBUF_NAMESPACE_ID::FieldOptions_CType _internal_ctype() const; + void _internal_set_ctype(::PROTOBUF_NAMESPACE_ID::FieldOptions_CType value); + public: + + // optional .google.protobuf.FieldOptions.JSType jstype = 6 [default = JS_NORMAL]; + bool has_jstype() const; + private: + bool _internal_has_jstype() const; + public: + void clear_jstype(); + ::PROTOBUF_NAMESPACE_ID::FieldOptions_JSType jstype() const; + void set_jstype(::PROTOBUF_NAMESPACE_ID::FieldOptions_JSType value); + private: + ::PROTOBUF_NAMESPACE_ID::FieldOptions_JSType _internal_jstype() const; + void _internal_set_jstype(::PROTOBUF_NAMESPACE_ID::FieldOptions_JSType value); + public: + + // optional bool packed = 2; + bool has_packed() const; + private: + bool _internal_has_packed() const; + public: + void clear_packed(); + bool packed() const; + void set_packed(bool value); + private: + bool _internal_packed() const; + void _internal_set_packed(bool value); + public: + + // optional bool lazy = 5 [default = false]; + bool has_lazy() const; + private: + bool _internal_has_lazy() const; + public: + void clear_lazy(); + bool lazy() const; + void set_lazy(bool value); + private: + bool _internal_lazy() const; + void _internal_set_lazy(bool value); + public: + + // optional bool unverified_lazy = 15 [default = false]; + bool has_unverified_lazy() const; + private: + bool _internal_has_unverified_lazy() const; + public: + void clear_unverified_lazy(); + bool unverified_lazy() const; + void set_unverified_lazy(bool value); + private: + bool _internal_unverified_lazy() const; + void _internal_set_unverified_lazy(bool value); + public: + + // optional bool deprecated = 3 [default = false]; + bool has_deprecated() const; + private: + bool _internal_has_deprecated() const; + public: + void clear_deprecated(); + bool deprecated() const; + void set_deprecated(bool value); + private: + bool _internal_deprecated() const; + void _internal_set_deprecated(bool value); + public: + + // optional bool weak = 10 [default = false]; + bool has_weak() const; + private: + bool _internal_has_weak() const; + public: + void clear_weak(); + bool weak() const; + void set_weak(bool value); + private: + bool _internal_weak() const; + void _internal_set_weak(bool value); + public: + + + template <typename _proto_TypeTraits, + ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type, + bool _is_packed> + inline bool HasExtension( + const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier< + FieldOptions, _proto_TypeTraits, _field_type, _is_packed>& id) const { + + return _impl_._extensions_.Has(id.number()); + } + + template <typename _proto_TypeTraits, + ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type, + bool _is_packed> + inline void ClearExtension( + const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier< + FieldOptions, _proto_TypeTraits, _field_type, _is_packed>& id) { + _impl_._extensions_.ClearExtension(id.number()); + + } + + template <typename _proto_TypeTraits, + ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type, + bool _is_packed> + inline int ExtensionSize( + const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier< + FieldOptions, _proto_TypeTraits, _field_type, _is_packed>& id) const { + + return _impl_._extensions_.ExtensionSize(id.number()); + } + + template <typename _proto_TypeTraits, + ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type, + bool _is_packed> + inline typename _proto_TypeTraits::Singular::ConstType GetExtension( + const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier< + FieldOptions, _proto_TypeTraits, _field_type, _is_packed>& id) const { + + return _proto_TypeTraits::Get(id.number(), _impl_._extensions_, + id.default_value()); + } + + template <typename _proto_TypeTraits, + ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type, + bool _is_packed> + inline typename _proto_TypeTraits::Singular::MutableType MutableExtension( + const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier< + FieldOptions, _proto_TypeTraits, _field_type, _is_packed>& id) { + + return _proto_TypeTraits::Mutable(id.number(), _field_type, + &_impl_._extensions_); + } + + template <typename _proto_TypeTraits, + ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type, + bool _is_packed> + inline void SetExtension( + const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier< + FieldOptions, _proto_TypeTraits, _field_type, _is_packed>& id, + typename _proto_TypeTraits::Singular::ConstType value) { + _proto_TypeTraits::Set(id.number(), _field_type, value, &_impl_._extensions_); + + } + + template <typename _proto_TypeTraits, + ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type, + bool _is_packed> + inline void SetAllocatedExtension( + const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier< + FieldOptions, _proto_TypeTraits, _field_type, _is_packed>& id, + typename _proto_TypeTraits::Singular::MutableType value) { + _proto_TypeTraits::SetAllocated(id.number(), _field_type, value, + &_impl_._extensions_); + + } + template <typename _proto_TypeTraits, + ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type, + bool _is_packed> + inline void UnsafeArenaSetAllocatedExtension( + const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier< + FieldOptions, _proto_TypeTraits, _field_type, _is_packed>& id, + typename _proto_TypeTraits::Singular::MutableType value) { + _proto_TypeTraits::UnsafeArenaSetAllocated(id.number(), _field_type, + value, &_impl_._extensions_); + + } + template <typename _proto_TypeTraits, + ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type, + bool _is_packed> + PROTOBUF_NODISCARD inline + typename _proto_TypeTraits::Singular::MutableType + ReleaseExtension( + const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier< + FieldOptions, _proto_TypeTraits, _field_type, _is_packed>& id) { + + return _proto_TypeTraits::Release(id.number(), _field_type, + &_impl_._extensions_); + } + template <typename _proto_TypeTraits, + ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type, + bool _is_packed> + inline typename _proto_TypeTraits::Singular::MutableType + UnsafeArenaReleaseExtension( + const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier< + FieldOptions, _proto_TypeTraits, _field_type, _is_packed>& id) { + + return _proto_TypeTraits::UnsafeArenaRelease(id.number(), _field_type, + &_impl_._extensions_); + } + + template <typename _proto_TypeTraits, + ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type, + bool _is_packed> + inline typename _proto_TypeTraits::Repeated::ConstType GetExtension( + const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier< + FieldOptions, _proto_TypeTraits, _field_type, _is_packed>& id, + int index) const { + + return _proto_TypeTraits::Get(id.number(), _impl_._extensions_, index); + } + + template <typename _proto_TypeTraits, + ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type, + bool _is_packed> + inline typename _proto_TypeTraits::Repeated::MutableType MutableExtension( + const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier< + FieldOptions, _proto_TypeTraits, _field_type, _is_packed>& id, + int index) { + + return _proto_TypeTraits::Mutable(id.number(), index, &_impl_._extensions_); + } + + template <typename _proto_TypeTraits, + ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type, + bool _is_packed> + inline void SetExtension( + const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier< + FieldOptions, _proto_TypeTraits, _field_type, _is_packed>& id, + int index, typename _proto_TypeTraits::Repeated::ConstType value) { + _proto_TypeTraits::Set(id.number(), index, value, &_impl_._extensions_); + + } + + template <typename _proto_TypeTraits, + ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type, + bool _is_packed> + inline typename _proto_TypeTraits::Repeated::MutableType AddExtension( + const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier< + FieldOptions, _proto_TypeTraits, _field_type, _is_packed>& id) { + typename _proto_TypeTraits::Repeated::MutableType to_add = + _proto_TypeTraits::Add(id.number(), _field_type, &_impl_._extensions_); + + return to_add; + } + + template <typename _proto_TypeTraits, + ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type, + bool _is_packed> + inline void AddExtension( + const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier< + FieldOptions, _proto_TypeTraits, _field_type, _is_packed>& id, + typename _proto_TypeTraits::Repeated::ConstType value) { + _proto_TypeTraits::Add(id.number(), _field_type, _is_packed, value, + &_impl_._extensions_); + + } + + template <typename _proto_TypeTraits, + ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type, + bool _is_packed> + inline const typename _proto_TypeTraits::Repeated::RepeatedFieldType& + GetRepeatedExtension( + const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier< + FieldOptions, _proto_TypeTraits, _field_type, _is_packed>& id) const { + + return _proto_TypeTraits::GetRepeated(id.number(), _impl_._extensions_); + } + + template <typename _proto_TypeTraits, + ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type, + bool _is_packed> + inline typename _proto_TypeTraits::Repeated::RepeatedFieldType* + MutableRepeatedExtension( + const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier< + FieldOptions, _proto_TypeTraits, _field_type, _is_packed>& id) { + + return _proto_TypeTraits::MutableRepeated(id.number(), _field_type, + _is_packed, &_impl_._extensions_); + } + + // @@protoc_insertion_point(class_scope:google.protobuf.FieldOptions) + private: + class _Internal; + + template <typename T> friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper; + typedef void InternalArenaConstructable_; + typedef void DestructorSkippable_; + struct Impl_ { + ::PROTOBUF_NAMESPACE_ID::internal::ExtensionSet _extensions_; + + ::PROTOBUF_NAMESPACE_ID::internal::HasBits<1> _has_bits_; + mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_; + ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::UninterpretedOption > uninterpreted_option_; + int ctype_; + int jstype_; + bool packed_; + bool lazy_; + bool unverified_lazy_; + bool deprecated_; + bool weak_; + }; + union { Impl_ _impl_; }; + friend struct ::TableStruct_google_2fprotobuf_2fdescriptor_2eproto; +}; +// ------------------------------------------------------------------- + +class PROTOBUF_EXPORT OneofOptions final : + public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.OneofOptions) */ { + public: + inline OneofOptions() : OneofOptions(nullptr) {} + ~OneofOptions() override; + explicit PROTOBUF_CONSTEXPR OneofOptions(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized); + + OneofOptions(const OneofOptions& from); + OneofOptions(OneofOptions&& from) noexcept + : OneofOptions() { + *this = ::std::move(from); + } + + inline OneofOptions& operator=(const OneofOptions& from) { + CopyFrom(from); + return *this; + } + inline OneofOptions& operator=(OneofOptions&& from) noexcept { + if (this == &from) return *this; + if (GetOwningArena() == from.GetOwningArena() + #ifdef PROTOBUF_FORCE_COPY_IN_MOVE + && GetOwningArena() != nullptr + #endif // !PROTOBUF_FORCE_COPY_IN_MOVE + ) { + InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + inline const ::PROTOBUF_NAMESPACE_ID::UnknownFieldSet& unknown_fields() const { + return _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance); + } + inline ::PROTOBUF_NAMESPACE_ID::UnknownFieldSet* mutable_unknown_fields() { + return _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); + } + + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* descriptor() { + return GetDescriptor(); + } + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() { + return default_instance().GetMetadata().descriptor; + } + static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() { + return default_instance().GetMetadata().reflection; + } + static const OneofOptions& default_instance() { + return *internal_default_instance(); + } + static inline const OneofOptions* internal_default_instance() { + return reinterpret_cast<const OneofOptions*>( + &_OneofOptions_default_instance_); + } + static constexpr int kIndexInFileMessages = + 16; + + friend void swap(OneofOptions& a, OneofOptions& b) { + a.Swap(&b); + } + inline void Swap(OneofOptions* other) { + if (other == this) return; + #ifdef PROTOBUF_FORCE_COPY_IN_SWAP + if (GetOwningArena() != nullptr && + GetOwningArena() == other->GetOwningArena()) { + #else // PROTOBUF_FORCE_COPY_IN_SWAP + if (GetOwningArena() == other->GetOwningArena()) { + #endif // !PROTOBUF_FORCE_COPY_IN_SWAP + InternalSwap(other); + } else { + ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(OneofOptions* other) { + if (other == this) return; + GOOGLE_DCHECK(GetOwningArena() == other->GetOwningArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + OneofOptions* New(::PROTOBUF_NAMESPACE_ID::Arena* arena = nullptr) const final { + return CreateMaybeMessage<OneofOptions>(arena); + } + using ::PROTOBUF_NAMESPACE_ID::Message::CopyFrom; + void CopyFrom(const OneofOptions& from); + using ::PROTOBUF_NAMESPACE_ID::Message::MergeFrom; + void MergeFrom( const OneofOptions& from) { + OneofOptions::MergeImpl(*this, from); + } + private: + static void MergeImpl(::PROTOBUF_NAMESPACE_ID::Message& to_msg, const ::PROTOBUF_NAMESPACE_ID::Message& from_msg); + public: + PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + bool IsInitialized() const final; + + size_t ByteSizeLong() const final; + const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final; + uint8_t* _InternalSerialize( + uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final; + int GetCachedSize() const final { return _impl_._cached_size_.Get(); } + + private: + void SharedCtor(::PROTOBUF_NAMESPACE_ID::Arena* arena, bool is_message_owned); + void SharedDtor(); + void SetCachedSize(int size) const final; + void InternalSwap(OneofOptions* other); + + private: + friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata; + static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() { + return "google.protobuf.OneofOptions"; + } + protected: + explicit OneofOptions(::PROTOBUF_NAMESPACE_ID::Arena* arena, + bool is_message_owned = false); + public: + + static const ClassData _class_data_; + const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*GetClassData() const final; + + ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final; + + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + + enum : int { + kUninterpretedOptionFieldNumber = 999, + }; + // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; + int uninterpreted_option_size() const; + private: + int _internal_uninterpreted_option_size() const; + public: + void clear_uninterpreted_option(); + ::PROTOBUF_NAMESPACE_ID::UninterpretedOption* mutable_uninterpreted_option(int index); + ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::UninterpretedOption >* + mutable_uninterpreted_option(); + private: + const ::PROTOBUF_NAMESPACE_ID::UninterpretedOption& _internal_uninterpreted_option(int index) const; + ::PROTOBUF_NAMESPACE_ID::UninterpretedOption* _internal_add_uninterpreted_option(); + public: + const ::PROTOBUF_NAMESPACE_ID::UninterpretedOption& uninterpreted_option(int index) const; + ::PROTOBUF_NAMESPACE_ID::UninterpretedOption* add_uninterpreted_option(); + const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::UninterpretedOption >& + uninterpreted_option() const; + + + template <typename _proto_TypeTraits, + ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type, + bool _is_packed> + inline bool HasExtension( + const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier< + OneofOptions, _proto_TypeTraits, _field_type, _is_packed>& id) const { + + return _impl_._extensions_.Has(id.number()); + } + + template <typename _proto_TypeTraits, + ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type, + bool _is_packed> + inline void ClearExtension( + const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier< + OneofOptions, _proto_TypeTraits, _field_type, _is_packed>& id) { + _impl_._extensions_.ClearExtension(id.number()); + + } + + template <typename _proto_TypeTraits, + ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type, + bool _is_packed> + inline int ExtensionSize( + const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier< + OneofOptions, _proto_TypeTraits, _field_type, _is_packed>& id) const { + + return _impl_._extensions_.ExtensionSize(id.number()); + } + + template <typename _proto_TypeTraits, + ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type, + bool _is_packed> + inline typename _proto_TypeTraits::Singular::ConstType GetExtension( + const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier< + OneofOptions, _proto_TypeTraits, _field_type, _is_packed>& id) const { + + return _proto_TypeTraits::Get(id.number(), _impl_._extensions_, + id.default_value()); + } + + template <typename _proto_TypeTraits, + ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type, + bool _is_packed> + inline typename _proto_TypeTraits::Singular::MutableType MutableExtension( + const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier< + OneofOptions, _proto_TypeTraits, _field_type, _is_packed>& id) { + + return _proto_TypeTraits::Mutable(id.number(), _field_type, + &_impl_._extensions_); + } + + template <typename _proto_TypeTraits, + ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type, + bool _is_packed> + inline void SetExtension( + const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier< + OneofOptions, _proto_TypeTraits, _field_type, _is_packed>& id, + typename _proto_TypeTraits::Singular::ConstType value) { + _proto_TypeTraits::Set(id.number(), _field_type, value, &_impl_._extensions_); + + } + + template <typename _proto_TypeTraits, + ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type, + bool _is_packed> + inline void SetAllocatedExtension( + const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier< + OneofOptions, _proto_TypeTraits, _field_type, _is_packed>& id, + typename _proto_TypeTraits::Singular::MutableType value) { + _proto_TypeTraits::SetAllocated(id.number(), _field_type, value, + &_impl_._extensions_); + + } + template <typename _proto_TypeTraits, + ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type, + bool _is_packed> + inline void UnsafeArenaSetAllocatedExtension( + const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier< + OneofOptions, _proto_TypeTraits, _field_type, _is_packed>& id, + typename _proto_TypeTraits::Singular::MutableType value) { + _proto_TypeTraits::UnsafeArenaSetAllocated(id.number(), _field_type, + value, &_impl_._extensions_); + + } + template <typename _proto_TypeTraits, + ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type, + bool _is_packed> + PROTOBUF_NODISCARD inline + typename _proto_TypeTraits::Singular::MutableType + ReleaseExtension( + const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier< + OneofOptions, _proto_TypeTraits, _field_type, _is_packed>& id) { + + return _proto_TypeTraits::Release(id.number(), _field_type, + &_impl_._extensions_); + } + template <typename _proto_TypeTraits, + ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type, + bool _is_packed> + inline typename _proto_TypeTraits::Singular::MutableType + UnsafeArenaReleaseExtension( + const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier< + OneofOptions, _proto_TypeTraits, _field_type, _is_packed>& id) { + + return _proto_TypeTraits::UnsafeArenaRelease(id.number(), _field_type, + &_impl_._extensions_); + } + + template <typename _proto_TypeTraits, + ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type, + bool _is_packed> + inline typename _proto_TypeTraits::Repeated::ConstType GetExtension( + const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier< + OneofOptions, _proto_TypeTraits, _field_type, _is_packed>& id, + int index) const { + + return _proto_TypeTraits::Get(id.number(), _impl_._extensions_, index); + } + + template <typename _proto_TypeTraits, + ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type, + bool _is_packed> + inline typename _proto_TypeTraits::Repeated::MutableType MutableExtension( + const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier< + OneofOptions, _proto_TypeTraits, _field_type, _is_packed>& id, + int index) { + + return _proto_TypeTraits::Mutable(id.number(), index, &_impl_._extensions_); + } + + template <typename _proto_TypeTraits, + ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type, + bool _is_packed> + inline void SetExtension( + const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier< + OneofOptions, _proto_TypeTraits, _field_type, _is_packed>& id, + int index, typename _proto_TypeTraits::Repeated::ConstType value) { + _proto_TypeTraits::Set(id.number(), index, value, &_impl_._extensions_); + + } + + template <typename _proto_TypeTraits, + ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type, + bool _is_packed> + inline typename _proto_TypeTraits::Repeated::MutableType AddExtension( + const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier< + OneofOptions, _proto_TypeTraits, _field_type, _is_packed>& id) { + typename _proto_TypeTraits::Repeated::MutableType to_add = + _proto_TypeTraits::Add(id.number(), _field_type, &_impl_._extensions_); + + return to_add; + } + + template <typename _proto_TypeTraits, + ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type, + bool _is_packed> + inline void AddExtension( + const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier< + OneofOptions, _proto_TypeTraits, _field_type, _is_packed>& id, + typename _proto_TypeTraits::Repeated::ConstType value) { + _proto_TypeTraits::Add(id.number(), _field_type, _is_packed, value, + &_impl_._extensions_); + + } + + template <typename _proto_TypeTraits, + ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type, + bool _is_packed> + inline const typename _proto_TypeTraits::Repeated::RepeatedFieldType& + GetRepeatedExtension( + const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier< + OneofOptions, _proto_TypeTraits, _field_type, _is_packed>& id) const { + + return _proto_TypeTraits::GetRepeated(id.number(), _impl_._extensions_); + } + + template <typename _proto_TypeTraits, + ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type, + bool _is_packed> + inline typename _proto_TypeTraits::Repeated::RepeatedFieldType* + MutableRepeatedExtension( + const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier< + OneofOptions, _proto_TypeTraits, _field_type, _is_packed>& id) { + + return _proto_TypeTraits::MutableRepeated(id.number(), _field_type, + _is_packed, &_impl_._extensions_); + } + + // @@protoc_insertion_point(class_scope:google.protobuf.OneofOptions) + private: + class _Internal; + + template <typename T> friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper; + typedef void InternalArenaConstructable_; + typedef void DestructorSkippable_; + struct Impl_ { + ::PROTOBUF_NAMESPACE_ID::internal::ExtensionSet _extensions_; + + ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::UninterpretedOption > uninterpreted_option_; + mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_; + }; + union { Impl_ _impl_; }; + friend struct ::TableStruct_google_2fprotobuf_2fdescriptor_2eproto; +}; +// ------------------------------------------------------------------- + +class PROTOBUF_EXPORT EnumOptions final : + public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.EnumOptions) */ { + public: + inline EnumOptions() : EnumOptions(nullptr) {} + ~EnumOptions() override; + explicit PROTOBUF_CONSTEXPR EnumOptions(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized); + + EnumOptions(const EnumOptions& from); + EnumOptions(EnumOptions&& from) noexcept + : EnumOptions() { + *this = ::std::move(from); + } + + inline EnumOptions& operator=(const EnumOptions& from) { + CopyFrom(from); + return *this; + } + inline EnumOptions& operator=(EnumOptions&& from) noexcept { + if (this == &from) return *this; + if (GetOwningArena() == from.GetOwningArena() + #ifdef PROTOBUF_FORCE_COPY_IN_MOVE + && GetOwningArena() != nullptr + #endif // !PROTOBUF_FORCE_COPY_IN_MOVE + ) { + InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + inline const ::PROTOBUF_NAMESPACE_ID::UnknownFieldSet& unknown_fields() const { + return _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance); + } + inline ::PROTOBUF_NAMESPACE_ID::UnknownFieldSet* mutable_unknown_fields() { + return _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); + } + + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* descriptor() { + return GetDescriptor(); + } + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() { + return default_instance().GetMetadata().descriptor; + } + static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() { + return default_instance().GetMetadata().reflection; + } + static const EnumOptions& default_instance() { + return *internal_default_instance(); + } + static inline const EnumOptions* internal_default_instance() { + return reinterpret_cast<const EnumOptions*>( + &_EnumOptions_default_instance_); + } + static constexpr int kIndexInFileMessages = + 17; + + friend void swap(EnumOptions& a, EnumOptions& b) { + a.Swap(&b); + } + inline void Swap(EnumOptions* other) { + if (other == this) return; + #ifdef PROTOBUF_FORCE_COPY_IN_SWAP + if (GetOwningArena() != nullptr && + GetOwningArena() == other->GetOwningArena()) { + #else // PROTOBUF_FORCE_COPY_IN_SWAP + if (GetOwningArena() == other->GetOwningArena()) { + #endif // !PROTOBUF_FORCE_COPY_IN_SWAP + InternalSwap(other); + } else { + ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(EnumOptions* other) { + if (other == this) return; + GOOGLE_DCHECK(GetOwningArena() == other->GetOwningArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + EnumOptions* New(::PROTOBUF_NAMESPACE_ID::Arena* arena = nullptr) const final { + return CreateMaybeMessage<EnumOptions>(arena); + } + using ::PROTOBUF_NAMESPACE_ID::Message::CopyFrom; + void CopyFrom(const EnumOptions& from); + using ::PROTOBUF_NAMESPACE_ID::Message::MergeFrom; + void MergeFrom( const EnumOptions& from) { + EnumOptions::MergeImpl(*this, from); + } + private: + static void MergeImpl(::PROTOBUF_NAMESPACE_ID::Message& to_msg, const ::PROTOBUF_NAMESPACE_ID::Message& from_msg); + public: + PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + bool IsInitialized() const final; + + size_t ByteSizeLong() const final; + const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final; + uint8_t* _InternalSerialize( + uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final; + int GetCachedSize() const final { return _impl_._cached_size_.Get(); } + + private: + void SharedCtor(::PROTOBUF_NAMESPACE_ID::Arena* arena, bool is_message_owned); + void SharedDtor(); + void SetCachedSize(int size) const final; + void InternalSwap(EnumOptions* other); + + private: + friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata; + static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() { + return "google.protobuf.EnumOptions"; + } + protected: + explicit EnumOptions(::PROTOBUF_NAMESPACE_ID::Arena* arena, + bool is_message_owned = false); + public: + + static const ClassData _class_data_; + const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*GetClassData() const final; + + ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final; + + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + + enum : int { + kUninterpretedOptionFieldNumber = 999, + kAllowAliasFieldNumber = 2, + kDeprecatedFieldNumber = 3, + }; + // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; + int uninterpreted_option_size() const; + private: + int _internal_uninterpreted_option_size() const; + public: + void clear_uninterpreted_option(); + ::PROTOBUF_NAMESPACE_ID::UninterpretedOption* mutable_uninterpreted_option(int index); + ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::UninterpretedOption >* + mutable_uninterpreted_option(); + private: + const ::PROTOBUF_NAMESPACE_ID::UninterpretedOption& _internal_uninterpreted_option(int index) const; + ::PROTOBUF_NAMESPACE_ID::UninterpretedOption* _internal_add_uninterpreted_option(); + public: + const ::PROTOBUF_NAMESPACE_ID::UninterpretedOption& uninterpreted_option(int index) const; + ::PROTOBUF_NAMESPACE_ID::UninterpretedOption* add_uninterpreted_option(); + const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::UninterpretedOption >& + uninterpreted_option() const; + + // optional bool allow_alias = 2; + bool has_allow_alias() const; + private: + bool _internal_has_allow_alias() const; + public: + void clear_allow_alias(); + bool allow_alias() const; + void set_allow_alias(bool value); + private: + bool _internal_allow_alias() const; + void _internal_set_allow_alias(bool value); + public: + + // optional bool deprecated = 3 [default = false]; + bool has_deprecated() const; + private: + bool _internal_has_deprecated() const; + public: + void clear_deprecated(); + bool deprecated() const; + void set_deprecated(bool value); + private: + bool _internal_deprecated() const; + void _internal_set_deprecated(bool value); + public: + + + template <typename _proto_TypeTraits, + ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type, + bool _is_packed> + inline bool HasExtension( + const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier< + EnumOptions, _proto_TypeTraits, _field_type, _is_packed>& id) const { + + return _impl_._extensions_.Has(id.number()); + } + + template <typename _proto_TypeTraits, + ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type, + bool _is_packed> + inline void ClearExtension( + const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier< + EnumOptions, _proto_TypeTraits, _field_type, _is_packed>& id) { + _impl_._extensions_.ClearExtension(id.number()); + + } + + template <typename _proto_TypeTraits, + ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type, + bool _is_packed> + inline int ExtensionSize( + const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier< + EnumOptions, _proto_TypeTraits, _field_type, _is_packed>& id) const { + + return _impl_._extensions_.ExtensionSize(id.number()); + } + + template <typename _proto_TypeTraits, + ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type, + bool _is_packed> + inline typename _proto_TypeTraits::Singular::ConstType GetExtension( + const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier< + EnumOptions, _proto_TypeTraits, _field_type, _is_packed>& id) const { + + return _proto_TypeTraits::Get(id.number(), _impl_._extensions_, + id.default_value()); + } + + template <typename _proto_TypeTraits, + ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type, + bool _is_packed> + inline typename _proto_TypeTraits::Singular::MutableType MutableExtension( + const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier< + EnumOptions, _proto_TypeTraits, _field_type, _is_packed>& id) { + + return _proto_TypeTraits::Mutable(id.number(), _field_type, + &_impl_._extensions_); + } + + template <typename _proto_TypeTraits, + ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type, + bool _is_packed> + inline void SetExtension( + const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier< + EnumOptions, _proto_TypeTraits, _field_type, _is_packed>& id, + typename _proto_TypeTraits::Singular::ConstType value) { + _proto_TypeTraits::Set(id.number(), _field_type, value, &_impl_._extensions_); + + } + + template <typename _proto_TypeTraits, + ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type, + bool _is_packed> + inline void SetAllocatedExtension( + const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier< + EnumOptions, _proto_TypeTraits, _field_type, _is_packed>& id, + typename _proto_TypeTraits::Singular::MutableType value) { + _proto_TypeTraits::SetAllocated(id.number(), _field_type, value, + &_impl_._extensions_); + + } + template <typename _proto_TypeTraits, + ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type, + bool _is_packed> + inline void UnsafeArenaSetAllocatedExtension( + const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier< + EnumOptions, _proto_TypeTraits, _field_type, _is_packed>& id, + typename _proto_TypeTraits::Singular::MutableType value) { + _proto_TypeTraits::UnsafeArenaSetAllocated(id.number(), _field_type, + value, &_impl_._extensions_); + + } + template <typename _proto_TypeTraits, + ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type, + bool _is_packed> + PROTOBUF_NODISCARD inline + typename _proto_TypeTraits::Singular::MutableType + ReleaseExtension( + const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier< + EnumOptions, _proto_TypeTraits, _field_type, _is_packed>& id) { + + return _proto_TypeTraits::Release(id.number(), _field_type, + &_impl_._extensions_); + } + template <typename _proto_TypeTraits, + ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type, + bool _is_packed> + inline typename _proto_TypeTraits::Singular::MutableType + UnsafeArenaReleaseExtension( + const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier< + EnumOptions, _proto_TypeTraits, _field_type, _is_packed>& id) { + + return _proto_TypeTraits::UnsafeArenaRelease(id.number(), _field_type, + &_impl_._extensions_); + } + + template <typename _proto_TypeTraits, + ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type, + bool _is_packed> + inline typename _proto_TypeTraits::Repeated::ConstType GetExtension( + const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier< + EnumOptions, _proto_TypeTraits, _field_type, _is_packed>& id, + int index) const { + + return _proto_TypeTraits::Get(id.number(), _impl_._extensions_, index); + } + + template <typename _proto_TypeTraits, + ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type, + bool _is_packed> + inline typename _proto_TypeTraits::Repeated::MutableType MutableExtension( + const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier< + EnumOptions, _proto_TypeTraits, _field_type, _is_packed>& id, + int index) { + + return _proto_TypeTraits::Mutable(id.number(), index, &_impl_._extensions_); + } + + template <typename _proto_TypeTraits, + ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type, + bool _is_packed> + inline void SetExtension( + const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier< + EnumOptions, _proto_TypeTraits, _field_type, _is_packed>& id, + int index, typename _proto_TypeTraits::Repeated::ConstType value) { + _proto_TypeTraits::Set(id.number(), index, value, &_impl_._extensions_); + + } + + template <typename _proto_TypeTraits, + ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type, + bool _is_packed> + inline typename _proto_TypeTraits::Repeated::MutableType AddExtension( + const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier< + EnumOptions, _proto_TypeTraits, _field_type, _is_packed>& id) { + typename _proto_TypeTraits::Repeated::MutableType to_add = + _proto_TypeTraits::Add(id.number(), _field_type, &_impl_._extensions_); + + return to_add; + } + + template <typename _proto_TypeTraits, + ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type, + bool _is_packed> + inline void AddExtension( + const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier< + EnumOptions, _proto_TypeTraits, _field_type, _is_packed>& id, + typename _proto_TypeTraits::Repeated::ConstType value) { + _proto_TypeTraits::Add(id.number(), _field_type, _is_packed, value, + &_impl_._extensions_); + + } + + template <typename _proto_TypeTraits, + ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type, + bool _is_packed> + inline const typename _proto_TypeTraits::Repeated::RepeatedFieldType& + GetRepeatedExtension( + const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier< + EnumOptions, _proto_TypeTraits, _field_type, _is_packed>& id) const { + + return _proto_TypeTraits::GetRepeated(id.number(), _impl_._extensions_); + } + + template <typename _proto_TypeTraits, + ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type, + bool _is_packed> + inline typename _proto_TypeTraits::Repeated::RepeatedFieldType* + MutableRepeatedExtension( + const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier< + EnumOptions, _proto_TypeTraits, _field_type, _is_packed>& id) { + + return _proto_TypeTraits::MutableRepeated(id.number(), _field_type, + _is_packed, &_impl_._extensions_); + } + + // @@protoc_insertion_point(class_scope:google.protobuf.EnumOptions) + private: + class _Internal; + + template <typename T> friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper; + typedef void InternalArenaConstructable_; + typedef void DestructorSkippable_; + struct Impl_ { + ::PROTOBUF_NAMESPACE_ID::internal::ExtensionSet _extensions_; + + ::PROTOBUF_NAMESPACE_ID::internal::HasBits<1> _has_bits_; + mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_; + ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::UninterpretedOption > uninterpreted_option_; + bool allow_alias_; + bool deprecated_; + }; + union { Impl_ _impl_; }; + friend struct ::TableStruct_google_2fprotobuf_2fdescriptor_2eproto; +}; +// ------------------------------------------------------------------- + +class PROTOBUF_EXPORT EnumValueOptions final : + public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.EnumValueOptions) */ { + public: + inline EnumValueOptions() : EnumValueOptions(nullptr) {} + ~EnumValueOptions() override; + explicit PROTOBUF_CONSTEXPR EnumValueOptions(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized); + + EnumValueOptions(const EnumValueOptions& from); + EnumValueOptions(EnumValueOptions&& from) noexcept + : EnumValueOptions() { + *this = ::std::move(from); + } + + inline EnumValueOptions& operator=(const EnumValueOptions& from) { + CopyFrom(from); + return *this; + } + inline EnumValueOptions& operator=(EnumValueOptions&& from) noexcept { + if (this == &from) return *this; + if (GetOwningArena() == from.GetOwningArena() + #ifdef PROTOBUF_FORCE_COPY_IN_MOVE + && GetOwningArena() != nullptr + #endif // !PROTOBUF_FORCE_COPY_IN_MOVE + ) { + InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + inline const ::PROTOBUF_NAMESPACE_ID::UnknownFieldSet& unknown_fields() const { + return _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance); + } + inline ::PROTOBUF_NAMESPACE_ID::UnknownFieldSet* mutable_unknown_fields() { + return _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); + } + + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* descriptor() { + return GetDescriptor(); + } + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() { + return default_instance().GetMetadata().descriptor; + } + static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() { + return default_instance().GetMetadata().reflection; + } + static const EnumValueOptions& default_instance() { + return *internal_default_instance(); + } + static inline const EnumValueOptions* internal_default_instance() { + return reinterpret_cast<const EnumValueOptions*>( + &_EnumValueOptions_default_instance_); + } + static constexpr int kIndexInFileMessages = + 18; + + friend void swap(EnumValueOptions& a, EnumValueOptions& b) { + a.Swap(&b); + } + inline void Swap(EnumValueOptions* other) { + if (other == this) return; + #ifdef PROTOBUF_FORCE_COPY_IN_SWAP + if (GetOwningArena() != nullptr && + GetOwningArena() == other->GetOwningArena()) { + #else // PROTOBUF_FORCE_COPY_IN_SWAP + if (GetOwningArena() == other->GetOwningArena()) { + #endif // !PROTOBUF_FORCE_COPY_IN_SWAP + InternalSwap(other); + } else { + ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(EnumValueOptions* other) { + if (other == this) return; + GOOGLE_DCHECK(GetOwningArena() == other->GetOwningArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + EnumValueOptions* New(::PROTOBUF_NAMESPACE_ID::Arena* arena = nullptr) const final { + return CreateMaybeMessage<EnumValueOptions>(arena); + } + using ::PROTOBUF_NAMESPACE_ID::Message::CopyFrom; + void CopyFrom(const EnumValueOptions& from); + using ::PROTOBUF_NAMESPACE_ID::Message::MergeFrom; + void MergeFrom( const EnumValueOptions& from) { + EnumValueOptions::MergeImpl(*this, from); + } + private: + static void MergeImpl(::PROTOBUF_NAMESPACE_ID::Message& to_msg, const ::PROTOBUF_NAMESPACE_ID::Message& from_msg); + public: + PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + bool IsInitialized() const final; + + size_t ByteSizeLong() const final; + const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final; + uint8_t* _InternalSerialize( + uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final; + int GetCachedSize() const final { return _impl_._cached_size_.Get(); } + + private: + void SharedCtor(::PROTOBUF_NAMESPACE_ID::Arena* arena, bool is_message_owned); + void SharedDtor(); + void SetCachedSize(int size) const final; + void InternalSwap(EnumValueOptions* other); + + private: + friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata; + static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() { + return "google.protobuf.EnumValueOptions"; + } + protected: + explicit EnumValueOptions(::PROTOBUF_NAMESPACE_ID::Arena* arena, + bool is_message_owned = false); + public: + + static const ClassData _class_data_; + const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*GetClassData() const final; + + ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final; + + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + + enum : int { + kUninterpretedOptionFieldNumber = 999, + kDeprecatedFieldNumber = 1, + }; + // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; + int uninterpreted_option_size() const; + private: + int _internal_uninterpreted_option_size() const; + public: + void clear_uninterpreted_option(); + ::PROTOBUF_NAMESPACE_ID::UninterpretedOption* mutable_uninterpreted_option(int index); + ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::UninterpretedOption >* + mutable_uninterpreted_option(); + private: + const ::PROTOBUF_NAMESPACE_ID::UninterpretedOption& _internal_uninterpreted_option(int index) const; + ::PROTOBUF_NAMESPACE_ID::UninterpretedOption* _internal_add_uninterpreted_option(); + public: + const ::PROTOBUF_NAMESPACE_ID::UninterpretedOption& uninterpreted_option(int index) const; + ::PROTOBUF_NAMESPACE_ID::UninterpretedOption* add_uninterpreted_option(); + const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::UninterpretedOption >& + uninterpreted_option() const; + + // optional bool deprecated = 1 [default = false]; + bool has_deprecated() const; + private: + bool _internal_has_deprecated() const; + public: + void clear_deprecated(); + bool deprecated() const; + void set_deprecated(bool value); + private: + bool _internal_deprecated() const; + void _internal_set_deprecated(bool value); + public: + + + template <typename _proto_TypeTraits, + ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type, + bool _is_packed> + inline bool HasExtension( + const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier< + EnumValueOptions, _proto_TypeTraits, _field_type, _is_packed>& id) const { + + return _impl_._extensions_.Has(id.number()); + } + + template <typename _proto_TypeTraits, + ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type, + bool _is_packed> + inline void ClearExtension( + const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier< + EnumValueOptions, _proto_TypeTraits, _field_type, _is_packed>& id) { + _impl_._extensions_.ClearExtension(id.number()); + + } + + template <typename _proto_TypeTraits, + ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type, + bool _is_packed> + inline int ExtensionSize( + const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier< + EnumValueOptions, _proto_TypeTraits, _field_type, _is_packed>& id) const { + + return _impl_._extensions_.ExtensionSize(id.number()); + } + + template <typename _proto_TypeTraits, + ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type, + bool _is_packed> + inline typename _proto_TypeTraits::Singular::ConstType GetExtension( + const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier< + EnumValueOptions, _proto_TypeTraits, _field_type, _is_packed>& id) const { + + return _proto_TypeTraits::Get(id.number(), _impl_._extensions_, + id.default_value()); + } + + template <typename _proto_TypeTraits, + ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type, + bool _is_packed> + inline typename _proto_TypeTraits::Singular::MutableType MutableExtension( + const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier< + EnumValueOptions, _proto_TypeTraits, _field_type, _is_packed>& id) { + + return _proto_TypeTraits::Mutable(id.number(), _field_type, + &_impl_._extensions_); + } + + template <typename _proto_TypeTraits, + ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type, + bool _is_packed> + inline void SetExtension( + const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier< + EnumValueOptions, _proto_TypeTraits, _field_type, _is_packed>& id, + typename _proto_TypeTraits::Singular::ConstType value) { + _proto_TypeTraits::Set(id.number(), _field_type, value, &_impl_._extensions_); + + } + + template <typename _proto_TypeTraits, + ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type, + bool _is_packed> + inline void SetAllocatedExtension( + const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier< + EnumValueOptions, _proto_TypeTraits, _field_type, _is_packed>& id, + typename _proto_TypeTraits::Singular::MutableType value) { + _proto_TypeTraits::SetAllocated(id.number(), _field_type, value, + &_impl_._extensions_); + + } + template <typename _proto_TypeTraits, + ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type, + bool _is_packed> + inline void UnsafeArenaSetAllocatedExtension( + const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier< + EnumValueOptions, _proto_TypeTraits, _field_type, _is_packed>& id, + typename _proto_TypeTraits::Singular::MutableType value) { + _proto_TypeTraits::UnsafeArenaSetAllocated(id.number(), _field_type, + value, &_impl_._extensions_); + + } + template <typename _proto_TypeTraits, + ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type, + bool _is_packed> + PROTOBUF_NODISCARD inline + typename _proto_TypeTraits::Singular::MutableType + ReleaseExtension( + const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier< + EnumValueOptions, _proto_TypeTraits, _field_type, _is_packed>& id) { + + return _proto_TypeTraits::Release(id.number(), _field_type, + &_impl_._extensions_); + } + template <typename _proto_TypeTraits, + ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type, + bool _is_packed> + inline typename _proto_TypeTraits::Singular::MutableType + UnsafeArenaReleaseExtension( + const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier< + EnumValueOptions, _proto_TypeTraits, _field_type, _is_packed>& id) { + + return _proto_TypeTraits::UnsafeArenaRelease(id.number(), _field_type, + &_impl_._extensions_); + } + + template <typename _proto_TypeTraits, + ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type, + bool _is_packed> + inline typename _proto_TypeTraits::Repeated::ConstType GetExtension( + const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier< + EnumValueOptions, _proto_TypeTraits, _field_type, _is_packed>& id, + int index) const { + + return _proto_TypeTraits::Get(id.number(), _impl_._extensions_, index); + } + + template <typename _proto_TypeTraits, + ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type, + bool _is_packed> + inline typename _proto_TypeTraits::Repeated::MutableType MutableExtension( + const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier< + EnumValueOptions, _proto_TypeTraits, _field_type, _is_packed>& id, + int index) { + + return _proto_TypeTraits::Mutable(id.number(), index, &_impl_._extensions_); + } + + template <typename _proto_TypeTraits, + ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type, + bool _is_packed> + inline void SetExtension( + const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier< + EnumValueOptions, _proto_TypeTraits, _field_type, _is_packed>& id, + int index, typename _proto_TypeTraits::Repeated::ConstType value) { + _proto_TypeTraits::Set(id.number(), index, value, &_impl_._extensions_); + + } + + template <typename _proto_TypeTraits, + ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type, + bool _is_packed> + inline typename _proto_TypeTraits::Repeated::MutableType AddExtension( + const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier< + EnumValueOptions, _proto_TypeTraits, _field_type, _is_packed>& id) { + typename _proto_TypeTraits::Repeated::MutableType to_add = + _proto_TypeTraits::Add(id.number(), _field_type, &_impl_._extensions_); + + return to_add; + } + + template <typename _proto_TypeTraits, + ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type, + bool _is_packed> + inline void AddExtension( + const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier< + EnumValueOptions, _proto_TypeTraits, _field_type, _is_packed>& id, + typename _proto_TypeTraits::Repeated::ConstType value) { + _proto_TypeTraits::Add(id.number(), _field_type, _is_packed, value, + &_impl_._extensions_); + + } + + template <typename _proto_TypeTraits, + ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type, + bool _is_packed> + inline const typename _proto_TypeTraits::Repeated::RepeatedFieldType& + GetRepeatedExtension( + const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier< + EnumValueOptions, _proto_TypeTraits, _field_type, _is_packed>& id) const { + + return _proto_TypeTraits::GetRepeated(id.number(), _impl_._extensions_); + } + + template <typename _proto_TypeTraits, + ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type, + bool _is_packed> + inline typename _proto_TypeTraits::Repeated::RepeatedFieldType* + MutableRepeatedExtension( + const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier< + EnumValueOptions, _proto_TypeTraits, _field_type, _is_packed>& id) { + + return _proto_TypeTraits::MutableRepeated(id.number(), _field_type, + _is_packed, &_impl_._extensions_); + } + + // @@protoc_insertion_point(class_scope:google.protobuf.EnumValueOptions) + private: + class _Internal; + + template <typename T> friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper; + typedef void InternalArenaConstructable_; + typedef void DestructorSkippable_; + struct Impl_ { + ::PROTOBUF_NAMESPACE_ID::internal::ExtensionSet _extensions_; + + ::PROTOBUF_NAMESPACE_ID::internal::HasBits<1> _has_bits_; + mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_; + ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::UninterpretedOption > uninterpreted_option_; + bool deprecated_; + }; + union { Impl_ _impl_; }; + friend struct ::TableStruct_google_2fprotobuf_2fdescriptor_2eproto; +}; +// ------------------------------------------------------------------- + +class PROTOBUF_EXPORT ServiceOptions final : + public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.ServiceOptions) */ { + public: + inline ServiceOptions() : ServiceOptions(nullptr) {} + ~ServiceOptions() override; + explicit PROTOBUF_CONSTEXPR ServiceOptions(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized); + + ServiceOptions(const ServiceOptions& from); + ServiceOptions(ServiceOptions&& from) noexcept + : ServiceOptions() { + *this = ::std::move(from); + } + + inline ServiceOptions& operator=(const ServiceOptions& from) { + CopyFrom(from); + return *this; + } + inline ServiceOptions& operator=(ServiceOptions&& from) noexcept { + if (this == &from) return *this; + if (GetOwningArena() == from.GetOwningArena() + #ifdef PROTOBUF_FORCE_COPY_IN_MOVE + && GetOwningArena() != nullptr + #endif // !PROTOBUF_FORCE_COPY_IN_MOVE + ) { + InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + inline const ::PROTOBUF_NAMESPACE_ID::UnknownFieldSet& unknown_fields() const { + return _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance); + } + inline ::PROTOBUF_NAMESPACE_ID::UnknownFieldSet* mutable_unknown_fields() { + return _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); + } + + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* descriptor() { + return GetDescriptor(); + } + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() { + return default_instance().GetMetadata().descriptor; + } + static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() { + return default_instance().GetMetadata().reflection; + } + static const ServiceOptions& default_instance() { + return *internal_default_instance(); + } + static inline const ServiceOptions* internal_default_instance() { + return reinterpret_cast<const ServiceOptions*>( + &_ServiceOptions_default_instance_); + } + static constexpr int kIndexInFileMessages = + 19; + + friend void swap(ServiceOptions& a, ServiceOptions& b) { + a.Swap(&b); + } + inline void Swap(ServiceOptions* other) { + if (other == this) return; + #ifdef PROTOBUF_FORCE_COPY_IN_SWAP + if (GetOwningArena() != nullptr && + GetOwningArena() == other->GetOwningArena()) { + #else // PROTOBUF_FORCE_COPY_IN_SWAP + if (GetOwningArena() == other->GetOwningArena()) { + #endif // !PROTOBUF_FORCE_COPY_IN_SWAP + InternalSwap(other); + } else { + ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(ServiceOptions* other) { + if (other == this) return; + GOOGLE_DCHECK(GetOwningArena() == other->GetOwningArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + ServiceOptions* New(::PROTOBUF_NAMESPACE_ID::Arena* arena = nullptr) const final { + return CreateMaybeMessage<ServiceOptions>(arena); + } + using ::PROTOBUF_NAMESPACE_ID::Message::CopyFrom; + void CopyFrom(const ServiceOptions& from); + using ::PROTOBUF_NAMESPACE_ID::Message::MergeFrom; + void MergeFrom( const ServiceOptions& from) { + ServiceOptions::MergeImpl(*this, from); + } + private: + static void MergeImpl(::PROTOBUF_NAMESPACE_ID::Message& to_msg, const ::PROTOBUF_NAMESPACE_ID::Message& from_msg); + public: + PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + bool IsInitialized() const final; + + size_t ByteSizeLong() const final; + const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final; + uint8_t* _InternalSerialize( + uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final; + int GetCachedSize() const final { return _impl_._cached_size_.Get(); } + + private: + void SharedCtor(::PROTOBUF_NAMESPACE_ID::Arena* arena, bool is_message_owned); + void SharedDtor(); + void SetCachedSize(int size) const final; + void InternalSwap(ServiceOptions* other); + + private: + friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata; + static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() { + return "google.protobuf.ServiceOptions"; + } + protected: + explicit ServiceOptions(::PROTOBUF_NAMESPACE_ID::Arena* arena, + bool is_message_owned = false); + public: + + static const ClassData _class_data_; + const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*GetClassData() const final; + + ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final; + + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + + enum : int { + kUninterpretedOptionFieldNumber = 999, + kDeprecatedFieldNumber = 33, + }; + // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; + int uninterpreted_option_size() const; + private: + int _internal_uninterpreted_option_size() const; + public: + void clear_uninterpreted_option(); + ::PROTOBUF_NAMESPACE_ID::UninterpretedOption* mutable_uninterpreted_option(int index); + ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::UninterpretedOption >* + mutable_uninterpreted_option(); + private: + const ::PROTOBUF_NAMESPACE_ID::UninterpretedOption& _internal_uninterpreted_option(int index) const; + ::PROTOBUF_NAMESPACE_ID::UninterpretedOption* _internal_add_uninterpreted_option(); + public: + const ::PROTOBUF_NAMESPACE_ID::UninterpretedOption& uninterpreted_option(int index) const; + ::PROTOBUF_NAMESPACE_ID::UninterpretedOption* add_uninterpreted_option(); + const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::UninterpretedOption >& + uninterpreted_option() const; + + // optional bool deprecated = 33 [default = false]; + bool has_deprecated() const; + private: + bool _internal_has_deprecated() const; + public: + void clear_deprecated(); + bool deprecated() const; + void set_deprecated(bool value); + private: + bool _internal_deprecated() const; + void _internal_set_deprecated(bool value); + public: + + + template <typename _proto_TypeTraits, + ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type, + bool _is_packed> + inline bool HasExtension( + const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier< + ServiceOptions, _proto_TypeTraits, _field_type, _is_packed>& id) const { + + return _impl_._extensions_.Has(id.number()); + } + + template <typename _proto_TypeTraits, + ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type, + bool _is_packed> + inline void ClearExtension( + const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier< + ServiceOptions, _proto_TypeTraits, _field_type, _is_packed>& id) { + _impl_._extensions_.ClearExtension(id.number()); + + } + + template <typename _proto_TypeTraits, + ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type, + bool _is_packed> + inline int ExtensionSize( + const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier< + ServiceOptions, _proto_TypeTraits, _field_type, _is_packed>& id) const { + + return _impl_._extensions_.ExtensionSize(id.number()); + } + + template <typename _proto_TypeTraits, + ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type, + bool _is_packed> + inline typename _proto_TypeTraits::Singular::ConstType GetExtension( + const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier< + ServiceOptions, _proto_TypeTraits, _field_type, _is_packed>& id) const { + + return _proto_TypeTraits::Get(id.number(), _impl_._extensions_, + id.default_value()); + } + + template <typename _proto_TypeTraits, + ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type, + bool _is_packed> + inline typename _proto_TypeTraits::Singular::MutableType MutableExtension( + const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier< + ServiceOptions, _proto_TypeTraits, _field_type, _is_packed>& id) { + + return _proto_TypeTraits::Mutable(id.number(), _field_type, + &_impl_._extensions_); + } + + template <typename _proto_TypeTraits, + ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type, + bool _is_packed> + inline void SetExtension( + const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier< + ServiceOptions, _proto_TypeTraits, _field_type, _is_packed>& id, + typename _proto_TypeTraits::Singular::ConstType value) { + _proto_TypeTraits::Set(id.number(), _field_type, value, &_impl_._extensions_); + + } + + template <typename _proto_TypeTraits, + ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type, + bool _is_packed> + inline void SetAllocatedExtension( + const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier< + ServiceOptions, _proto_TypeTraits, _field_type, _is_packed>& id, + typename _proto_TypeTraits::Singular::MutableType value) { + _proto_TypeTraits::SetAllocated(id.number(), _field_type, value, + &_impl_._extensions_); + + } + template <typename _proto_TypeTraits, + ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type, + bool _is_packed> + inline void UnsafeArenaSetAllocatedExtension( + const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier< + ServiceOptions, _proto_TypeTraits, _field_type, _is_packed>& id, + typename _proto_TypeTraits::Singular::MutableType value) { + _proto_TypeTraits::UnsafeArenaSetAllocated(id.number(), _field_type, + value, &_impl_._extensions_); + + } + template <typename _proto_TypeTraits, + ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type, + bool _is_packed> + PROTOBUF_NODISCARD inline + typename _proto_TypeTraits::Singular::MutableType + ReleaseExtension( + const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier< + ServiceOptions, _proto_TypeTraits, _field_type, _is_packed>& id) { + + return _proto_TypeTraits::Release(id.number(), _field_type, + &_impl_._extensions_); + } + template <typename _proto_TypeTraits, + ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type, + bool _is_packed> + inline typename _proto_TypeTraits::Singular::MutableType + UnsafeArenaReleaseExtension( + const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier< + ServiceOptions, _proto_TypeTraits, _field_type, _is_packed>& id) { + + return _proto_TypeTraits::UnsafeArenaRelease(id.number(), _field_type, + &_impl_._extensions_); + } + + template <typename _proto_TypeTraits, + ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type, + bool _is_packed> + inline typename _proto_TypeTraits::Repeated::ConstType GetExtension( + const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier< + ServiceOptions, _proto_TypeTraits, _field_type, _is_packed>& id, + int index) const { + + return _proto_TypeTraits::Get(id.number(), _impl_._extensions_, index); + } + + template <typename _proto_TypeTraits, + ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type, + bool _is_packed> + inline typename _proto_TypeTraits::Repeated::MutableType MutableExtension( + const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier< + ServiceOptions, _proto_TypeTraits, _field_type, _is_packed>& id, + int index) { + + return _proto_TypeTraits::Mutable(id.number(), index, &_impl_._extensions_); + } + + template <typename _proto_TypeTraits, + ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type, + bool _is_packed> + inline void SetExtension( + const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier< + ServiceOptions, _proto_TypeTraits, _field_type, _is_packed>& id, + int index, typename _proto_TypeTraits::Repeated::ConstType value) { + _proto_TypeTraits::Set(id.number(), index, value, &_impl_._extensions_); + + } + + template <typename _proto_TypeTraits, + ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type, + bool _is_packed> + inline typename _proto_TypeTraits::Repeated::MutableType AddExtension( + const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier< + ServiceOptions, _proto_TypeTraits, _field_type, _is_packed>& id) { + typename _proto_TypeTraits::Repeated::MutableType to_add = + _proto_TypeTraits::Add(id.number(), _field_type, &_impl_._extensions_); + + return to_add; + } + + template <typename _proto_TypeTraits, + ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type, + bool _is_packed> + inline void AddExtension( + const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier< + ServiceOptions, _proto_TypeTraits, _field_type, _is_packed>& id, + typename _proto_TypeTraits::Repeated::ConstType value) { + _proto_TypeTraits::Add(id.number(), _field_type, _is_packed, value, + &_impl_._extensions_); + + } + + template <typename _proto_TypeTraits, + ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type, + bool _is_packed> + inline const typename _proto_TypeTraits::Repeated::RepeatedFieldType& + GetRepeatedExtension( + const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier< + ServiceOptions, _proto_TypeTraits, _field_type, _is_packed>& id) const { + + return _proto_TypeTraits::GetRepeated(id.number(), _impl_._extensions_); + } + + template <typename _proto_TypeTraits, + ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type, + bool _is_packed> + inline typename _proto_TypeTraits::Repeated::RepeatedFieldType* + MutableRepeatedExtension( + const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier< + ServiceOptions, _proto_TypeTraits, _field_type, _is_packed>& id) { + + return _proto_TypeTraits::MutableRepeated(id.number(), _field_type, + _is_packed, &_impl_._extensions_); + } + + // @@protoc_insertion_point(class_scope:google.protobuf.ServiceOptions) + private: + class _Internal; + + template <typename T> friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper; + typedef void InternalArenaConstructable_; + typedef void DestructorSkippable_; + struct Impl_ { + ::PROTOBUF_NAMESPACE_ID::internal::ExtensionSet _extensions_; + + ::PROTOBUF_NAMESPACE_ID::internal::HasBits<1> _has_bits_; + mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_; + ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::UninterpretedOption > uninterpreted_option_; + bool deprecated_; + }; + union { Impl_ _impl_; }; + friend struct ::TableStruct_google_2fprotobuf_2fdescriptor_2eproto; +}; +// ------------------------------------------------------------------- + +class PROTOBUF_EXPORT MethodOptions final : + public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.MethodOptions) */ { + public: + inline MethodOptions() : MethodOptions(nullptr) {} + ~MethodOptions() override; + explicit PROTOBUF_CONSTEXPR MethodOptions(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized); + + MethodOptions(const MethodOptions& from); + MethodOptions(MethodOptions&& from) noexcept + : MethodOptions() { + *this = ::std::move(from); + } + + inline MethodOptions& operator=(const MethodOptions& from) { + CopyFrom(from); + return *this; + } + inline MethodOptions& operator=(MethodOptions&& from) noexcept { + if (this == &from) return *this; + if (GetOwningArena() == from.GetOwningArena() + #ifdef PROTOBUF_FORCE_COPY_IN_MOVE + && GetOwningArena() != nullptr + #endif // !PROTOBUF_FORCE_COPY_IN_MOVE + ) { + InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + inline const ::PROTOBUF_NAMESPACE_ID::UnknownFieldSet& unknown_fields() const { + return _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance); + } + inline ::PROTOBUF_NAMESPACE_ID::UnknownFieldSet* mutable_unknown_fields() { + return _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); + } + + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* descriptor() { + return GetDescriptor(); + } + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() { + return default_instance().GetMetadata().descriptor; + } + static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() { + return default_instance().GetMetadata().reflection; + } + static const MethodOptions& default_instance() { + return *internal_default_instance(); + } + static inline const MethodOptions* internal_default_instance() { + return reinterpret_cast<const MethodOptions*>( + &_MethodOptions_default_instance_); + } + static constexpr int kIndexInFileMessages = + 20; + + friend void swap(MethodOptions& a, MethodOptions& b) { + a.Swap(&b); + } + inline void Swap(MethodOptions* other) { + if (other == this) return; + #ifdef PROTOBUF_FORCE_COPY_IN_SWAP + if (GetOwningArena() != nullptr && + GetOwningArena() == other->GetOwningArena()) { + #else // PROTOBUF_FORCE_COPY_IN_SWAP + if (GetOwningArena() == other->GetOwningArena()) { + #endif // !PROTOBUF_FORCE_COPY_IN_SWAP + InternalSwap(other); + } else { + ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(MethodOptions* other) { + if (other == this) return; + GOOGLE_DCHECK(GetOwningArena() == other->GetOwningArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + MethodOptions* New(::PROTOBUF_NAMESPACE_ID::Arena* arena = nullptr) const final { + return CreateMaybeMessage<MethodOptions>(arena); + } + using ::PROTOBUF_NAMESPACE_ID::Message::CopyFrom; + void CopyFrom(const MethodOptions& from); + using ::PROTOBUF_NAMESPACE_ID::Message::MergeFrom; + void MergeFrom( const MethodOptions& from) { + MethodOptions::MergeImpl(*this, from); + } + private: + static void MergeImpl(::PROTOBUF_NAMESPACE_ID::Message& to_msg, const ::PROTOBUF_NAMESPACE_ID::Message& from_msg); + public: + PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + bool IsInitialized() const final; + + size_t ByteSizeLong() const final; + const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final; + uint8_t* _InternalSerialize( + uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final; + int GetCachedSize() const final { return _impl_._cached_size_.Get(); } + + private: + void SharedCtor(::PROTOBUF_NAMESPACE_ID::Arena* arena, bool is_message_owned); + void SharedDtor(); + void SetCachedSize(int size) const final; + void InternalSwap(MethodOptions* other); + + private: + friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata; + static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() { + return "google.protobuf.MethodOptions"; + } + protected: + explicit MethodOptions(::PROTOBUF_NAMESPACE_ID::Arena* arena, + bool is_message_owned = false); + public: + + static const ClassData _class_data_; + const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*GetClassData() const final; + + ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final; + + // nested types ---------------------------------------------------- + + typedef MethodOptions_IdempotencyLevel IdempotencyLevel; + static constexpr IdempotencyLevel IDEMPOTENCY_UNKNOWN = + MethodOptions_IdempotencyLevel_IDEMPOTENCY_UNKNOWN; + static constexpr IdempotencyLevel NO_SIDE_EFFECTS = + MethodOptions_IdempotencyLevel_NO_SIDE_EFFECTS; + static constexpr IdempotencyLevel IDEMPOTENT = + MethodOptions_IdempotencyLevel_IDEMPOTENT; + static inline bool IdempotencyLevel_IsValid(int value) { + return MethodOptions_IdempotencyLevel_IsValid(value); + } + static constexpr IdempotencyLevel IdempotencyLevel_MIN = + MethodOptions_IdempotencyLevel_IdempotencyLevel_MIN; + static constexpr IdempotencyLevel IdempotencyLevel_MAX = + MethodOptions_IdempotencyLevel_IdempotencyLevel_MAX; + static constexpr int IdempotencyLevel_ARRAYSIZE = + MethodOptions_IdempotencyLevel_IdempotencyLevel_ARRAYSIZE; + static inline const ::PROTOBUF_NAMESPACE_ID::EnumDescriptor* + IdempotencyLevel_descriptor() { + return MethodOptions_IdempotencyLevel_descriptor(); + } + template<typename T> + static inline const std::string& IdempotencyLevel_Name(T enum_t_value) { + static_assert(::std::is_same<T, IdempotencyLevel>::value || + ::std::is_integral<T>::value, + "Incorrect type passed to function IdempotencyLevel_Name."); + return MethodOptions_IdempotencyLevel_Name(enum_t_value); + } + static inline bool IdempotencyLevel_Parse(::PROTOBUF_NAMESPACE_ID::ConstStringParam name, + IdempotencyLevel* value) { + return MethodOptions_IdempotencyLevel_Parse(name, value); + } + + // accessors ------------------------------------------------------- + + enum : int { + kUninterpretedOptionFieldNumber = 999, + kDeprecatedFieldNumber = 33, + kIdempotencyLevelFieldNumber = 34, + }; + // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; + int uninterpreted_option_size() const; + private: + int _internal_uninterpreted_option_size() const; + public: + void clear_uninterpreted_option(); + ::PROTOBUF_NAMESPACE_ID::UninterpretedOption* mutable_uninterpreted_option(int index); + ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::UninterpretedOption >* + mutable_uninterpreted_option(); + private: + const ::PROTOBUF_NAMESPACE_ID::UninterpretedOption& _internal_uninterpreted_option(int index) const; + ::PROTOBUF_NAMESPACE_ID::UninterpretedOption* _internal_add_uninterpreted_option(); + public: + const ::PROTOBUF_NAMESPACE_ID::UninterpretedOption& uninterpreted_option(int index) const; + ::PROTOBUF_NAMESPACE_ID::UninterpretedOption* add_uninterpreted_option(); + const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::UninterpretedOption >& + uninterpreted_option() const; + + // optional bool deprecated = 33 [default = false]; + bool has_deprecated() const; + private: + bool _internal_has_deprecated() const; + public: + void clear_deprecated(); + bool deprecated() const; + void set_deprecated(bool value); + private: + bool _internal_deprecated() const; + void _internal_set_deprecated(bool value); + public: + + // optional .google.protobuf.MethodOptions.IdempotencyLevel idempotency_level = 34 [default = IDEMPOTENCY_UNKNOWN]; + bool has_idempotency_level() const; + private: + bool _internal_has_idempotency_level() const; + public: + void clear_idempotency_level(); + ::PROTOBUF_NAMESPACE_ID::MethodOptions_IdempotencyLevel idempotency_level() const; + void set_idempotency_level(::PROTOBUF_NAMESPACE_ID::MethodOptions_IdempotencyLevel value); + private: + ::PROTOBUF_NAMESPACE_ID::MethodOptions_IdempotencyLevel _internal_idempotency_level() const; + void _internal_set_idempotency_level(::PROTOBUF_NAMESPACE_ID::MethodOptions_IdempotencyLevel value); + public: + + + template <typename _proto_TypeTraits, + ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type, + bool _is_packed> + inline bool HasExtension( + const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier< + MethodOptions, _proto_TypeTraits, _field_type, _is_packed>& id) const { + + return _impl_._extensions_.Has(id.number()); + } + + template <typename _proto_TypeTraits, + ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type, + bool _is_packed> + inline void ClearExtension( + const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier< + MethodOptions, _proto_TypeTraits, _field_type, _is_packed>& id) { + _impl_._extensions_.ClearExtension(id.number()); + + } + + template <typename _proto_TypeTraits, + ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type, + bool _is_packed> + inline int ExtensionSize( + const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier< + MethodOptions, _proto_TypeTraits, _field_type, _is_packed>& id) const { + + return _impl_._extensions_.ExtensionSize(id.number()); + } + + template <typename _proto_TypeTraits, + ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type, + bool _is_packed> + inline typename _proto_TypeTraits::Singular::ConstType GetExtension( + const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier< + MethodOptions, _proto_TypeTraits, _field_type, _is_packed>& id) const { + + return _proto_TypeTraits::Get(id.number(), _impl_._extensions_, + id.default_value()); + } + + template <typename _proto_TypeTraits, + ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type, + bool _is_packed> + inline typename _proto_TypeTraits::Singular::MutableType MutableExtension( + const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier< + MethodOptions, _proto_TypeTraits, _field_type, _is_packed>& id) { + + return _proto_TypeTraits::Mutable(id.number(), _field_type, + &_impl_._extensions_); + } + + template <typename _proto_TypeTraits, + ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type, + bool _is_packed> + inline void SetExtension( + const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier< + MethodOptions, _proto_TypeTraits, _field_type, _is_packed>& id, + typename _proto_TypeTraits::Singular::ConstType value) { + _proto_TypeTraits::Set(id.number(), _field_type, value, &_impl_._extensions_); + + } + + template <typename _proto_TypeTraits, + ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type, + bool _is_packed> + inline void SetAllocatedExtension( + const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier< + MethodOptions, _proto_TypeTraits, _field_type, _is_packed>& id, + typename _proto_TypeTraits::Singular::MutableType value) { + _proto_TypeTraits::SetAllocated(id.number(), _field_type, value, + &_impl_._extensions_); + + } + template <typename _proto_TypeTraits, + ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type, + bool _is_packed> + inline void UnsafeArenaSetAllocatedExtension( + const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier< + MethodOptions, _proto_TypeTraits, _field_type, _is_packed>& id, + typename _proto_TypeTraits::Singular::MutableType value) { + _proto_TypeTraits::UnsafeArenaSetAllocated(id.number(), _field_type, + value, &_impl_._extensions_); + + } + template <typename _proto_TypeTraits, + ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type, + bool _is_packed> + PROTOBUF_NODISCARD inline + typename _proto_TypeTraits::Singular::MutableType + ReleaseExtension( + const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier< + MethodOptions, _proto_TypeTraits, _field_type, _is_packed>& id) { + + return _proto_TypeTraits::Release(id.number(), _field_type, + &_impl_._extensions_); + } + template <typename _proto_TypeTraits, + ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type, + bool _is_packed> + inline typename _proto_TypeTraits::Singular::MutableType + UnsafeArenaReleaseExtension( + const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier< + MethodOptions, _proto_TypeTraits, _field_type, _is_packed>& id) { + + return _proto_TypeTraits::UnsafeArenaRelease(id.number(), _field_type, + &_impl_._extensions_); + } + + template <typename _proto_TypeTraits, + ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type, + bool _is_packed> + inline typename _proto_TypeTraits::Repeated::ConstType GetExtension( + const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier< + MethodOptions, _proto_TypeTraits, _field_type, _is_packed>& id, + int index) const { + + return _proto_TypeTraits::Get(id.number(), _impl_._extensions_, index); + } + + template <typename _proto_TypeTraits, + ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type, + bool _is_packed> + inline typename _proto_TypeTraits::Repeated::MutableType MutableExtension( + const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier< + MethodOptions, _proto_TypeTraits, _field_type, _is_packed>& id, + int index) { + + return _proto_TypeTraits::Mutable(id.number(), index, &_impl_._extensions_); + } + + template <typename _proto_TypeTraits, + ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type, + bool _is_packed> + inline void SetExtension( + const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier< + MethodOptions, _proto_TypeTraits, _field_type, _is_packed>& id, + int index, typename _proto_TypeTraits::Repeated::ConstType value) { + _proto_TypeTraits::Set(id.number(), index, value, &_impl_._extensions_); + + } + + template <typename _proto_TypeTraits, + ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type, + bool _is_packed> + inline typename _proto_TypeTraits::Repeated::MutableType AddExtension( + const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier< + MethodOptions, _proto_TypeTraits, _field_type, _is_packed>& id) { + typename _proto_TypeTraits::Repeated::MutableType to_add = + _proto_TypeTraits::Add(id.number(), _field_type, &_impl_._extensions_); + + return to_add; + } + + template <typename _proto_TypeTraits, + ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type, + bool _is_packed> + inline void AddExtension( + const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier< + MethodOptions, _proto_TypeTraits, _field_type, _is_packed>& id, + typename _proto_TypeTraits::Repeated::ConstType value) { + _proto_TypeTraits::Add(id.number(), _field_type, _is_packed, value, + &_impl_._extensions_); + + } + + template <typename _proto_TypeTraits, + ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type, + bool _is_packed> + inline const typename _proto_TypeTraits::Repeated::RepeatedFieldType& + GetRepeatedExtension( + const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier< + MethodOptions, _proto_TypeTraits, _field_type, _is_packed>& id) const { + + return _proto_TypeTraits::GetRepeated(id.number(), _impl_._extensions_); + } + + template <typename _proto_TypeTraits, + ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type, + bool _is_packed> + inline typename _proto_TypeTraits::Repeated::RepeatedFieldType* + MutableRepeatedExtension( + const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier< + MethodOptions, _proto_TypeTraits, _field_type, _is_packed>& id) { + + return _proto_TypeTraits::MutableRepeated(id.number(), _field_type, + _is_packed, &_impl_._extensions_); + } + + // @@protoc_insertion_point(class_scope:google.protobuf.MethodOptions) + private: + class _Internal; + + template <typename T> friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper; + typedef void InternalArenaConstructable_; + typedef void DestructorSkippable_; + struct Impl_ { + ::PROTOBUF_NAMESPACE_ID::internal::ExtensionSet _extensions_; + + ::PROTOBUF_NAMESPACE_ID::internal::HasBits<1> _has_bits_; + mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_; + ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::UninterpretedOption > uninterpreted_option_; + bool deprecated_; + int idempotency_level_; + }; + union { Impl_ _impl_; }; + friend struct ::TableStruct_google_2fprotobuf_2fdescriptor_2eproto; +}; +// ------------------------------------------------------------------- + +class PROTOBUF_EXPORT UninterpretedOption_NamePart final : + public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.UninterpretedOption.NamePart) */ { + public: + inline UninterpretedOption_NamePart() : UninterpretedOption_NamePart(nullptr) {} + ~UninterpretedOption_NamePart() override; + explicit PROTOBUF_CONSTEXPR UninterpretedOption_NamePart(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized); + + UninterpretedOption_NamePart(const UninterpretedOption_NamePart& from); + UninterpretedOption_NamePart(UninterpretedOption_NamePart&& from) noexcept + : UninterpretedOption_NamePart() { + *this = ::std::move(from); + } + + inline UninterpretedOption_NamePart& operator=(const UninterpretedOption_NamePart& from) { + CopyFrom(from); + return *this; + } + inline UninterpretedOption_NamePart& operator=(UninterpretedOption_NamePart&& from) noexcept { + if (this == &from) return *this; + if (GetOwningArena() == from.GetOwningArena() + #ifdef PROTOBUF_FORCE_COPY_IN_MOVE + && GetOwningArena() != nullptr + #endif // !PROTOBUF_FORCE_COPY_IN_MOVE + ) { + InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + inline const ::PROTOBUF_NAMESPACE_ID::UnknownFieldSet& unknown_fields() const { + return _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance); + } + inline ::PROTOBUF_NAMESPACE_ID::UnknownFieldSet* mutable_unknown_fields() { + return _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); + } + + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* descriptor() { + return GetDescriptor(); + } + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() { + return default_instance().GetMetadata().descriptor; + } + static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() { + return default_instance().GetMetadata().reflection; + } + static const UninterpretedOption_NamePart& default_instance() { + return *internal_default_instance(); + } + static inline const UninterpretedOption_NamePart* internal_default_instance() { + return reinterpret_cast<const UninterpretedOption_NamePart*>( + &_UninterpretedOption_NamePart_default_instance_); + } + static constexpr int kIndexInFileMessages = + 21; + + friend void swap(UninterpretedOption_NamePart& a, UninterpretedOption_NamePart& b) { + a.Swap(&b); + } + inline void Swap(UninterpretedOption_NamePart* other) { + if (other == this) return; + #ifdef PROTOBUF_FORCE_COPY_IN_SWAP + if (GetOwningArena() != nullptr && + GetOwningArena() == other->GetOwningArena()) { + #else // PROTOBUF_FORCE_COPY_IN_SWAP + if (GetOwningArena() == other->GetOwningArena()) { + #endif // !PROTOBUF_FORCE_COPY_IN_SWAP + InternalSwap(other); + } else { + ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(UninterpretedOption_NamePart* other) { + if (other == this) return; + GOOGLE_DCHECK(GetOwningArena() == other->GetOwningArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + UninterpretedOption_NamePart* New(::PROTOBUF_NAMESPACE_ID::Arena* arena = nullptr) const final { + return CreateMaybeMessage<UninterpretedOption_NamePart>(arena); + } + using ::PROTOBUF_NAMESPACE_ID::Message::CopyFrom; + void CopyFrom(const UninterpretedOption_NamePart& from); + using ::PROTOBUF_NAMESPACE_ID::Message::MergeFrom; + void MergeFrom( const UninterpretedOption_NamePart& from) { + UninterpretedOption_NamePart::MergeImpl(*this, from); + } + private: + static void MergeImpl(::PROTOBUF_NAMESPACE_ID::Message& to_msg, const ::PROTOBUF_NAMESPACE_ID::Message& from_msg); + public: + PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + bool IsInitialized() const final; + + size_t ByteSizeLong() const final; + const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final; + uint8_t* _InternalSerialize( + uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final; + int GetCachedSize() const final { return _impl_._cached_size_.Get(); } + + private: + void SharedCtor(::PROTOBUF_NAMESPACE_ID::Arena* arena, bool is_message_owned); + void SharedDtor(); + void SetCachedSize(int size) const final; + void InternalSwap(UninterpretedOption_NamePart* other); + + private: + friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata; + static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() { + return "google.protobuf.UninterpretedOption.NamePart"; + } + protected: + explicit UninterpretedOption_NamePart(::PROTOBUF_NAMESPACE_ID::Arena* arena, + bool is_message_owned = false); + public: + + static const ClassData _class_data_; + const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*GetClassData() const final; + + ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final; + + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + + enum : int { + kNamePartFieldNumber = 1, + kIsExtensionFieldNumber = 2, + }; + // required string name_part = 1; + bool has_name_part() const; + private: + bool _internal_has_name_part() const; + public: + void clear_name_part(); + const std::string& name_part() const; + template <typename ArgT0 = const std::string&, typename... ArgT> + void set_name_part(ArgT0&& arg0, ArgT... args); + std::string* mutable_name_part(); + PROTOBUF_NODISCARD std::string* release_name_part(); + void set_allocated_name_part(std::string* name_part); + private: + const std::string& _internal_name_part() const; + inline PROTOBUF_ALWAYS_INLINE void _internal_set_name_part(const std::string& value); + std::string* _internal_mutable_name_part(); + public: + + // required bool is_extension = 2; + bool has_is_extension() const; + private: + bool _internal_has_is_extension() const; + public: + void clear_is_extension(); + bool is_extension() const; + void set_is_extension(bool value); + private: + bool _internal_is_extension() const; + void _internal_set_is_extension(bool value); + public: + + // @@protoc_insertion_point(class_scope:google.protobuf.UninterpretedOption.NamePart) + private: + class _Internal; + + // helper for ByteSizeLong() + size_t RequiredFieldsByteSizeFallback() const; + + template <typename T> friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper; + typedef void InternalArenaConstructable_; + typedef void DestructorSkippable_; + struct Impl_ { + ::PROTOBUF_NAMESPACE_ID::internal::HasBits<1> _has_bits_; + mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_; + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr name_part_; + bool is_extension_; + }; + union { Impl_ _impl_; }; + friend struct ::TableStruct_google_2fprotobuf_2fdescriptor_2eproto; +}; +// ------------------------------------------------------------------- + +class PROTOBUF_EXPORT UninterpretedOption final : + public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.UninterpretedOption) */ { + public: + inline UninterpretedOption() : UninterpretedOption(nullptr) {} + ~UninterpretedOption() override; + explicit PROTOBUF_CONSTEXPR UninterpretedOption(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized); + + UninterpretedOption(const UninterpretedOption& from); + UninterpretedOption(UninterpretedOption&& from) noexcept + : UninterpretedOption() { + *this = ::std::move(from); + } + + inline UninterpretedOption& operator=(const UninterpretedOption& from) { + CopyFrom(from); + return *this; + } + inline UninterpretedOption& operator=(UninterpretedOption&& from) noexcept { + if (this == &from) return *this; + if (GetOwningArena() == from.GetOwningArena() + #ifdef PROTOBUF_FORCE_COPY_IN_MOVE + && GetOwningArena() != nullptr + #endif // !PROTOBUF_FORCE_COPY_IN_MOVE + ) { + InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + inline const ::PROTOBUF_NAMESPACE_ID::UnknownFieldSet& unknown_fields() const { + return _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance); + } + inline ::PROTOBUF_NAMESPACE_ID::UnknownFieldSet* mutable_unknown_fields() { + return _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); + } + + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* descriptor() { + return GetDescriptor(); + } + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() { + return default_instance().GetMetadata().descriptor; + } + static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() { + return default_instance().GetMetadata().reflection; + } + static const UninterpretedOption& default_instance() { + return *internal_default_instance(); + } + static inline const UninterpretedOption* internal_default_instance() { + return reinterpret_cast<const UninterpretedOption*>( + &_UninterpretedOption_default_instance_); + } + static constexpr int kIndexInFileMessages = + 22; + + friend void swap(UninterpretedOption& a, UninterpretedOption& b) { + a.Swap(&b); + } + inline void Swap(UninterpretedOption* other) { + if (other == this) return; + #ifdef PROTOBUF_FORCE_COPY_IN_SWAP + if (GetOwningArena() != nullptr && + GetOwningArena() == other->GetOwningArena()) { + #else // PROTOBUF_FORCE_COPY_IN_SWAP + if (GetOwningArena() == other->GetOwningArena()) { + #endif // !PROTOBUF_FORCE_COPY_IN_SWAP + InternalSwap(other); + } else { + ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(UninterpretedOption* other) { + if (other == this) return; + GOOGLE_DCHECK(GetOwningArena() == other->GetOwningArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + UninterpretedOption* New(::PROTOBUF_NAMESPACE_ID::Arena* arena = nullptr) const final { + return CreateMaybeMessage<UninterpretedOption>(arena); + } + using ::PROTOBUF_NAMESPACE_ID::Message::CopyFrom; + void CopyFrom(const UninterpretedOption& from); + using ::PROTOBUF_NAMESPACE_ID::Message::MergeFrom; + void MergeFrom( const UninterpretedOption& from) { + UninterpretedOption::MergeImpl(*this, from); + } + private: + static void MergeImpl(::PROTOBUF_NAMESPACE_ID::Message& to_msg, const ::PROTOBUF_NAMESPACE_ID::Message& from_msg); + public: + PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + bool IsInitialized() const final; + + size_t ByteSizeLong() const final; + const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final; + uint8_t* _InternalSerialize( + uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final; + int GetCachedSize() const final { return _impl_._cached_size_.Get(); } + + private: + void SharedCtor(::PROTOBUF_NAMESPACE_ID::Arena* arena, bool is_message_owned); + void SharedDtor(); + void SetCachedSize(int size) const final; + void InternalSwap(UninterpretedOption* other); + + private: + friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata; + static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() { + return "google.protobuf.UninterpretedOption"; + } + protected: + explicit UninterpretedOption(::PROTOBUF_NAMESPACE_ID::Arena* arena, + bool is_message_owned = false); + public: + + static const ClassData _class_data_; + const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*GetClassData() const final; + + ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final; + + // nested types ---------------------------------------------------- + + typedef UninterpretedOption_NamePart NamePart; + + // accessors ------------------------------------------------------- + + enum : int { + kNameFieldNumber = 2, + kIdentifierValueFieldNumber = 3, + kStringValueFieldNumber = 7, + kAggregateValueFieldNumber = 8, + kPositiveIntValueFieldNumber = 4, + kNegativeIntValueFieldNumber = 5, + kDoubleValueFieldNumber = 6, + }; + // repeated .google.protobuf.UninterpretedOption.NamePart name = 2; + int name_size() const; + private: + int _internal_name_size() const; + public: + void clear_name(); + ::PROTOBUF_NAMESPACE_ID::UninterpretedOption_NamePart* mutable_name(int index); + ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::UninterpretedOption_NamePart >* + mutable_name(); + private: + const ::PROTOBUF_NAMESPACE_ID::UninterpretedOption_NamePart& _internal_name(int index) const; + ::PROTOBUF_NAMESPACE_ID::UninterpretedOption_NamePart* _internal_add_name(); + public: + const ::PROTOBUF_NAMESPACE_ID::UninterpretedOption_NamePart& name(int index) const; + ::PROTOBUF_NAMESPACE_ID::UninterpretedOption_NamePart* add_name(); + const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::UninterpretedOption_NamePart >& + name() const; + + // optional string identifier_value = 3; + bool has_identifier_value() const; + private: + bool _internal_has_identifier_value() const; + public: + void clear_identifier_value(); + const std::string& identifier_value() const; + template <typename ArgT0 = const std::string&, typename... ArgT> + void set_identifier_value(ArgT0&& arg0, ArgT... args); + std::string* mutable_identifier_value(); + PROTOBUF_NODISCARD std::string* release_identifier_value(); + void set_allocated_identifier_value(std::string* identifier_value); + private: + const std::string& _internal_identifier_value() const; + inline PROTOBUF_ALWAYS_INLINE void _internal_set_identifier_value(const std::string& value); + std::string* _internal_mutable_identifier_value(); + public: + + // optional bytes string_value = 7; + bool has_string_value() const; + private: + bool _internal_has_string_value() const; + public: + void clear_string_value(); + const std::string& string_value() const; + template <typename ArgT0 = const std::string&, typename... ArgT> + void set_string_value(ArgT0&& arg0, ArgT... args); + std::string* mutable_string_value(); + PROTOBUF_NODISCARD std::string* release_string_value(); + void set_allocated_string_value(std::string* string_value); + private: + const std::string& _internal_string_value() const; + inline PROTOBUF_ALWAYS_INLINE void _internal_set_string_value(const std::string& value); + std::string* _internal_mutable_string_value(); + public: + + // optional string aggregate_value = 8; + bool has_aggregate_value() const; + private: + bool _internal_has_aggregate_value() const; + public: + void clear_aggregate_value(); + const std::string& aggregate_value() const; + template <typename ArgT0 = const std::string&, typename... ArgT> + void set_aggregate_value(ArgT0&& arg0, ArgT... args); + std::string* mutable_aggregate_value(); + PROTOBUF_NODISCARD std::string* release_aggregate_value(); + void set_allocated_aggregate_value(std::string* aggregate_value); + private: + const std::string& _internal_aggregate_value() const; + inline PROTOBUF_ALWAYS_INLINE void _internal_set_aggregate_value(const std::string& value); + std::string* _internal_mutable_aggregate_value(); + public: + + // optional uint64 positive_int_value = 4; + bool has_positive_int_value() const; + private: + bool _internal_has_positive_int_value() const; + public: + void clear_positive_int_value(); + uint64_t positive_int_value() const; + void set_positive_int_value(uint64_t value); + private: + uint64_t _internal_positive_int_value() const; + void _internal_set_positive_int_value(uint64_t value); + public: + + // optional int64 negative_int_value = 5; + bool has_negative_int_value() const; + private: + bool _internal_has_negative_int_value() const; + public: + void clear_negative_int_value(); + int64_t negative_int_value() const; + void set_negative_int_value(int64_t value); + private: + int64_t _internal_negative_int_value() const; + void _internal_set_negative_int_value(int64_t value); + public: + + // optional double double_value = 6; + bool has_double_value() const; + private: + bool _internal_has_double_value() const; + public: + void clear_double_value(); + double double_value() const; + void set_double_value(double value); + private: + double _internal_double_value() const; + void _internal_set_double_value(double value); + public: + + // @@protoc_insertion_point(class_scope:google.protobuf.UninterpretedOption) + private: + class _Internal; + + template <typename T> friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper; + typedef void InternalArenaConstructable_; + typedef void DestructorSkippable_; + struct Impl_ { + ::PROTOBUF_NAMESPACE_ID::internal::HasBits<1> _has_bits_; + mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_; + ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::UninterpretedOption_NamePart > name_; + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr identifier_value_; + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr string_value_; + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr aggregate_value_; + uint64_t positive_int_value_; + int64_t negative_int_value_; + double double_value_; + }; + union { Impl_ _impl_; }; + friend struct ::TableStruct_google_2fprotobuf_2fdescriptor_2eproto; +}; +// ------------------------------------------------------------------- + +class PROTOBUF_EXPORT SourceCodeInfo_Location final : + public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.SourceCodeInfo.Location) */ { + public: + inline SourceCodeInfo_Location() : SourceCodeInfo_Location(nullptr) {} + ~SourceCodeInfo_Location() override; + explicit PROTOBUF_CONSTEXPR SourceCodeInfo_Location(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized); + + SourceCodeInfo_Location(const SourceCodeInfo_Location& from); + SourceCodeInfo_Location(SourceCodeInfo_Location&& from) noexcept + : SourceCodeInfo_Location() { + *this = ::std::move(from); + } + + inline SourceCodeInfo_Location& operator=(const SourceCodeInfo_Location& from) { + CopyFrom(from); + return *this; + } + inline SourceCodeInfo_Location& operator=(SourceCodeInfo_Location&& from) noexcept { + if (this == &from) return *this; + if (GetOwningArena() == from.GetOwningArena() + #ifdef PROTOBUF_FORCE_COPY_IN_MOVE + && GetOwningArena() != nullptr + #endif // !PROTOBUF_FORCE_COPY_IN_MOVE + ) { + InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + inline const ::PROTOBUF_NAMESPACE_ID::UnknownFieldSet& unknown_fields() const { + return _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance); + } + inline ::PROTOBUF_NAMESPACE_ID::UnknownFieldSet* mutable_unknown_fields() { + return _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); + } + + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* descriptor() { + return GetDescriptor(); + } + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() { + return default_instance().GetMetadata().descriptor; + } + static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() { + return default_instance().GetMetadata().reflection; + } + static const SourceCodeInfo_Location& default_instance() { + return *internal_default_instance(); + } + static inline const SourceCodeInfo_Location* internal_default_instance() { + return reinterpret_cast<const SourceCodeInfo_Location*>( + &_SourceCodeInfo_Location_default_instance_); + } + static constexpr int kIndexInFileMessages = + 23; + + friend void swap(SourceCodeInfo_Location& a, SourceCodeInfo_Location& b) { + a.Swap(&b); + } + inline void Swap(SourceCodeInfo_Location* other) { + if (other == this) return; + #ifdef PROTOBUF_FORCE_COPY_IN_SWAP + if (GetOwningArena() != nullptr && + GetOwningArena() == other->GetOwningArena()) { + #else // PROTOBUF_FORCE_COPY_IN_SWAP + if (GetOwningArena() == other->GetOwningArena()) { + #endif // !PROTOBUF_FORCE_COPY_IN_SWAP + InternalSwap(other); + } else { + ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(SourceCodeInfo_Location* other) { + if (other == this) return; + GOOGLE_DCHECK(GetOwningArena() == other->GetOwningArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + SourceCodeInfo_Location* New(::PROTOBUF_NAMESPACE_ID::Arena* arena = nullptr) const final { + return CreateMaybeMessage<SourceCodeInfo_Location>(arena); + } + using ::PROTOBUF_NAMESPACE_ID::Message::CopyFrom; + void CopyFrom(const SourceCodeInfo_Location& from); + using ::PROTOBUF_NAMESPACE_ID::Message::MergeFrom; + void MergeFrom( const SourceCodeInfo_Location& from) { + SourceCodeInfo_Location::MergeImpl(*this, from); + } + private: + static void MergeImpl(::PROTOBUF_NAMESPACE_ID::Message& to_msg, const ::PROTOBUF_NAMESPACE_ID::Message& from_msg); + public: + PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + bool IsInitialized() const final; + + size_t ByteSizeLong() const final; + const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final; + uint8_t* _InternalSerialize( + uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final; + int GetCachedSize() const final { return _impl_._cached_size_.Get(); } + + private: + void SharedCtor(::PROTOBUF_NAMESPACE_ID::Arena* arena, bool is_message_owned); + void SharedDtor(); + void SetCachedSize(int size) const final; + void InternalSwap(SourceCodeInfo_Location* other); + + private: + friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata; + static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() { + return "google.protobuf.SourceCodeInfo.Location"; + } + protected: + explicit SourceCodeInfo_Location(::PROTOBUF_NAMESPACE_ID::Arena* arena, + bool is_message_owned = false); + public: + + static const ClassData _class_data_; + const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*GetClassData() const final; + + ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final; + + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + + enum : int { + kPathFieldNumber = 1, + kSpanFieldNumber = 2, + kLeadingDetachedCommentsFieldNumber = 6, + kLeadingCommentsFieldNumber = 3, + kTrailingCommentsFieldNumber = 4, + }; + // repeated int32 path = 1 [packed = true]; + int path_size() const; + private: + int _internal_path_size() const; + public: + void clear_path(); + private: + int32_t _internal_path(int index) const; + const ::PROTOBUF_NAMESPACE_ID::RepeatedField< int32_t >& + _internal_path() const; + void _internal_add_path(int32_t value); + ::PROTOBUF_NAMESPACE_ID::RepeatedField< int32_t >* + _internal_mutable_path(); + public: + int32_t path(int index) const; + void set_path(int index, int32_t value); + void add_path(int32_t value); + const ::PROTOBUF_NAMESPACE_ID::RepeatedField< int32_t >& + path() const; + ::PROTOBUF_NAMESPACE_ID::RepeatedField< int32_t >* + mutable_path(); + + // repeated int32 span = 2 [packed = true]; + int span_size() const; + private: + int _internal_span_size() const; + public: + void clear_span(); + private: + int32_t _internal_span(int index) const; + const ::PROTOBUF_NAMESPACE_ID::RepeatedField< int32_t >& + _internal_span() const; + void _internal_add_span(int32_t value); + ::PROTOBUF_NAMESPACE_ID::RepeatedField< int32_t >* + _internal_mutable_span(); + public: + int32_t span(int index) const; + void set_span(int index, int32_t value); + void add_span(int32_t value); + const ::PROTOBUF_NAMESPACE_ID::RepeatedField< int32_t >& + span() const; + ::PROTOBUF_NAMESPACE_ID::RepeatedField< int32_t >* + mutable_span(); + + // repeated string leading_detached_comments = 6; + int leading_detached_comments_size() const; + private: + int _internal_leading_detached_comments_size() const; + public: + void clear_leading_detached_comments(); + const std::string& leading_detached_comments(int index) const; + std::string* mutable_leading_detached_comments(int index); + void set_leading_detached_comments(int index, const std::string& value); + void set_leading_detached_comments(int index, std::string&& value); + void set_leading_detached_comments(int index, const char* value); + void set_leading_detached_comments(int index, const char* value, size_t size); + std::string* add_leading_detached_comments(); + void add_leading_detached_comments(const std::string& value); + void add_leading_detached_comments(std::string&& value); + void add_leading_detached_comments(const char* value); + void add_leading_detached_comments(const char* value, size_t size); + const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField<std::string>& leading_detached_comments() const; + ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField<std::string>* mutable_leading_detached_comments(); + private: + const std::string& _internal_leading_detached_comments(int index) const; + std::string* _internal_add_leading_detached_comments(); + public: + + // optional string leading_comments = 3; + bool has_leading_comments() const; + private: + bool _internal_has_leading_comments() const; + public: + void clear_leading_comments(); + const std::string& leading_comments() const; + template <typename ArgT0 = const std::string&, typename... ArgT> + void set_leading_comments(ArgT0&& arg0, ArgT... args); + std::string* mutable_leading_comments(); + PROTOBUF_NODISCARD std::string* release_leading_comments(); + void set_allocated_leading_comments(std::string* leading_comments); + private: + const std::string& _internal_leading_comments() const; + inline PROTOBUF_ALWAYS_INLINE void _internal_set_leading_comments(const std::string& value); + std::string* _internal_mutable_leading_comments(); + public: + + // optional string trailing_comments = 4; + bool has_trailing_comments() const; + private: + bool _internal_has_trailing_comments() const; + public: + void clear_trailing_comments(); + const std::string& trailing_comments() const; + template <typename ArgT0 = const std::string&, typename... ArgT> + void set_trailing_comments(ArgT0&& arg0, ArgT... args); + std::string* mutable_trailing_comments(); + PROTOBUF_NODISCARD std::string* release_trailing_comments(); + void set_allocated_trailing_comments(std::string* trailing_comments); + private: + const std::string& _internal_trailing_comments() const; + inline PROTOBUF_ALWAYS_INLINE void _internal_set_trailing_comments(const std::string& value); + std::string* _internal_mutable_trailing_comments(); + public: + + // @@protoc_insertion_point(class_scope:google.protobuf.SourceCodeInfo.Location) + private: + class _Internal; + + template <typename T> friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper; + typedef void InternalArenaConstructable_; + typedef void DestructorSkippable_; + struct Impl_ { + ::PROTOBUF_NAMESPACE_ID::internal::HasBits<1> _has_bits_; + mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_; + ::PROTOBUF_NAMESPACE_ID::RepeatedField< int32_t > path_; + mutable std::atomic<int> _path_cached_byte_size_; + ::PROTOBUF_NAMESPACE_ID::RepeatedField< int32_t > span_; + mutable std::atomic<int> _span_cached_byte_size_; + ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField<std::string> leading_detached_comments_; + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr leading_comments_; + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr trailing_comments_; + }; + union { Impl_ _impl_; }; + friend struct ::TableStruct_google_2fprotobuf_2fdescriptor_2eproto; +}; +// ------------------------------------------------------------------- + +class PROTOBUF_EXPORT SourceCodeInfo final : + public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.SourceCodeInfo) */ { + public: + inline SourceCodeInfo() : SourceCodeInfo(nullptr) {} + ~SourceCodeInfo() override; + explicit PROTOBUF_CONSTEXPR SourceCodeInfo(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized); + + SourceCodeInfo(const SourceCodeInfo& from); + SourceCodeInfo(SourceCodeInfo&& from) noexcept + : SourceCodeInfo() { + *this = ::std::move(from); + } + + inline SourceCodeInfo& operator=(const SourceCodeInfo& from) { + CopyFrom(from); + return *this; + } + inline SourceCodeInfo& operator=(SourceCodeInfo&& from) noexcept { + if (this == &from) return *this; + if (GetOwningArena() == from.GetOwningArena() + #ifdef PROTOBUF_FORCE_COPY_IN_MOVE + && GetOwningArena() != nullptr + #endif // !PROTOBUF_FORCE_COPY_IN_MOVE + ) { + InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + inline const ::PROTOBUF_NAMESPACE_ID::UnknownFieldSet& unknown_fields() const { + return _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance); + } + inline ::PROTOBUF_NAMESPACE_ID::UnknownFieldSet* mutable_unknown_fields() { + return _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); + } + + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* descriptor() { + return GetDescriptor(); + } + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() { + return default_instance().GetMetadata().descriptor; + } + static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() { + return default_instance().GetMetadata().reflection; + } + static const SourceCodeInfo& default_instance() { + return *internal_default_instance(); + } + static inline const SourceCodeInfo* internal_default_instance() { + return reinterpret_cast<const SourceCodeInfo*>( + &_SourceCodeInfo_default_instance_); + } + static constexpr int kIndexInFileMessages = + 24; + + friend void swap(SourceCodeInfo& a, SourceCodeInfo& b) { + a.Swap(&b); + } + inline void Swap(SourceCodeInfo* other) { + if (other == this) return; + #ifdef PROTOBUF_FORCE_COPY_IN_SWAP + if (GetOwningArena() != nullptr && + GetOwningArena() == other->GetOwningArena()) { + #else // PROTOBUF_FORCE_COPY_IN_SWAP + if (GetOwningArena() == other->GetOwningArena()) { + #endif // !PROTOBUF_FORCE_COPY_IN_SWAP + InternalSwap(other); + } else { + ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(SourceCodeInfo* other) { + if (other == this) return; + GOOGLE_DCHECK(GetOwningArena() == other->GetOwningArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + SourceCodeInfo* New(::PROTOBUF_NAMESPACE_ID::Arena* arena = nullptr) const final { + return CreateMaybeMessage<SourceCodeInfo>(arena); + } + using ::PROTOBUF_NAMESPACE_ID::Message::CopyFrom; + void CopyFrom(const SourceCodeInfo& from); + using ::PROTOBUF_NAMESPACE_ID::Message::MergeFrom; + void MergeFrom( const SourceCodeInfo& from) { + SourceCodeInfo::MergeImpl(*this, from); + } + private: + static void MergeImpl(::PROTOBUF_NAMESPACE_ID::Message& to_msg, const ::PROTOBUF_NAMESPACE_ID::Message& from_msg); + public: + PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + bool IsInitialized() const final; + + size_t ByteSizeLong() const final; + const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final; + uint8_t* _InternalSerialize( + uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final; + int GetCachedSize() const final { return _impl_._cached_size_.Get(); } + + private: + void SharedCtor(::PROTOBUF_NAMESPACE_ID::Arena* arena, bool is_message_owned); + void SharedDtor(); + void SetCachedSize(int size) const final; + void InternalSwap(SourceCodeInfo* other); + + private: + friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata; + static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() { + return "google.protobuf.SourceCodeInfo"; + } + protected: + explicit SourceCodeInfo(::PROTOBUF_NAMESPACE_ID::Arena* arena, + bool is_message_owned = false); + public: + + static const ClassData _class_data_; + const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*GetClassData() const final; + + ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final; + + // nested types ---------------------------------------------------- + + typedef SourceCodeInfo_Location Location; + + // accessors ------------------------------------------------------- + + enum : int { + kLocationFieldNumber = 1, + }; + // repeated .google.protobuf.SourceCodeInfo.Location location = 1; + int location_size() const; + private: + int _internal_location_size() const; + public: + void clear_location(); + ::PROTOBUF_NAMESPACE_ID::SourceCodeInfo_Location* mutable_location(int index); + ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::SourceCodeInfo_Location >* + mutable_location(); + private: + const ::PROTOBUF_NAMESPACE_ID::SourceCodeInfo_Location& _internal_location(int index) const; + ::PROTOBUF_NAMESPACE_ID::SourceCodeInfo_Location* _internal_add_location(); + public: + const ::PROTOBUF_NAMESPACE_ID::SourceCodeInfo_Location& location(int index) const; + ::PROTOBUF_NAMESPACE_ID::SourceCodeInfo_Location* add_location(); + const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::SourceCodeInfo_Location >& + location() const; + + // @@protoc_insertion_point(class_scope:google.protobuf.SourceCodeInfo) + private: + class _Internal; + + template <typename T> friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper; + typedef void InternalArenaConstructable_; + typedef void DestructorSkippable_; + struct Impl_ { + ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::SourceCodeInfo_Location > location_; + mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_; + }; + union { Impl_ _impl_; }; + friend struct ::TableStruct_google_2fprotobuf_2fdescriptor_2eproto; +}; +// ------------------------------------------------------------------- + +class PROTOBUF_EXPORT GeneratedCodeInfo_Annotation final : + public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.GeneratedCodeInfo.Annotation) */ { + public: + inline GeneratedCodeInfo_Annotation() : GeneratedCodeInfo_Annotation(nullptr) {} + ~GeneratedCodeInfo_Annotation() override; + explicit PROTOBUF_CONSTEXPR GeneratedCodeInfo_Annotation(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized); + + GeneratedCodeInfo_Annotation(const GeneratedCodeInfo_Annotation& from); + GeneratedCodeInfo_Annotation(GeneratedCodeInfo_Annotation&& from) noexcept + : GeneratedCodeInfo_Annotation() { + *this = ::std::move(from); + } + + inline GeneratedCodeInfo_Annotation& operator=(const GeneratedCodeInfo_Annotation& from) { + CopyFrom(from); + return *this; + } + inline GeneratedCodeInfo_Annotation& operator=(GeneratedCodeInfo_Annotation&& from) noexcept { + if (this == &from) return *this; + if (GetOwningArena() == from.GetOwningArena() + #ifdef PROTOBUF_FORCE_COPY_IN_MOVE + && GetOwningArena() != nullptr + #endif // !PROTOBUF_FORCE_COPY_IN_MOVE + ) { + InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + inline const ::PROTOBUF_NAMESPACE_ID::UnknownFieldSet& unknown_fields() const { + return _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance); + } + inline ::PROTOBUF_NAMESPACE_ID::UnknownFieldSet* mutable_unknown_fields() { + return _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); + } + + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* descriptor() { + return GetDescriptor(); + } + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() { + return default_instance().GetMetadata().descriptor; + } + static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() { + return default_instance().GetMetadata().reflection; + } + static const GeneratedCodeInfo_Annotation& default_instance() { + return *internal_default_instance(); + } + static inline const GeneratedCodeInfo_Annotation* internal_default_instance() { + return reinterpret_cast<const GeneratedCodeInfo_Annotation*>( + &_GeneratedCodeInfo_Annotation_default_instance_); + } + static constexpr int kIndexInFileMessages = + 25; + + friend void swap(GeneratedCodeInfo_Annotation& a, GeneratedCodeInfo_Annotation& b) { + a.Swap(&b); + } + inline void Swap(GeneratedCodeInfo_Annotation* other) { + if (other == this) return; + #ifdef PROTOBUF_FORCE_COPY_IN_SWAP + if (GetOwningArena() != nullptr && + GetOwningArena() == other->GetOwningArena()) { + #else // PROTOBUF_FORCE_COPY_IN_SWAP + if (GetOwningArena() == other->GetOwningArena()) { + #endif // !PROTOBUF_FORCE_COPY_IN_SWAP + InternalSwap(other); + } else { + ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(GeneratedCodeInfo_Annotation* other) { + if (other == this) return; + GOOGLE_DCHECK(GetOwningArena() == other->GetOwningArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + GeneratedCodeInfo_Annotation* New(::PROTOBUF_NAMESPACE_ID::Arena* arena = nullptr) const final { + return CreateMaybeMessage<GeneratedCodeInfo_Annotation>(arena); + } + using ::PROTOBUF_NAMESPACE_ID::Message::CopyFrom; + void CopyFrom(const GeneratedCodeInfo_Annotation& from); + using ::PROTOBUF_NAMESPACE_ID::Message::MergeFrom; + void MergeFrom( const GeneratedCodeInfo_Annotation& from) { + GeneratedCodeInfo_Annotation::MergeImpl(*this, from); + } + private: + static void MergeImpl(::PROTOBUF_NAMESPACE_ID::Message& to_msg, const ::PROTOBUF_NAMESPACE_ID::Message& from_msg); + public: + PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + bool IsInitialized() const final; + + size_t ByteSizeLong() const final; + const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final; + uint8_t* _InternalSerialize( + uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final; + int GetCachedSize() const final { return _impl_._cached_size_.Get(); } + + private: + void SharedCtor(::PROTOBUF_NAMESPACE_ID::Arena* arena, bool is_message_owned); + void SharedDtor(); + void SetCachedSize(int size) const final; + void InternalSwap(GeneratedCodeInfo_Annotation* other); + + private: + friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata; + static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() { + return "google.protobuf.GeneratedCodeInfo.Annotation"; + } + protected: + explicit GeneratedCodeInfo_Annotation(::PROTOBUF_NAMESPACE_ID::Arena* arena, + bool is_message_owned = false); + public: + + static const ClassData _class_data_; + const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*GetClassData() const final; + + ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final; + + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + + enum : int { + kPathFieldNumber = 1, + kSourceFileFieldNumber = 2, + kBeginFieldNumber = 3, + kEndFieldNumber = 4, + }; + // repeated int32 path = 1 [packed = true]; + int path_size() const; + private: + int _internal_path_size() const; + public: + void clear_path(); + private: + int32_t _internal_path(int index) const; + const ::PROTOBUF_NAMESPACE_ID::RepeatedField< int32_t >& + _internal_path() const; + void _internal_add_path(int32_t value); + ::PROTOBUF_NAMESPACE_ID::RepeatedField< int32_t >* + _internal_mutable_path(); + public: + int32_t path(int index) const; + void set_path(int index, int32_t value); + void add_path(int32_t value); + const ::PROTOBUF_NAMESPACE_ID::RepeatedField< int32_t >& + path() const; + ::PROTOBUF_NAMESPACE_ID::RepeatedField< int32_t >* + mutable_path(); + + // optional string source_file = 2; + bool has_source_file() const; + private: + bool _internal_has_source_file() const; + public: + void clear_source_file(); + const std::string& source_file() const; + template <typename ArgT0 = const std::string&, typename... ArgT> + void set_source_file(ArgT0&& arg0, ArgT... args); + std::string* mutable_source_file(); + PROTOBUF_NODISCARD std::string* release_source_file(); + void set_allocated_source_file(std::string* source_file); + private: + const std::string& _internal_source_file() const; + inline PROTOBUF_ALWAYS_INLINE void _internal_set_source_file(const std::string& value); + std::string* _internal_mutable_source_file(); + public: + + // optional int32 begin = 3; + bool has_begin() const; + private: + bool _internal_has_begin() const; + public: + void clear_begin(); + int32_t begin() const; + void set_begin(int32_t value); + private: + int32_t _internal_begin() const; + void _internal_set_begin(int32_t value); + public: + + // optional int32 end = 4; + bool has_end() const; + private: + bool _internal_has_end() const; + public: + void clear_end(); + int32_t end() const; + void set_end(int32_t value); + private: + int32_t _internal_end() const; + void _internal_set_end(int32_t value); + public: + + // @@protoc_insertion_point(class_scope:google.protobuf.GeneratedCodeInfo.Annotation) + private: + class _Internal; + + template <typename T> friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper; + typedef void InternalArenaConstructable_; + typedef void DestructorSkippable_; + struct Impl_ { + ::PROTOBUF_NAMESPACE_ID::internal::HasBits<1> _has_bits_; + mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_; + ::PROTOBUF_NAMESPACE_ID::RepeatedField< int32_t > path_; + mutable std::atomic<int> _path_cached_byte_size_; + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr source_file_; + int32_t begin_; + int32_t end_; + }; + union { Impl_ _impl_; }; + friend struct ::TableStruct_google_2fprotobuf_2fdescriptor_2eproto; +}; +// ------------------------------------------------------------------- + +class PROTOBUF_EXPORT GeneratedCodeInfo final : + public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.GeneratedCodeInfo) */ { + public: + inline GeneratedCodeInfo() : GeneratedCodeInfo(nullptr) {} + ~GeneratedCodeInfo() override; + explicit PROTOBUF_CONSTEXPR GeneratedCodeInfo(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized); + + GeneratedCodeInfo(const GeneratedCodeInfo& from); + GeneratedCodeInfo(GeneratedCodeInfo&& from) noexcept + : GeneratedCodeInfo() { + *this = ::std::move(from); + } + + inline GeneratedCodeInfo& operator=(const GeneratedCodeInfo& from) { + CopyFrom(from); + return *this; + } + inline GeneratedCodeInfo& operator=(GeneratedCodeInfo&& from) noexcept { + if (this == &from) return *this; + if (GetOwningArena() == from.GetOwningArena() + #ifdef PROTOBUF_FORCE_COPY_IN_MOVE + && GetOwningArena() != nullptr + #endif // !PROTOBUF_FORCE_COPY_IN_MOVE + ) { + InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + inline const ::PROTOBUF_NAMESPACE_ID::UnknownFieldSet& unknown_fields() const { + return _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance); + } + inline ::PROTOBUF_NAMESPACE_ID::UnknownFieldSet* mutable_unknown_fields() { + return _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); + } + + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* descriptor() { + return GetDescriptor(); + } + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() { + return default_instance().GetMetadata().descriptor; + } + static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() { + return default_instance().GetMetadata().reflection; + } + static const GeneratedCodeInfo& default_instance() { + return *internal_default_instance(); + } + static inline const GeneratedCodeInfo* internal_default_instance() { + return reinterpret_cast<const GeneratedCodeInfo*>( + &_GeneratedCodeInfo_default_instance_); + } + static constexpr int kIndexInFileMessages = + 26; + + friend void swap(GeneratedCodeInfo& a, GeneratedCodeInfo& b) { + a.Swap(&b); + } + inline void Swap(GeneratedCodeInfo* other) { + if (other == this) return; + #ifdef PROTOBUF_FORCE_COPY_IN_SWAP + if (GetOwningArena() != nullptr && + GetOwningArena() == other->GetOwningArena()) { + #else // PROTOBUF_FORCE_COPY_IN_SWAP + if (GetOwningArena() == other->GetOwningArena()) { + #endif // !PROTOBUF_FORCE_COPY_IN_SWAP + InternalSwap(other); + } else { + ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(GeneratedCodeInfo* other) { + if (other == this) return; + GOOGLE_DCHECK(GetOwningArena() == other->GetOwningArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + GeneratedCodeInfo* New(::PROTOBUF_NAMESPACE_ID::Arena* arena = nullptr) const final { + return CreateMaybeMessage<GeneratedCodeInfo>(arena); + } + using ::PROTOBUF_NAMESPACE_ID::Message::CopyFrom; + void CopyFrom(const GeneratedCodeInfo& from); + using ::PROTOBUF_NAMESPACE_ID::Message::MergeFrom; + void MergeFrom( const GeneratedCodeInfo& from) { + GeneratedCodeInfo::MergeImpl(*this, from); + } + private: + static void MergeImpl(::PROTOBUF_NAMESPACE_ID::Message& to_msg, const ::PROTOBUF_NAMESPACE_ID::Message& from_msg); + public: + PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + bool IsInitialized() const final; + + size_t ByteSizeLong() const final; + const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final; + uint8_t* _InternalSerialize( + uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final; + int GetCachedSize() const final { return _impl_._cached_size_.Get(); } + + private: + void SharedCtor(::PROTOBUF_NAMESPACE_ID::Arena* arena, bool is_message_owned); + void SharedDtor(); + void SetCachedSize(int size) const final; + void InternalSwap(GeneratedCodeInfo* other); + + private: + friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata; + static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() { + return "google.protobuf.GeneratedCodeInfo"; + } + protected: + explicit GeneratedCodeInfo(::PROTOBUF_NAMESPACE_ID::Arena* arena, + bool is_message_owned = false); + public: + + static const ClassData _class_data_; + const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*GetClassData() const final; + + ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final; + + // nested types ---------------------------------------------------- + + typedef GeneratedCodeInfo_Annotation Annotation; + + // accessors ------------------------------------------------------- + + enum : int { + kAnnotationFieldNumber = 1, + }; + // repeated .google.protobuf.GeneratedCodeInfo.Annotation annotation = 1; + int annotation_size() const; + private: + int _internal_annotation_size() const; + public: + void clear_annotation(); + ::PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo_Annotation* mutable_annotation(int index); + ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo_Annotation >* + mutable_annotation(); + private: + const ::PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo_Annotation& _internal_annotation(int index) const; + ::PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo_Annotation* _internal_add_annotation(); + public: + const ::PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo_Annotation& annotation(int index) const; + ::PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo_Annotation* add_annotation(); + const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo_Annotation >& + annotation() const; + + // @@protoc_insertion_point(class_scope:google.protobuf.GeneratedCodeInfo) + private: + class _Internal; + + template <typename T> friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper; + typedef void InternalArenaConstructable_; + typedef void DestructorSkippable_; + struct Impl_ { + ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo_Annotation > annotation_; + mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_; + }; + union { Impl_ _impl_; }; + friend struct ::TableStruct_google_2fprotobuf_2fdescriptor_2eproto; +}; +// =================================================================== + + +// =================================================================== + +#ifdef __GNUC__ + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wstrict-aliasing" +#endif // __GNUC__ +// FileDescriptorSet + +// repeated .google.protobuf.FileDescriptorProto file = 1; +inline int FileDescriptorSet::_internal_file_size() const { + return _impl_.file_.size(); +} +inline int FileDescriptorSet::file_size() const { + return _internal_file_size(); +} +inline void FileDescriptorSet::clear_file() { + _impl_.file_.Clear(); +} +inline ::PROTOBUF_NAMESPACE_ID::FileDescriptorProto* FileDescriptorSet::mutable_file(int index) { + // @@protoc_insertion_point(field_mutable:google.protobuf.FileDescriptorSet.file) + return _impl_.file_.Mutable(index); +} +inline ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::FileDescriptorProto >* +FileDescriptorSet::mutable_file() { + // @@protoc_insertion_point(field_mutable_list:google.protobuf.FileDescriptorSet.file) + return &_impl_.file_; +} +inline const ::PROTOBUF_NAMESPACE_ID::FileDescriptorProto& FileDescriptorSet::_internal_file(int index) const { + return _impl_.file_.Get(index); +} +inline const ::PROTOBUF_NAMESPACE_ID::FileDescriptorProto& FileDescriptorSet::file(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.FileDescriptorSet.file) + return _internal_file(index); +} +inline ::PROTOBUF_NAMESPACE_ID::FileDescriptorProto* FileDescriptorSet::_internal_add_file() { + return _impl_.file_.Add(); +} +inline ::PROTOBUF_NAMESPACE_ID::FileDescriptorProto* FileDescriptorSet::add_file() { + ::PROTOBUF_NAMESPACE_ID::FileDescriptorProto* _add = _internal_add_file(); + // @@protoc_insertion_point(field_add:google.protobuf.FileDescriptorSet.file) + return _add; +} +inline const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::FileDescriptorProto >& +FileDescriptorSet::file() const { + // @@protoc_insertion_point(field_list:google.protobuf.FileDescriptorSet.file) + return _impl_.file_; +} + +// ------------------------------------------------------------------- + +// FileDescriptorProto + +// optional string name = 1; +inline bool FileDescriptorProto::_internal_has_name() const { + bool value = (_impl_._has_bits_[0] & 0x00000001u) != 0; + return value; +} +inline bool FileDescriptorProto::has_name() const { + return _internal_has_name(); +} +inline void FileDescriptorProto::clear_name() { + _impl_.name_.ClearToEmpty(); + _impl_._has_bits_[0] &= ~0x00000001u; +} +inline const std::string& FileDescriptorProto::name() const { + // @@protoc_insertion_point(field_get:google.protobuf.FileDescriptorProto.name) + return _internal_name(); +} +template <typename ArgT0, typename... ArgT> +inline PROTOBUF_ALWAYS_INLINE +void FileDescriptorProto::set_name(ArgT0&& arg0, ArgT... args) { + _impl_._has_bits_[0] |= 0x00000001u; + _impl_.name_.Set(static_cast<ArgT0 &&>(arg0), args..., GetArenaForAllocation()); + // @@protoc_insertion_point(field_set:google.protobuf.FileDescriptorProto.name) +} +inline std::string* FileDescriptorProto::mutable_name() { + std::string* _s = _internal_mutable_name(); + // @@protoc_insertion_point(field_mutable:google.protobuf.FileDescriptorProto.name) + return _s; +} +inline const std::string& FileDescriptorProto::_internal_name() const { + return _impl_.name_.Get(); +} +inline void FileDescriptorProto::_internal_set_name(const std::string& value) { + _impl_._has_bits_[0] |= 0x00000001u; + _impl_.name_.Set(value, GetArenaForAllocation()); +} +inline std::string* FileDescriptorProto::_internal_mutable_name() { + _impl_._has_bits_[0] |= 0x00000001u; + return _impl_.name_.Mutable(GetArenaForAllocation()); +} +inline std::string* FileDescriptorProto::release_name() { + // @@protoc_insertion_point(field_release:google.protobuf.FileDescriptorProto.name) + if (!_internal_has_name()) { + return nullptr; + } + _impl_._has_bits_[0] &= ~0x00000001u; + auto* p = _impl_.name_.Release(); +#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (_impl_.name_.IsDefault()) { + _impl_.name_.Set("", GetArenaForAllocation()); + } +#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + return p; +} +inline void FileDescriptorProto::set_allocated_name(std::string* name) { + if (name != nullptr) { + _impl_._has_bits_[0] |= 0x00000001u; + } else { + _impl_._has_bits_[0] &= ~0x00000001u; + } + _impl_.name_.SetAllocated(name, GetArenaForAllocation()); +#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (_impl_.name_.IsDefault()) { + _impl_.name_.Set("", GetArenaForAllocation()); + } +#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + // @@protoc_insertion_point(field_set_allocated:google.protobuf.FileDescriptorProto.name) +} + +// optional string package = 2; +inline bool FileDescriptorProto::_internal_has_package() const { + bool value = (_impl_._has_bits_[0] & 0x00000002u) != 0; + return value; +} +inline bool FileDescriptorProto::has_package() const { + return _internal_has_package(); +} +inline void FileDescriptorProto::clear_package() { + _impl_.package_.ClearToEmpty(); + _impl_._has_bits_[0] &= ~0x00000002u; +} +inline const std::string& FileDescriptorProto::package() const { + // @@protoc_insertion_point(field_get:google.protobuf.FileDescriptorProto.package) + return _internal_package(); +} +template <typename ArgT0, typename... ArgT> +inline PROTOBUF_ALWAYS_INLINE +void FileDescriptorProto::set_package(ArgT0&& arg0, ArgT... args) { + _impl_._has_bits_[0] |= 0x00000002u; + _impl_.package_.Set(static_cast<ArgT0 &&>(arg0), args..., GetArenaForAllocation()); + // @@protoc_insertion_point(field_set:google.protobuf.FileDescriptorProto.package) +} +inline std::string* FileDescriptorProto::mutable_package() { + std::string* _s = _internal_mutable_package(); + // @@protoc_insertion_point(field_mutable:google.protobuf.FileDescriptorProto.package) + return _s; +} +inline const std::string& FileDescriptorProto::_internal_package() const { + return _impl_.package_.Get(); +} +inline void FileDescriptorProto::_internal_set_package(const std::string& value) { + _impl_._has_bits_[0] |= 0x00000002u; + _impl_.package_.Set(value, GetArenaForAllocation()); +} +inline std::string* FileDescriptorProto::_internal_mutable_package() { + _impl_._has_bits_[0] |= 0x00000002u; + return _impl_.package_.Mutable(GetArenaForAllocation()); +} +inline std::string* FileDescriptorProto::release_package() { + // @@protoc_insertion_point(field_release:google.protobuf.FileDescriptorProto.package) + if (!_internal_has_package()) { + return nullptr; + } + _impl_._has_bits_[0] &= ~0x00000002u; + auto* p = _impl_.package_.Release(); +#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (_impl_.package_.IsDefault()) { + _impl_.package_.Set("", GetArenaForAllocation()); + } +#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + return p; +} +inline void FileDescriptorProto::set_allocated_package(std::string* package) { + if (package != nullptr) { + _impl_._has_bits_[0] |= 0x00000002u; + } else { + _impl_._has_bits_[0] &= ~0x00000002u; + } + _impl_.package_.SetAllocated(package, GetArenaForAllocation()); +#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (_impl_.package_.IsDefault()) { + _impl_.package_.Set("", GetArenaForAllocation()); + } +#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + // @@protoc_insertion_point(field_set_allocated:google.protobuf.FileDescriptorProto.package) +} + +// repeated string dependency = 3; +inline int FileDescriptorProto::_internal_dependency_size() const { + return _impl_.dependency_.size(); +} +inline int FileDescriptorProto::dependency_size() const { + return _internal_dependency_size(); +} +inline void FileDescriptorProto::clear_dependency() { + _impl_.dependency_.Clear(); +} +inline std::string* FileDescriptorProto::add_dependency() { + std::string* _s = _internal_add_dependency(); + // @@protoc_insertion_point(field_add_mutable:google.protobuf.FileDescriptorProto.dependency) + return _s; +} +inline const std::string& FileDescriptorProto::_internal_dependency(int index) const { + return _impl_.dependency_.Get(index); +} +inline const std::string& FileDescriptorProto::dependency(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.FileDescriptorProto.dependency) + return _internal_dependency(index); +} +inline std::string* FileDescriptorProto::mutable_dependency(int index) { + // @@protoc_insertion_point(field_mutable:google.protobuf.FileDescriptorProto.dependency) + return _impl_.dependency_.Mutable(index); +} +inline void FileDescriptorProto::set_dependency(int index, const std::string& value) { + _impl_.dependency_.Mutable(index)->assign(value); + // @@protoc_insertion_point(field_set:google.protobuf.FileDescriptorProto.dependency) +} +inline void FileDescriptorProto::set_dependency(int index, std::string&& value) { + _impl_.dependency_.Mutable(index)->assign(std::move(value)); + // @@protoc_insertion_point(field_set:google.protobuf.FileDescriptorProto.dependency) +} +inline void FileDescriptorProto::set_dependency(int index, const char* value) { + GOOGLE_DCHECK(value != nullptr); + _impl_.dependency_.Mutable(index)->assign(value); + // @@protoc_insertion_point(field_set_char:google.protobuf.FileDescriptorProto.dependency) +} +inline void FileDescriptorProto::set_dependency(int index, const char* value, size_t size) { + _impl_.dependency_.Mutable(index)->assign( + reinterpret_cast<const char*>(value), size); + // @@protoc_insertion_point(field_set_pointer:google.protobuf.FileDescriptorProto.dependency) +} +inline std::string* FileDescriptorProto::_internal_add_dependency() { + return _impl_.dependency_.Add(); +} +inline void FileDescriptorProto::add_dependency(const std::string& value) { + _impl_.dependency_.Add()->assign(value); + // @@protoc_insertion_point(field_add:google.protobuf.FileDescriptorProto.dependency) +} +inline void FileDescriptorProto::add_dependency(std::string&& value) { + _impl_.dependency_.Add(std::move(value)); + // @@protoc_insertion_point(field_add:google.protobuf.FileDescriptorProto.dependency) +} +inline void FileDescriptorProto::add_dependency(const char* value) { + GOOGLE_DCHECK(value != nullptr); + _impl_.dependency_.Add()->assign(value); + // @@protoc_insertion_point(field_add_char:google.protobuf.FileDescriptorProto.dependency) +} +inline void FileDescriptorProto::add_dependency(const char* value, size_t size) { + _impl_.dependency_.Add()->assign(reinterpret_cast<const char*>(value), size); + // @@protoc_insertion_point(field_add_pointer:google.protobuf.FileDescriptorProto.dependency) +} +inline const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField<std::string>& +FileDescriptorProto::dependency() const { + // @@protoc_insertion_point(field_list:google.protobuf.FileDescriptorProto.dependency) + return _impl_.dependency_; +} +inline ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField<std::string>* +FileDescriptorProto::mutable_dependency() { + // @@protoc_insertion_point(field_mutable_list:google.protobuf.FileDescriptorProto.dependency) + return &_impl_.dependency_; +} + +// repeated int32 public_dependency = 10; +inline int FileDescriptorProto::_internal_public_dependency_size() const { + return _impl_.public_dependency_.size(); +} +inline int FileDescriptorProto::public_dependency_size() const { + return _internal_public_dependency_size(); +} +inline void FileDescriptorProto::clear_public_dependency() { + _impl_.public_dependency_.Clear(); +} +inline int32_t FileDescriptorProto::_internal_public_dependency(int index) const { + return _impl_.public_dependency_.Get(index); +} +inline int32_t FileDescriptorProto::public_dependency(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.FileDescriptorProto.public_dependency) + return _internal_public_dependency(index); +} +inline void FileDescriptorProto::set_public_dependency(int index, int32_t value) { + _impl_.public_dependency_.Set(index, value); + // @@protoc_insertion_point(field_set:google.protobuf.FileDescriptorProto.public_dependency) +} +inline void FileDescriptorProto::_internal_add_public_dependency(int32_t value) { + _impl_.public_dependency_.Add(value); +} +inline void FileDescriptorProto::add_public_dependency(int32_t value) { + _internal_add_public_dependency(value); + // @@protoc_insertion_point(field_add:google.protobuf.FileDescriptorProto.public_dependency) +} +inline const ::PROTOBUF_NAMESPACE_ID::RepeatedField< int32_t >& +FileDescriptorProto::_internal_public_dependency() const { + return _impl_.public_dependency_; +} +inline const ::PROTOBUF_NAMESPACE_ID::RepeatedField< int32_t >& +FileDescriptorProto::public_dependency() const { + // @@protoc_insertion_point(field_list:google.protobuf.FileDescriptorProto.public_dependency) + return _internal_public_dependency(); +} +inline ::PROTOBUF_NAMESPACE_ID::RepeatedField< int32_t >* +FileDescriptorProto::_internal_mutable_public_dependency() { + return &_impl_.public_dependency_; +} +inline ::PROTOBUF_NAMESPACE_ID::RepeatedField< int32_t >* +FileDescriptorProto::mutable_public_dependency() { + // @@protoc_insertion_point(field_mutable_list:google.protobuf.FileDescriptorProto.public_dependency) + return _internal_mutable_public_dependency(); +} + +// repeated int32 weak_dependency = 11; +inline int FileDescriptorProto::_internal_weak_dependency_size() const { + return _impl_.weak_dependency_.size(); +} +inline int FileDescriptorProto::weak_dependency_size() const { + return _internal_weak_dependency_size(); +} +inline void FileDescriptorProto::clear_weak_dependency() { + _impl_.weak_dependency_.Clear(); +} +inline int32_t FileDescriptorProto::_internal_weak_dependency(int index) const { + return _impl_.weak_dependency_.Get(index); +} +inline int32_t FileDescriptorProto::weak_dependency(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.FileDescriptorProto.weak_dependency) + return _internal_weak_dependency(index); +} +inline void FileDescriptorProto::set_weak_dependency(int index, int32_t value) { + _impl_.weak_dependency_.Set(index, value); + // @@protoc_insertion_point(field_set:google.protobuf.FileDescriptorProto.weak_dependency) +} +inline void FileDescriptorProto::_internal_add_weak_dependency(int32_t value) { + _impl_.weak_dependency_.Add(value); +} +inline void FileDescriptorProto::add_weak_dependency(int32_t value) { + _internal_add_weak_dependency(value); + // @@protoc_insertion_point(field_add:google.protobuf.FileDescriptorProto.weak_dependency) +} +inline const ::PROTOBUF_NAMESPACE_ID::RepeatedField< int32_t >& +FileDescriptorProto::_internal_weak_dependency() const { + return _impl_.weak_dependency_; +} +inline const ::PROTOBUF_NAMESPACE_ID::RepeatedField< int32_t >& +FileDescriptorProto::weak_dependency() const { + // @@protoc_insertion_point(field_list:google.protobuf.FileDescriptorProto.weak_dependency) + return _internal_weak_dependency(); +} +inline ::PROTOBUF_NAMESPACE_ID::RepeatedField< int32_t >* +FileDescriptorProto::_internal_mutable_weak_dependency() { + return &_impl_.weak_dependency_; +} +inline ::PROTOBUF_NAMESPACE_ID::RepeatedField< int32_t >* +FileDescriptorProto::mutable_weak_dependency() { + // @@protoc_insertion_point(field_mutable_list:google.protobuf.FileDescriptorProto.weak_dependency) + return _internal_mutable_weak_dependency(); +} + +// repeated .google.protobuf.DescriptorProto message_type = 4; +inline int FileDescriptorProto::_internal_message_type_size() const { + return _impl_.message_type_.size(); +} +inline int FileDescriptorProto::message_type_size() const { + return _internal_message_type_size(); +} +inline void FileDescriptorProto::clear_message_type() { + _impl_.message_type_.Clear(); +} +inline ::PROTOBUF_NAMESPACE_ID::DescriptorProto* FileDescriptorProto::mutable_message_type(int index) { + // @@protoc_insertion_point(field_mutable:google.protobuf.FileDescriptorProto.message_type) + return _impl_.message_type_.Mutable(index); +} +inline ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::DescriptorProto >* +FileDescriptorProto::mutable_message_type() { + // @@protoc_insertion_point(field_mutable_list:google.protobuf.FileDescriptorProto.message_type) + return &_impl_.message_type_; +} +inline const ::PROTOBUF_NAMESPACE_ID::DescriptorProto& FileDescriptorProto::_internal_message_type(int index) const { + return _impl_.message_type_.Get(index); +} +inline const ::PROTOBUF_NAMESPACE_ID::DescriptorProto& FileDescriptorProto::message_type(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.FileDescriptorProto.message_type) + return _internal_message_type(index); +} +inline ::PROTOBUF_NAMESPACE_ID::DescriptorProto* FileDescriptorProto::_internal_add_message_type() { + return _impl_.message_type_.Add(); +} +inline ::PROTOBUF_NAMESPACE_ID::DescriptorProto* FileDescriptorProto::add_message_type() { + ::PROTOBUF_NAMESPACE_ID::DescriptorProto* _add = _internal_add_message_type(); + // @@protoc_insertion_point(field_add:google.protobuf.FileDescriptorProto.message_type) + return _add; +} +inline const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::DescriptorProto >& +FileDescriptorProto::message_type() const { + // @@protoc_insertion_point(field_list:google.protobuf.FileDescriptorProto.message_type) + return _impl_.message_type_; +} + +// repeated .google.protobuf.EnumDescriptorProto enum_type = 5; +inline int FileDescriptorProto::_internal_enum_type_size() const { + return _impl_.enum_type_.size(); +} +inline int FileDescriptorProto::enum_type_size() const { + return _internal_enum_type_size(); +} +inline void FileDescriptorProto::clear_enum_type() { + _impl_.enum_type_.Clear(); +} +inline ::PROTOBUF_NAMESPACE_ID::EnumDescriptorProto* FileDescriptorProto::mutable_enum_type(int index) { + // @@protoc_insertion_point(field_mutable:google.protobuf.FileDescriptorProto.enum_type) + return _impl_.enum_type_.Mutable(index); +} +inline ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::EnumDescriptorProto >* +FileDescriptorProto::mutable_enum_type() { + // @@protoc_insertion_point(field_mutable_list:google.protobuf.FileDescriptorProto.enum_type) + return &_impl_.enum_type_; +} +inline const ::PROTOBUF_NAMESPACE_ID::EnumDescriptorProto& FileDescriptorProto::_internal_enum_type(int index) const { + return _impl_.enum_type_.Get(index); +} +inline const ::PROTOBUF_NAMESPACE_ID::EnumDescriptorProto& FileDescriptorProto::enum_type(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.FileDescriptorProto.enum_type) + return _internal_enum_type(index); +} +inline ::PROTOBUF_NAMESPACE_ID::EnumDescriptorProto* FileDescriptorProto::_internal_add_enum_type() { + return _impl_.enum_type_.Add(); +} +inline ::PROTOBUF_NAMESPACE_ID::EnumDescriptorProto* FileDescriptorProto::add_enum_type() { + ::PROTOBUF_NAMESPACE_ID::EnumDescriptorProto* _add = _internal_add_enum_type(); + // @@protoc_insertion_point(field_add:google.protobuf.FileDescriptorProto.enum_type) + return _add; +} +inline const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::EnumDescriptorProto >& +FileDescriptorProto::enum_type() const { + // @@protoc_insertion_point(field_list:google.protobuf.FileDescriptorProto.enum_type) + return _impl_.enum_type_; +} + +// repeated .google.protobuf.ServiceDescriptorProto service = 6; +inline int FileDescriptorProto::_internal_service_size() const { + return _impl_.service_.size(); +} +inline int FileDescriptorProto::service_size() const { + return _internal_service_size(); +} +inline void FileDescriptorProto::clear_service() { + _impl_.service_.Clear(); +} +inline ::PROTOBUF_NAMESPACE_ID::ServiceDescriptorProto* FileDescriptorProto::mutable_service(int index) { + // @@protoc_insertion_point(field_mutable:google.protobuf.FileDescriptorProto.service) + return _impl_.service_.Mutable(index); +} +inline ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::ServiceDescriptorProto >* +FileDescriptorProto::mutable_service() { + // @@protoc_insertion_point(field_mutable_list:google.protobuf.FileDescriptorProto.service) + return &_impl_.service_; +} +inline const ::PROTOBUF_NAMESPACE_ID::ServiceDescriptorProto& FileDescriptorProto::_internal_service(int index) const { + return _impl_.service_.Get(index); +} +inline const ::PROTOBUF_NAMESPACE_ID::ServiceDescriptorProto& FileDescriptorProto::service(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.FileDescriptorProto.service) + return _internal_service(index); +} +inline ::PROTOBUF_NAMESPACE_ID::ServiceDescriptorProto* FileDescriptorProto::_internal_add_service() { + return _impl_.service_.Add(); +} +inline ::PROTOBUF_NAMESPACE_ID::ServiceDescriptorProto* FileDescriptorProto::add_service() { + ::PROTOBUF_NAMESPACE_ID::ServiceDescriptorProto* _add = _internal_add_service(); + // @@protoc_insertion_point(field_add:google.protobuf.FileDescriptorProto.service) + return _add; +} +inline const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::ServiceDescriptorProto >& +FileDescriptorProto::service() const { + // @@protoc_insertion_point(field_list:google.protobuf.FileDescriptorProto.service) + return _impl_.service_; +} + +// repeated .google.protobuf.FieldDescriptorProto extension = 7; +inline int FileDescriptorProto::_internal_extension_size() const { + return _impl_.extension_.size(); +} +inline int FileDescriptorProto::extension_size() const { + return _internal_extension_size(); +} +inline void FileDescriptorProto::clear_extension() { + _impl_.extension_.Clear(); +} +inline ::PROTOBUF_NAMESPACE_ID::FieldDescriptorProto* FileDescriptorProto::mutable_extension(int index) { + // @@protoc_insertion_point(field_mutable:google.protobuf.FileDescriptorProto.extension) + return _impl_.extension_.Mutable(index); +} +inline ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::FieldDescriptorProto >* +FileDescriptorProto::mutable_extension() { + // @@protoc_insertion_point(field_mutable_list:google.protobuf.FileDescriptorProto.extension) + return &_impl_.extension_; +} +inline const ::PROTOBUF_NAMESPACE_ID::FieldDescriptorProto& FileDescriptorProto::_internal_extension(int index) const { + return _impl_.extension_.Get(index); +} +inline const ::PROTOBUF_NAMESPACE_ID::FieldDescriptorProto& FileDescriptorProto::extension(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.FileDescriptorProto.extension) + return _internal_extension(index); +} +inline ::PROTOBUF_NAMESPACE_ID::FieldDescriptorProto* FileDescriptorProto::_internal_add_extension() { + return _impl_.extension_.Add(); +} +inline ::PROTOBUF_NAMESPACE_ID::FieldDescriptorProto* FileDescriptorProto::add_extension() { + ::PROTOBUF_NAMESPACE_ID::FieldDescriptorProto* _add = _internal_add_extension(); + // @@protoc_insertion_point(field_add:google.protobuf.FileDescriptorProto.extension) + return _add; +} +inline const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::FieldDescriptorProto >& +FileDescriptorProto::extension() const { + // @@protoc_insertion_point(field_list:google.protobuf.FileDescriptorProto.extension) + return _impl_.extension_; +} + +// optional .google.protobuf.FileOptions options = 8; +inline bool FileDescriptorProto::_internal_has_options() const { + bool value = (_impl_._has_bits_[0] & 0x00000008u) != 0; + PROTOBUF_ASSUME(!value || _impl_.options_ != nullptr); + return value; +} +inline bool FileDescriptorProto::has_options() const { + return _internal_has_options(); +} +inline void FileDescriptorProto::clear_options() { + if (_impl_.options_ != nullptr) _impl_.options_->Clear(); + _impl_._has_bits_[0] &= ~0x00000008u; +} +inline const ::PROTOBUF_NAMESPACE_ID::FileOptions& FileDescriptorProto::_internal_options() const { + const ::PROTOBUF_NAMESPACE_ID::FileOptions* p = _impl_.options_; + return p != nullptr ? *p : reinterpret_cast<const ::PROTOBUF_NAMESPACE_ID::FileOptions&>( + ::PROTOBUF_NAMESPACE_ID::_FileOptions_default_instance_); +} +inline const ::PROTOBUF_NAMESPACE_ID::FileOptions& FileDescriptorProto::options() const { + // @@protoc_insertion_point(field_get:google.protobuf.FileDescriptorProto.options) + return _internal_options(); +} +inline void FileDescriptorProto::unsafe_arena_set_allocated_options( + ::PROTOBUF_NAMESPACE_ID::FileOptions* options) { + if (GetArenaForAllocation() == nullptr) { + delete reinterpret_cast<::PROTOBUF_NAMESPACE_ID::MessageLite*>(_impl_.options_); + } + _impl_.options_ = options; + if (options) { + _impl_._has_bits_[0] |= 0x00000008u; + } else { + _impl_._has_bits_[0] &= ~0x00000008u; + } + // @@protoc_insertion_point(field_unsafe_arena_set_allocated:google.protobuf.FileDescriptorProto.options) +} +inline ::PROTOBUF_NAMESPACE_ID::FileOptions* FileDescriptorProto::release_options() { + _impl_._has_bits_[0] &= ~0x00000008u; + ::PROTOBUF_NAMESPACE_ID::FileOptions* temp = _impl_.options_; + _impl_.options_ = nullptr; +#ifdef PROTOBUF_FORCE_COPY_IN_RELEASE + auto* old = reinterpret_cast<::PROTOBUF_NAMESPACE_ID::MessageLite*>(temp); + temp = ::PROTOBUF_NAMESPACE_ID::internal::DuplicateIfNonNull(temp); + if (GetArenaForAllocation() == nullptr) { delete old; } +#else // PROTOBUF_FORCE_COPY_IN_RELEASE + if (GetArenaForAllocation() != nullptr) { + temp = ::PROTOBUF_NAMESPACE_ID::internal::DuplicateIfNonNull(temp); + } +#endif // !PROTOBUF_FORCE_COPY_IN_RELEASE + return temp; +} +inline ::PROTOBUF_NAMESPACE_ID::FileOptions* FileDescriptorProto::unsafe_arena_release_options() { + // @@protoc_insertion_point(field_release:google.protobuf.FileDescriptorProto.options) + _impl_._has_bits_[0] &= ~0x00000008u; + ::PROTOBUF_NAMESPACE_ID::FileOptions* temp = _impl_.options_; + _impl_.options_ = nullptr; + return temp; +} +inline ::PROTOBUF_NAMESPACE_ID::FileOptions* FileDescriptorProto::_internal_mutable_options() { + _impl_._has_bits_[0] |= 0x00000008u; + if (_impl_.options_ == nullptr) { + auto* p = CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::FileOptions>(GetArenaForAllocation()); + _impl_.options_ = p; + } + return _impl_.options_; +} +inline ::PROTOBUF_NAMESPACE_ID::FileOptions* FileDescriptorProto::mutable_options() { + ::PROTOBUF_NAMESPACE_ID::FileOptions* _msg = _internal_mutable_options(); + // @@protoc_insertion_point(field_mutable:google.protobuf.FileDescriptorProto.options) + return _msg; +} +inline void FileDescriptorProto::set_allocated_options(::PROTOBUF_NAMESPACE_ID::FileOptions* options) { + ::PROTOBUF_NAMESPACE_ID::Arena* message_arena = GetArenaForAllocation(); + if (message_arena == nullptr) { + delete _impl_.options_; + } + if (options) { + ::PROTOBUF_NAMESPACE_ID::Arena* submessage_arena = + ::PROTOBUF_NAMESPACE_ID::Arena::InternalGetOwningArena(options); + if (message_arena != submessage_arena) { + options = ::PROTOBUF_NAMESPACE_ID::internal::GetOwnedMessage( + message_arena, options, submessage_arena); + } + _impl_._has_bits_[0] |= 0x00000008u; + } else { + _impl_._has_bits_[0] &= ~0x00000008u; + } + _impl_.options_ = options; + // @@protoc_insertion_point(field_set_allocated:google.protobuf.FileDescriptorProto.options) +} + +// optional .google.protobuf.SourceCodeInfo source_code_info = 9; +inline bool FileDescriptorProto::_internal_has_source_code_info() const { + bool value = (_impl_._has_bits_[0] & 0x00000010u) != 0; + PROTOBUF_ASSUME(!value || _impl_.source_code_info_ != nullptr); + return value; +} +inline bool FileDescriptorProto::has_source_code_info() const { + return _internal_has_source_code_info(); +} +inline void FileDescriptorProto::clear_source_code_info() { + if (_impl_.source_code_info_ != nullptr) _impl_.source_code_info_->Clear(); + _impl_._has_bits_[0] &= ~0x00000010u; +} +inline const ::PROTOBUF_NAMESPACE_ID::SourceCodeInfo& FileDescriptorProto::_internal_source_code_info() const { + const ::PROTOBUF_NAMESPACE_ID::SourceCodeInfo* p = _impl_.source_code_info_; + return p != nullptr ? *p : reinterpret_cast<const ::PROTOBUF_NAMESPACE_ID::SourceCodeInfo&>( + ::PROTOBUF_NAMESPACE_ID::_SourceCodeInfo_default_instance_); +} +inline const ::PROTOBUF_NAMESPACE_ID::SourceCodeInfo& FileDescriptorProto::source_code_info() const { + // @@protoc_insertion_point(field_get:google.protobuf.FileDescriptorProto.source_code_info) + return _internal_source_code_info(); +} +inline void FileDescriptorProto::unsafe_arena_set_allocated_source_code_info( + ::PROTOBUF_NAMESPACE_ID::SourceCodeInfo* source_code_info) { + if (GetArenaForAllocation() == nullptr) { + delete reinterpret_cast<::PROTOBUF_NAMESPACE_ID::MessageLite*>(_impl_.source_code_info_); + } + _impl_.source_code_info_ = source_code_info; + if (source_code_info) { + _impl_._has_bits_[0] |= 0x00000010u; + } else { + _impl_._has_bits_[0] &= ~0x00000010u; + } + // @@protoc_insertion_point(field_unsafe_arena_set_allocated:google.protobuf.FileDescriptorProto.source_code_info) +} +inline ::PROTOBUF_NAMESPACE_ID::SourceCodeInfo* FileDescriptorProto::release_source_code_info() { + _impl_._has_bits_[0] &= ~0x00000010u; + ::PROTOBUF_NAMESPACE_ID::SourceCodeInfo* temp = _impl_.source_code_info_; + _impl_.source_code_info_ = nullptr; +#ifdef PROTOBUF_FORCE_COPY_IN_RELEASE + auto* old = reinterpret_cast<::PROTOBUF_NAMESPACE_ID::MessageLite*>(temp); + temp = ::PROTOBUF_NAMESPACE_ID::internal::DuplicateIfNonNull(temp); + if (GetArenaForAllocation() == nullptr) { delete old; } +#else // PROTOBUF_FORCE_COPY_IN_RELEASE + if (GetArenaForAllocation() != nullptr) { + temp = ::PROTOBUF_NAMESPACE_ID::internal::DuplicateIfNonNull(temp); + } +#endif // !PROTOBUF_FORCE_COPY_IN_RELEASE + return temp; +} +inline ::PROTOBUF_NAMESPACE_ID::SourceCodeInfo* FileDescriptorProto::unsafe_arena_release_source_code_info() { + // @@protoc_insertion_point(field_release:google.protobuf.FileDescriptorProto.source_code_info) + _impl_._has_bits_[0] &= ~0x00000010u; + ::PROTOBUF_NAMESPACE_ID::SourceCodeInfo* temp = _impl_.source_code_info_; + _impl_.source_code_info_ = nullptr; + return temp; +} +inline ::PROTOBUF_NAMESPACE_ID::SourceCodeInfo* FileDescriptorProto::_internal_mutable_source_code_info() { + _impl_._has_bits_[0] |= 0x00000010u; + if (_impl_.source_code_info_ == nullptr) { + auto* p = CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::SourceCodeInfo>(GetArenaForAllocation()); + _impl_.source_code_info_ = p; + } + return _impl_.source_code_info_; +} +inline ::PROTOBUF_NAMESPACE_ID::SourceCodeInfo* FileDescriptorProto::mutable_source_code_info() { + ::PROTOBUF_NAMESPACE_ID::SourceCodeInfo* _msg = _internal_mutable_source_code_info(); + // @@protoc_insertion_point(field_mutable:google.protobuf.FileDescriptorProto.source_code_info) + return _msg; +} +inline void FileDescriptorProto::set_allocated_source_code_info(::PROTOBUF_NAMESPACE_ID::SourceCodeInfo* source_code_info) { + ::PROTOBUF_NAMESPACE_ID::Arena* message_arena = GetArenaForAllocation(); + if (message_arena == nullptr) { + delete _impl_.source_code_info_; + } + if (source_code_info) { + ::PROTOBUF_NAMESPACE_ID::Arena* submessage_arena = + ::PROTOBUF_NAMESPACE_ID::Arena::InternalGetOwningArena(source_code_info); + if (message_arena != submessage_arena) { + source_code_info = ::PROTOBUF_NAMESPACE_ID::internal::GetOwnedMessage( + message_arena, source_code_info, submessage_arena); + } + _impl_._has_bits_[0] |= 0x00000010u; + } else { + _impl_._has_bits_[0] &= ~0x00000010u; + } + _impl_.source_code_info_ = source_code_info; + // @@protoc_insertion_point(field_set_allocated:google.protobuf.FileDescriptorProto.source_code_info) +} + +// optional string syntax = 12; +inline bool FileDescriptorProto::_internal_has_syntax() const { + bool value = (_impl_._has_bits_[0] & 0x00000004u) != 0; + return value; +} +inline bool FileDescriptorProto::has_syntax() const { + return _internal_has_syntax(); +} +inline void FileDescriptorProto::clear_syntax() { + _impl_.syntax_.ClearToEmpty(); + _impl_._has_bits_[0] &= ~0x00000004u; +} +inline const std::string& FileDescriptorProto::syntax() const { + // @@protoc_insertion_point(field_get:google.protobuf.FileDescriptorProto.syntax) + return _internal_syntax(); +} +template <typename ArgT0, typename... ArgT> +inline PROTOBUF_ALWAYS_INLINE +void FileDescriptorProto::set_syntax(ArgT0&& arg0, ArgT... args) { + _impl_._has_bits_[0] |= 0x00000004u; + _impl_.syntax_.Set(static_cast<ArgT0 &&>(arg0), args..., GetArenaForAllocation()); + // @@protoc_insertion_point(field_set:google.protobuf.FileDescriptorProto.syntax) +} +inline std::string* FileDescriptorProto::mutable_syntax() { + std::string* _s = _internal_mutable_syntax(); + // @@protoc_insertion_point(field_mutable:google.protobuf.FileDescriptorProto.syntax) + return _s; +} +inline const std::string& FileDescriptorProto::_internal_syntax() const { + return _impl_.syntax_.Get(); +} +inline void FileDescriptorProto::_internal_set_syntax(const std::string& value) { + _impl_._has_bits_[0] |= 0x00000004u; + _impl_.syntax_.Set(value, GetArenaForAllocation()); +} +inline std::string* FileDescriptorProto::_internal_mutable_syntax() { + _impl_._has_bits_[0] |= 0x00000004u; + return _impl_.syntax_.Mutable(GetArenaForAllocation()); +} +inline std::string* FileDescriptorProto::release_syntax() { + // @@protoc_insertion_point(field_release:google.protobuf.FileDescriptorProto.syntax) + if (!_internal_has_syntax()) { + return nullptr; + } + _impl_._has_bits_[0] &= ~0x00000004u; + auto* p = _impl_.syntax_.Release(); +#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (_impl_.syntax_.IsDefault()) { + _impl_.syntax_.Set("", GetArenaForAllocation()); + } +#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + return p; +} +inline void FileDescriptorProto::set_allocated_syntax(std::string* syntax) { + if (syntax != nullptr) { + _impl_._has_bits_[0] |= 0x00000004u; + } else { + _impl_._has_bits_[0] &= ~0x00000004u; + } + _impl_.syntax_.SetAllocated(syntax, GetArenaForAllocation()); +#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (_impl_.syntax_.IsDefault()) { + _impl_.syntax_.Set("", GetArenaForAllocation()); + } +#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + // @@protoc_insertion_point(field_set_allocated:google.protobuf.FileDescriptorProto.syntax) +} + +// ------------------------------------------------------------------- + +// DescriptorProto_ExtensionRange + +// optional int32 start = 1; +inline bool DescriptorProto_ExtensionRange::_internal_has_start() const { + bool value = (_impl_._has_bits_[0] & 0x00000002u) != 0; + return value; +} +inline bool DescriptorProto_ExtensionRange::has_start() const { + return _internal_has_start(); +} +inline void DescriptorProto_ExtensionRange::clear_start() { + _impl_.start_ = 0; + _impl_._has_bits_[0] &= ~0x00000002u; +} +inline int32_t DescriptorProto_ExtensionRange::_internal_start() const { + return _impl_.start_; +} +inline int32_t DescriptorProto_ExtensionRange::start() const { + // @@protoc_insertion_point(field_get:google.protobuf.DescriptorProto.ExtensionRange.start) + return _internal_start(); +} +inline void DescriptorProto_ExtensionRange::_internal_set_start(int32_t value) { + _impl_._has_bits_[0] |= 0x00000002u; + _impl_.start_ = value; +} +inline void DescriptorProto_ExtensionRange::set_start(int32_t value) { + _internal_set_start(value); + // @@protoc_insertion_point(field_set:google.protobuf.DescriptorProto.ExtensionRange.start) +} + +// optional int32 end = 2; +inline bool DescriptorProto_ExtensionRange::_internal_has_end() const { + bool value = (_impl_._has_bits_[0] & 0x00000004u) != 0; + return value; +} +inline bool DescriptorProto_ExtensionRange::has_end() const { + return _internal_has_end(); +} +inline void DescriptorProto_ExtensionRange::clear_end() { + _impl_.end_ = 0; + _impl_._has_bits_[0] &= ~0x00000004u; +} +inline int32_t DescriptorProto_ExtensionRange::_internal_end() const { + return _impl_.end_; +} +inline int32_t DescriptorProto_ExtensionRange::end() const { + // @@protoc_insertion_point(field_get:google.protobuf.DescriptorProto.ExtensionRange.end) + return _internal_end(); +} +inline void DescriptorProto_ExtensionRange::_internal_set_end(int32_t value) { + _impl_._has_bits_[0] |= 0x00000004u; + _impl_.end_ = value; +} +inline void DescriptorProto_ExtensionRange::set_end(int32_t value) { + _internal_set_end(value); + // @@protoc_insertion_point(field_set:google.protobuf.DescriptorProto.ExtensionRange.end) +} + +// optional .google.protobuf.ExtensionRangeOptions options = 3; +inline bool DescriptorProto_ExtensionRange::_internal_has_options() const { + bool value = (_impl_._has_bits_[0] & 0x00000001u) != 0; + PROTOBUF_ASSUME(!value || _impl_.options_ != nullptr); + return value; +} +inline bool DescriptorProto_ExtensionRange::has_options() const { + return _internal_has_options(); +} +inline void DescriptorProto_ExtensionRange::clear_options() { + if (_impl_.options_ != nullptr) _impl_.options_->Clear(); + _impl_._has_bits_[0] &= ~0x00000001u; +} +inline const ::PROTOBUF_NAMESPACE_ID::ExtensionRangeOptions& DescriptorProto_ExtensionRange::_internal_options() const { + const ::PROTOBUF_NAMESPACE_ID::ExtensionRangeOptions* p = _impl_.options_; + return p != nullptr ? *p : reinterpret_cast<const ::PROTOBUF_NAMESPACE_ID::ExtensionRangeOptions&>( + ::PROTOBUF_NAMESPACE_ID::_ExtensionRangeOptions_default_instance_); +} +inline const ::PROTOBUF_NAMESPACE_ID::ExtensionRangeOptions& DescriptorProto_ExtensionRange::options() const { + // @@protoc_insertion_point(field_get:google.protobuf.DescriptorProto.ExtensionRange.options) + return _internal_options(); +} +inline void DescriptorProto_ExtensionRange::unsafe_arena_set_allocated_options( + ::PROTOBUF_NAMESPACE_ID::ExtensionRangeOptions* options) { + if (GetArenaForAllocation() == nullptr) { + delete reinterpret_cast<::PROTOBUF_NAMESPACE_ID::MessageLite*>(_impl_.options_); + } + _impl_.options_ = options; + if (options) { + _impl_._has_bits_[0] |= 0x00000001u; + } else { + _impl_._has_bits_[0] &= ~0x00000001u; + } + // @@protoc_insertion_point(field_unsafe_arena_set_allocated:google.protobuf.DescriptorProto.ExtensionRange.options) +} +inline ::PROTOBUF_NAMESPACE_ID::ExtensionRangeOptions* DescriptorProto_ExtensionRange::release_options() { + _impl_._has_bits_[0] &= ~0x00000001u; + ::PROTOBUF_NAMESPACE_ID::ExtensionRangeOptions* temp = _impl_.options_; + _impl_.options_ = nullptr; +#ifdef PROTOBUF_FORCE_COPY_IN_RELEASE + auto* old = reinterpret_cast<::PROTOBUF_NAMESPACE_ID::MessageLite*>(temp); + temp = ::PROTOBUF_NAMESPACE_ID::internal::DuplicateIfNonNull(temp); + if (GetArenaForAllocation() == nullptr) { delete old; } +#else // PROTOBUF_FORCE_COPY_IN_RELEASE + if (GetArenaForAllocation() != nullptr) { + temp = ::PROTOBUF_NAMESPACE_ID::internal::DuplicateIfNonNull(temp); + } +#endif // !PROTOBUF_FORCE_COPY_IN_RELEASE + return temp; +} +inline ::PROTOBUF_NAMESPACE_ID::ExtensionRangeOptions* DescriptorProto_ExtensionRange::unsafe_arena_release_options() { + // @@protoc_insertion_point(field_release:google.protobuf.DescriptorProto.ExtensionRange.options) + _impl_._has_bits_[0] &= ~0x00000001u; + ::PROTOBUF_NAMESPACE_ID::ExtensionRangeOptions* temp = _impl_.options_; + _impl_.options_ = nullptr; + return temp; +} +inline ::PROTOBUF_NAMESPACE_ID::ExtensionRangeOptions* DescriptorProto_ExtensionRange::_internal_mutable_options() { + _impl_._has_bits_[0] |= 0x00000001u; + if (_impl_.options_ == nullptr) { + auto* p = CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::ExtensionRangeOptions>(GetArenaForAllocation()); + _impl_.options_ = p; + } + return _impl_.options_; +} +inline ::PROTOBUF_NAMESPACE_ID::ExtensionRangeOptions* DescriptorProto_ExtensionRange::mutable_options() { + ::PROTOBUF_NAMESPACE_ID::ExtensionRangeOptions* _msg = _internal_mutable_options(); + // @@protoc_insertion_point(field_mutable:google.protobuf.DescriptorProto.ExtensionRange.options) + return _msg; +} +inline void DescriptorProto_ExtensionRange::set_allocated_options(::PROTOBUF_NAMESPACE_ID::ExtensionRangeOptions* options) { + ::PROTOBUF_NAMESPACE_ID::Arena* message_arena = GetArenaForAllocation(); + if (message_arena == nullptr) { + delete _impl_.options_; + } + if (options) { + ::PROTOBUF_NAMESPACE_ID::Arena* submessage_arena = + ::PROTOBUF_NAMESPACE_ID::Arena::InternalGetOwningArena(options); + if (message_arena != submessage_arena) { + options = ::PROTOBUF_NAMESPACE_ID::internal::GetOwnedMessage( + message_arena, options, submessage_arena); + } + _impl_._has_bits_[0] |= 0x00000001u; + } else { + _impl_._has_bits_[0] &= ~0x00000001u; + } + _impl_.options_ = options; + // @@protoc_insertion_point(field_set_allocated:google.protobuf.DescriptorProto.ExtensionRange.options) +} + +// ------------------------------------------------------------------- + +// DescriptorProto_ReservedRange + +// optional int32 start = 1; +inline bool DescriptorProto_ReservedRange::_internal_has_start() const { + bool value = (_impl_._has_bits_[0] & 0x00000001u) != 0; + return value; +} +inline bool DescriptorProto_ReservedRange::has_start() const { + return _internal_has_start(); +} +inline void DescriptorProto_ReservedRange::clear_start() { + _impl_.start_ = 0; + _impl_._has_bits_[0] &= ~0x00000001u; +} +inline int32_t DescriptorProto_ReservedRange::_internal_start() const { + return _impl_.start_; +} +inline int32_t DescriptorProto_ReservedRange::start() const { + // @@protoc_insertion_point(field_get:google.protobuf.DescriptorProto.ReservedRange.start) + return _internal_start(); +} +inline void DescriptorProto_ReservedRange::_internal_set_start(int32_t value) { + _impl_._has_bits_[0] |= 0x00000001u; + _impl_.start_ = value; +} +inline void DescriptorProto_ReservedRange::set_start(int32_t value) { + _internal_set_start(value); + // @@protoc_insertion_point(field_set:google.protobuf.DescriptorProto.ReservedRange.start) +} + +// optional int32 end = 2; +inline bool DescriptorProto_ReservedRange::_internal_has_end() const { + bool value = (_impl_._has_bits_[0] & 0x00000002u) != 0; + return value; +} +inline bool DescriptorProto_ReservedRange::has_end() const { + return _internal_has_end(); +} +inline void DescriptorProto_ReservedRange::clear_end() { + _impl_.end_ = 0; + _impl_._has_bits_[0] &= ~0x00000002u; +} +inline int32_t DescriptorProto_ReservedRange::_internal_end() const { + return _impl_.end_; +} +inline int32_t DescriptorProto_ReservedRange::end() const { + // @@protoc_insertion_point(field_get:google.protobuf.DescriptorProto.ReservedRange.end) + return _internal_end(); +} +inline void DescriptorProto_ReservedRange::_internal_set_end(int32_t value) { + _impl_._has_bits_[0] |= 0x00000002u; + _impl_.end_ = value; +} +inline void DescriptorProto_ReservedRange::set_end(int32_t value) { + _internal_set_end(value); + // @@protoc_insertion_point(field_set:google.protobuf.DescriptorProto.ReservedRange.end) +} + +// ------------------------------------------------------------------- + +// DescriptorProto + +// optional string name = 1; +inline bool DescriptorProto::_internal_has_name() const { + bool value = (_impl_._has_bits_[0] & 0x00000001u) != 0; + return value; +} +inline bool DescriptorProto::has_name() const { + return _internal_has_name(); +} +inline void DescriptorProto::clear_name() { + _impl_.name_.ClearToEmpty(); + _impl_._has_bits_[0] &= ~0x00000001u; +} +inline const std::string& DescriptorProto::name() const { + // @@protoc_insertion_point(field_get:google.protobuf.DescriptorProto.name) + return _internal_name(); +} +template <typename ArgT0, typename... ArgT> +inline PROTOBUF_ALWAYS_INLINE +void DescriptorProto::set_name(ArgT0&& arg0, ArgT... args) { + _impl_._has_bits_[0] |= 0x00000001u; + _impl_.name_.Set(static_cast<ArgT0 &&>(arg0), args..., GetArenaForAllocation()); + // @@protoc_insertion_point(field_set:google.protobuf.DescriptorProto.name) +} +inline std::string* DescriptorProto::mutable_name() { + std::string* _s = _internal_mutable_name(); + // @@protoc_insertion_point(field_mutable:google.protobuf.DescriptorProto.name) + return _s; +} +inline const std::string& DescriptorProto::_internal_name() const { + return _impl_.name_.Get(); +} +inline void DescriptorProto::_internal_set_name(const std::string& value) { + _impl_._has_bits_[0] |= 0x00000001u; + _impl_.name_.Set(value, GetArenaForAllocation()); +} +inline std::string* DescriptorProto::_internal_mutable_name() { + _impl_._has_bits_[0] |= 0x00000001u; + return _impl_.name_.Mutable(GetArenaForAllocation()); +} +inline std::string* DescriptorProto::release_name() { + // @@protoc_insertion_point(field_release:google.protobuf.DescriptorProto.name) + if (!_internal_has_name()) { + return nullptr; + } + _impl_._has_bits_[0] &= ~0x00000001u; + auto* p = _impl_.name_.Release(); +#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (_impl_.name_.IsDefault()) { + _impl_.name_.Set("", GetArenaForAllocation()); + } +#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + return p; +} +inline void DescriptorProto::set_allocated_name(std::string* name) { + if (name != nullptr) { + _impl_._has_bits_[0] |= 0x00000001u; + } else { + _impl_._has_bits_[0] &= ~0x00000001u; + } + _impl_.name_.SetAllocated(name, GetArenaForAllocation()); +#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (_impl_.name_.IsDefault()) { + _impl_.name_.Set("", GetArenaForAllocation()); + } +#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + // @@protoc_insertion_point(field_set_allocated:google.protobuf.DescriptorProto.name) +} + +// repeated .google.protobuf.FieldDescriptorProto field = 2; +inline int DescriptorProto::_internal_field_size() const { + return _impl_.field_.size(); +} +inline int DescriptorProto::field_size() const { + return _internal_field_size(); +} +inline void DescriptorProto::clear_field() { + _impl_.field_.Clear(); +} +inline ::PROTOBUF_NAMESPACE_ID::FieldDescriptorProto* DescriptorProto::mutable_field(int index) { + // @@protoc_insertion_point(field_mutable:google.protobuf.DescriptorProto.field) + return _impl_.field_.Mutable(index); +} +inline ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::FieldDescriptorProto >* +DescriptorProto::mutable_field() { + // @@protoc_insertion_point(field_mutable_list:google.protobuf.DescriptorProto.field) + return &_impl_.field_; +} +inline const ::PROTOBUF_NAMESPACE_ID::FieldDescriptorProto& DescriptorProto::_internal_field(int index) const { + return _impl_.field_.Get(index); +} +inline const ::PROTOBUF_NAMESPACE_ID::FieldDescriptorProto& DescriptorProto::field(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.DescriptorProto.field) + return _internal_field(index); +} +inline ::PROTOBUF_NAMESPACE_ID::FieldDescriptorProto* DescriptorProto::_internal_add_field() { + return _impl_.field_.Add(); +} +inline ::PROTOBUF_NAMESPACE_ID::FieldDescriptorProto* DescriptorProto::add_field() { + ::PROTOBUF_NAMESPACE_ID::FieldDescriptorProto* _add = _internal_add_field(); + // @@protoc_insertion_point(field_add:google.protobuf.DescriptorProto.field) + return _add; +} +inline const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::FieldDescriptorProto >& +DescriptorProto::field() const { + // @@protoc_insertion_point(field_list:google.protobuf.DescriptorProto.field) + return _impl_.field_; +} + +// repeated .google.protobuf.FieldDescriptorProto extension = 6; +inline int DescriptorProto::_internal_extension_size() const { + return _impl_.extension_.size(); +} +inline int DescriptorProto::extension_size() const { + return _internal_extension_size(); +} +inline void DescriptorProto::clear_extension() { + _impl_.extension_.Clear(); +} +inline ::PROTOBUF_NAMESPACE_ID::FieldDescriptorProto* DescriptorProto::mutable_extension(int index) { + // @@protoc_insertion_point(field_mutable:google.protobuf.DescriptorProto.extension) + return _impl_.extension_.Mutable(index); +} +inline ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::FieldDescriptorProto >* +DescriptorProto::mutable_extension() { + // @@protoc_insertion_point(field_mutable_list:google.protobuf.DescriptorProto.extension) + return &_impl_.extension_; +} +inline const ::PROTOBUF_NAMESPACE_ID::FieldDescriptorProto& DescriptorProto::_internal_extension(int index) const { + return _impl_.extension_.Get(index); +} +inline const ::PROTOBUF_NAMESPACE_ID::FieldDescriptorProto& DescriptorProto::extension(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.DescriptorProto.extension) + return _internal_extension(index); +} +inline ::PROTOBUF_NAMESPACE_ID::FieldDescriptorProto* DescriptorProto::_internal_add_extension() { + return _impl_.extension_.Add(); +} +inline ::PROTOBUF_NAMESPACE_ID::FieldDescriptorProto* DescriptorProto::add_extension() { + ::PROTOBUF_NAMESPACE_ID::FieldDescriptorProto* _add = _internal_add_extension(); + // @@protoc_insertion_point(field_add:google.protobuf.DescriptorProto.extension) + return _add; +} +inline const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::FieldDescriptorProto >& +DescriptorProto::extension() const { + // @@protoc_insertion_point(field_list:google.protobuf.DescriptorProto.extension) + return _impl_.extension_; +} + +// repeated .google.protobuf.DescriptorProto nested_type = 3; +inline int DescriptorProto::_internal_nested_type_size() const { + return _impl_.nested_type_.size(); +} +inline int DescriptorProto::nested_type_size() const { + return _internal_nested_type_size(); +} +inline void DescriptorProto::clear_nested_type() { + _impl_.nested_type_.Clear(); +} +inline ::PROTOBUF_NAMESPACE_ID::DescriptorProto* DescriptorProto::mutable_nested_type(int index) { + // @@protoc_insertion_point(field_mutable:google.protobuf.DescriptorProto.nested_type) + return _impl_.nested_type_.Mutable(index); +} +inline ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::DescriptorProto >* +DescriptorProto::mutable_nested_type() { + // @@protoc_insertion_point(field_mutable_list:google.protobuf.DescriptorProto.nested_type) + return &_impl_.nested_type_; +} +inline const ::PROTOBUF_NAMESPACE_ID::DescriptorProto& DescriptorProto::_internal_nested_type(int index) const { + return _impl_.nested_type_.Get(index); +} +inline const ::PROTOBUF_NAMESPACE_ID::DescriptorProto& DescriptorProto::nested_type(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.DescriptorProto.nested_type) + return _internal_nested_type(index); +} +inline ::PROTOBUF_NAMESPACE_ID::DescriptorProto* DescriptorProto::_internal_add_nested_type() { + return _impl_.nested_type_.Add(); +} +inline ::PROTOBUF_NAMESPACE_ID::DescriptorProto* DescriptorProto::add_nested_type() { + ::PROTOBUF_NAMESPACE_ID::DescriptorProto* _add = _internal_add_nested_type(); + // @@protoc_insertion_point(field_add:google.protobuf.DescriptorProto.nested_type) + return _add; +} +inline const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::DescriptorProto >& +DescriptorProto::nested_type() const { + // @@protoc_insertion_point(field_list:google.protobuf.DescriptorProto.nested_type) + return _impl_.nested_type_; +} + +// repeated .google.protobuf.EnumDescriptorProto enum_type = 4; +inline int DescriptorProto::_internal_enum_type_size() const { + return _impl_.enum_type_.size(); +} +inline int DescriptorProto::enum_type_size() const { + return _internal_enum_type_size(); +} +inline void DescriptorProto::clear_enum_type() { + _impl_.enum_type_.Clear(); +} +inline ::PROTOBUF_NAMESPACE_ID::EnumDescriptorProto* DescriptorProto::mutable_enum_type(int index) { + // @@protoc_insertion_point(field_mutable:google.protobuf.DescriptorProto.enum_type) + return _impl_.enum_type_.Mutable(index); +} +inline ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::EnumDescriptorProto >* +DescriptorProto::mutable_enum_type() { + // @@protoc_insertion_point(field_mutable_list:google.protobuf.DescriptorProto.enum_type) + return &_impl_.enum_type_; +} +inline const ::PROTOBUF_NAMESPACE_ID::EnumDescriptorProto& DescriptorProto::_internal_enum_type(int index) const { + return _impl_.enum_type_.Get(index); +} +inline const ::PROTOBUF_NAMESPACE_ID::EnumDescriptorProto& DescriptorProto::enum_type(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.DescriptorProto.enum_type) + return _internal_enum_type(index); +} +inline ::PROTOBUF_NAMESPACE_ID::EnumDescriptorProto* DescriptorProto::_internal_add_enum_type() { + return _impl_.enum_type_.Add(); +} +inline ::PROTOBUF_NAMESPACE_ID::EnumDescriptorProto* DescriptorProto::add_enum_type() { + ::PROTOBUF_NAMESPACE_ID::EnumDescriptorProto* _add = _internal_add_enum_type(); + // @@protoc_insertion_point(field_add:google.protobuf.DescriptorProto.enum_type) + return _add; +} +inline const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::EnumDescriptorProto >& +DescriptorProto::enum_type() const { + // @@protoc_insertion_point(field_list:google.protobuf.DescriptorProto.enum_type) + return _impl_.enum_type_; +} + +// repeated .google.protobuf.DescriptorProto.ExtensionRange extension_range = 5; +inline int DescriptorProto::_internal_extension_range_size() const { + return _impl_.extension_range_.size(); +} +inline int DescriptorProto::extension_range_size() const { + return _internal_extension_range_size(); +} +inline void DescriptorProto::clear_extension_range() { + _impl_.extension_range_.Clear(); +} +inline ::PROTOBUF_NAMESPACE_ID::DescriptorProto_ExtensionRange* DescriptorProto::mutable_extension_range(int index) { + // @@protoc_insertion_point(field_mutable:google.protobuf.DescriptorProto.extension_range) + return _impl_.extension_range_.Mutable(index); +} +inline ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::DescriptorProto_ExtensionRange >* +DescriptorProto::mutable_extension_range() { + // @@protoc_insertion_point(field_mutable_list:google.protobuf.DescriptorProto.extension_range) + return &_impl_.extension_range_; +} +inline const ::PROTOBUF_NAMESPACE_ID::DescriptorProto_ExtensionRange& DescriptorProto::_internal_extension_range(int index) const { + return _impl_.extension_range_.Get(index); +} +inline const ::PROTOBUF_NAMESPACE_ID::DescriptorProto_ExtensionRange& DescriptorProto::extension_range(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.DescriptorProto.extension_range) + return _internal_extension_range(index); +} +inline ::PROTOBUF_NAMESPACE_ID::DescriptorProto_ExtensionRange* DescriptorProto::_internal_add_extension_range() { + return _impl_.extension_range_.Add(); +} +inline ::PROTOBUF_NAMESPACE_ID::DescriptorProto_ExtensionRange* DescriptorProto::add_extension_range() { + ::PROTOBUF_NAMESPACE_ID::DescriptorProto_ExtensionRange* _add = _internal_add_extension_range(); + // @@protoc_insertion_point(field_add:google.protobuf.DescriptorProto.extension_range) + return _add; +} +inline const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::DescriptorProto_ExtensionRange >& +DescriptorProto::extension_range() const { + // @@protoc_insertion_point(field_list:google.protobuf.DescriptorProto.extension_range) + return _impl_.extension_range_; +} + +// repeated .google.protobuf.OneofDescriptorProto oneof_decl = 8; +inline int DescriptorProto::_internal_oneof_decl_size() const { + return _impl_.oneof_decl_.size(); +} +inline int DescriptorProto::oneof_decl_size() const { + return _internal_oneof_decl_size(); +} +inline void DescriptorProto::clear_oneof_decl() { + _impl_.oneof_decl_.Clear(); +} +inline ::PROTOBUF_NAMESPACE_ID::OneofDescriptorProto* DescriptorProto::mutable_oneof_decl(int index) { + // @@protoc_insertion_point(field_mutable:google.protobuf.DescriptorProto.oneof_decl) + return _impl_.oneof_decl_.Mutable(index); +} +inline ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::OneofDescriptorProto >* +DescriptorProto::mutable_oneof_decl() { + // @@protoc_insertion_point(field_mutable_list:google.protobuf.DescriptorProto.oneof_decl) + return &_impl_.oneof_decl_; +} +inline const ::PROTOBUF_NAMESPACE_ID::OneofDescriptorProto& DescriptorProto::_internal_oneof_decl(int index) const { + return _impl_.oneof_decl_.Get(index); +} +inline const ::PROTOBUF_NAMESPACE_ID::OneofDescriptorProto& DescriptorProto::oneof_decl(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.DescriptorProto.oneof_decl) + return _internal_oneof_decl(index); +} +inline ::PROTOBUF_NAMESPACE_ID::OneofDescriptorProto* DescriptorProto::_internal_add_oneof_decl() { + return _impl_.oneof_decl_.Add(); +} +inline ::PROTOBUF_NAMESPACE_ID::OneofDescriptorProto* DescriptorProto::add_oneof_decl() { + ::PROTOBUF_NAMESPACE_ID::OneofDescriptorProto* _add = _internal_add_oneof_decl(); + // @@protoc_insertion_point(field_add:google.protobuf.DescriptorProto.oneof_decl) + return _add; +} +inline const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::OneofDescriptorProto >& +DescriptorProto::oneof_decl() const { + // @@protoc_insertion_point(field_list:google.protobuf.DescriptorProto.oneof_decl) + return _impl_.oneof_decl_; +} + +// optional .google.protobuf.MessageOptions options = 7; +inline bool DescriptorProto::_internal_has_options() const { + bool value = (_impl_._has_bits_[0] & 0x00000002u) != 0; + PROTOBUF_ASSUME(!value || _impl_.options_ != nullptr); + return value; +} +inline bool DescriptorProto::has_options() const { + return _internal_has_options(); +} +inline void DescriptorProto::clear_options() { + if (_impl_.options_ != nullptr) _impl_.options_->Clear(); + _impl_._has_bits_[0] &= ~0x00000002u; +} +inline const ::PROTOBUF_NAMESPACE_ID::MessageOptions& DescriptorProto::_internal_options() const { + const ::PROTOBUF_NAMESPACE_ID::MessageOptions* p = _impl_.options_; + return p != nullptr ? *p : reinterpret_cast<const ::PROTOBUF_NAMESPACE_ID::MessageOptions&>( + ::PROTOBUF_NAMESPACE_ID::_MessageOptions_default_instance_); +} +inline const ::PROTOBUF_NAMESPACE_ID::MessageOptions& DescriptorProto::options() const { + // @@protoc_insertion_point(field_get:google.protobuf.DescriptorProto.options) + return _internal_options(); +} +inline void DescriptorProto::unsafe_arena_set_allocated_options( + ::PROTOBUF_NAMESPACE_ID::MessageOptions* options) { + if (GetArenaForAllocation() == nullptr) { + delete reinterpret_cast<::PROTOBUF_NAMESPACE_ID::MessageLite*>(_impl_.options_); + } + _impl_.options_ = options; + if (options) { + _impl_._has_bits_[0] |= 0x00000002u; + } else { + _impl_._has_bits_[0] &= ~0x00000002u; + } + // @@protoc_insertion_point(field_unsafe_arena_set_allocated:google.protobuf.DescriptorProto.options) +} +inline ::PROTOBUF_NAMESPACE_ID::MessageOptions* DescriptorProto::release_options() { + _impl_._has_bits_[0] &= ~0x00000002u; + ::PROTOBUF_NAMESPACE_ID::MessageOptions* temp = _impl_.options_; + _impl_.options_ = nullptr; +#ifdef PROTOBUF_FORCE_COPY_IN_RELEASE + auto* old = reinterpret_cast<::PROTOBUF_NAMESPACE_ID::MessageLite*>(temp); + temp = ::PROTOBUF_NAMESPACE_ID::internal::DuplicateIfNonNull(temp); + if (GetArenaForAllocation() == nullptr) { delete old; } +#else // PROTOBUF_FORCE_COPY_IN_RELEASE + if (GetArenaForAllocation() != nullptr) { + temp = ::PROTOBUF_NAMESPACE_ID::internal::DuplicateIfNonNull(temp); + } +#endif // !PROTOBUF_FORCE_COPY_IN_RELEASE + return temp; +} +inline ::PROTOBUF_NAMESPACE_ID::MessageOptions* DescriptorProto::unsafe_arena_release_options() { + // @@protoc_insertion_point(field_release:google.protobuf.DescriptorProto.options) + _impl_._has_bits_[0] &= ~0x00000002u; + ::PROTOBUF_NAMESPACE_ID::MessageOptions* temp = _impl_.options_; + _impl_.options_ = nullptr; + return temp; +} +inline ::PROTOBUF_NAMESPACE_ID::MessageOptions* DescriptorProto::_internal_mutable_options() { + _impl_._has_bits_[0] |= 0x00000002u; + if (_impl_.options_ == nullptr) { + auto* p = CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::MessageOptions>(GetArenaForAllocation()); + _impl_.options_ = p; + } + return _impl_.options_; +} +inline ::PROTOBUF_NAMESPACE_ID::MessageOptions* DescriptorProto::mutable_options() { + ::PROTOBUF_NAMESPACE_ID::MessageOptions* _msg = _internal_mutable_options(); + // @@protoc_insertion_point(field_mutable:google.protobuf.DescriptorProto.options) + return _msg; +} +inline void DescriptorProto::set_allocated_options(::PROTOBUF_NAMESPACE_ID::MessageOptions* options) { + ::PROTOBUF_NAMESPACE_ID::Arena* message_arena = GetArenaForAllocation(); + if (message_arena == nullptr) { + delete _impl_.options_; + } + if (options) { + ::PROTOBUF_NAMESPACE_ID::Arena* submessage_arena = + ::PROTOBUF_NAMESPACE_ID::Arena::InternalGetOwningArena(options); + if (message_arena != submessage_arena) { + options = ::PROTOBUF_NAMESPACE_ID::internal::GetOwnedMessage( + message_arena, options, submessage_arena); + } + _impl_._has_bits_[0] |= 0x00000002u; + } else { + _impl_._has_bits_[0] &= ~0x00000002u; + } + _impl_.options_ = options; + // @@protoc_insertion_point(field_set_allocated:google.protobuf.DescriptorProto.options) +} + +// repeated .google.protobuf.DescriptorProto.ReservedRange reserved_range = 9; +inline int DescriptorProto::_internal_reserved_range_size() const { + return _impl_.reserved_range_.size(); +} +inline int DescriptorProto::reserved_range_size() const { + return _internal_reserved_range_size(); +} +inline void DescriptorProto::clear_reserved_range() { + _impl_.reserved_range_.Clear(); +} +inline ::PROTOBUF_NAMESPACE_ID::DescriptorProto_ReservedRange* DescriptorProto::mutable_reserved_range(int index) { + // @@protoc_insertion_point(field_mutable:google.protobuf.DescriptorProto.reserved_range) + return _impl_.reserved_range_.Mutable(index); +} +inline ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::DescriptorProto_ReservedRange >* +DescriptorProto::mutable_reserved_range() { + // @@protoc_insertion_point(field_mutable_list:google.protobuf.DescriptorProto.reserved_range) + return &_impl_.reserved_range_; +} +inline const ::PROTOBUF_NAMESPACE_ID::DescriptorProto_ReservedRange& DescriptorProto::_internal_reserved_range(int index) const { + return _impl_.reserved_range_.Get(index); +} +inline const ::PROTOBUF_NAMESPACE_ID::DescriptorProto_ReservedRange& DescriptorProto::reserved_range(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.DescriptorProto.reserved_range) + return _internal_reserved_range(index); +} +inline ::PROTOBUF_NAMESPACE_ID::DescriptorProto_ReservedRange* DescriptorProto::_internal_add_reserved_range() { + return _impl_.reserved_range_.Add(); +} +inline ::PROTOBUF_NAMESPACE_ID::DescriptorProto_ReservedRange* DescriptorProto::add_reserved_range() { + ::PROTOBUF_NAMESPACE_ID::DescriptorProto_ReservedRange* _add = _internal_add_reserved_range(); + // @@protoc_insertion_point(field_add:google.protobuf.DescriptorProto.reserved_range) + return _add; +} +inline const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::DescriptorProto_ReservedRange >& +DescriptorProto::reserved_range() const { + // @@protoc_insertion_point(field_list:google.protobuf.DescriptorProto.reserved_range) + return _impl_.reserved_range_; +} + +// repeated string reserved_name = 10; +inline int DescriptorProto::_internal_reserved_name_size() const { + return _impl_.reserved_name_.size(); +} +inline int DescriptorProto::reserved_name_size() const { + return _internal_reserved_name_size(); +} +inline void DescriptorProto::clear_reserved_name() { + _impl_.reserved_name_.Clear(); +} +inline std::string* DescriptorProto::add_reserved_name() { + std::string* _s = _internal_add_reserved_name(); + // @@protoc_insertion_point(field_add_mutable:google.protobuf.DescriptorProto.reserved_name) + return _s; +} +inline const std::string& DescriptorProto::_internal_reserved_name(int index) const { + return _impl_.reserved_name_.Get(index); +} +inline const std::string& DescriptorProto::reserved_name(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.DescriptorProto.reserved_name) + return _internal_reserved_name(index); +} +inline std::string* DescriptorProto::mutable_reserved_name(int index) { + // @@protoc_insertion_point(field_mutable:google.protobuf.DescriptorProto.reserved_name) + return _impl_.reserved_name_.Mutable(index); +} +inline void DescriptorProto::set_reserved_name(int index, const std::string& value) { + _impl_.reserved_name_.Mutable(index)->assign(value); + // @@protoc_insertion_point(field_set:google.protobuf.DescriptorProto.reserved_name) +} +inline void DescriptorProto::set_reserved_name(int index, std::string&& value) { + _impl_.reserved_name_.Mutable(index)->assign(std::move(value)); + // @@protoc_insertion_point(field_set:google.protobuf.DescriptorProto.reserved_name) +} +inline void DescriptorProto::set_reserved_name(int index, const char* value) { + GOOGLE_DCHECK(value != nullptr); + _impl_.reserved_name_.Mutable(index)->assign(value); + // @@protoc_insertion_point(field_set_char:google.protobuf.DescriptorProto.reserved_name) +} +inline void DescriptorProto::set_reserved_name(int index, const char* value, size_t size) { + _impl_.reserved_name_.Mutable(index)->assign( + reinterpret_cast<const char*>(value), size); + // @@protoc_insertion_point(field_set_pointer:google.protobuf.DescriptorProto.reserved_name) +} +inline std::string* DescriptorProto::_internal_add_reserved_name() { + return _impl_.reserved_name_.Add(); +} +inline void DescriptorProto::add_reserved_name(const std::string& value) { + _impl_.reserved_name_.Add()->assign(value); + // @@protoc_insertion_point(field_add:google.protobuf.DescriptorProto.reserved_name) +} +inline void DescriptorProto::add_reserved_name(std::string&& value) { + _impl_.reserved_name_.Add(std::move(value)); + // @@protoc_insertion_point(field_add:google.protobuf.DescriptorProto.reserved_name) +} +inline void DescriptorProto::add_reserved_name(const char* value) { + GOOGLE_DCHECK(value != nullptr); + _impl_.reserved_name_.Add()->assign(value); + // @@protoc_insertion_point(field_add_char:google.protobuf.DescriptorProto.reserved_name) +} +inline void DescriptorProto::add_reserved_name(const char* value, size_t size) { + _impl_.reserved_name_.Add()->assign(reinterpret_cast<const char*>(value), size); + // @@protoc_insertion_point(field_add_pointer:google.protobuf.DescriptorProto.reserved_name) +} +inline const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField<std::string>& +DescriptorProto::reserved_name() const { + // @@protoc_insertion_point(field_list:google.protobuf.DescriptorProto.reserved_name) + return _impl_.reserved_name_; +} +inline ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField<std::string>* +DescriptorProto::mutable_reserved_name() { + // @@protoc_insertion_point(field_mutable_list:google.protobuf.DescriptorProto.reserved_name) + return &_impl_.reserved_name_; +} + +// ------------------------------------------------------------------- + +// ExtensionRangeOptions + +// repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; +inline int ExtensionRangeOptions::_internal_uninterpreted_option_size() const { + return _impl_.uninterpreted_option_.size(); +} +inline int ExtensionRangeOptions::uninterpreted_option_size() const { + return _internal_uninterpreted_option_size(); +} +inline void ExtensionRangeOptions::clear_uninterpreted_option() { + _impl_.uninterpreted_option_.Clear(); +} +inline ::PROTOBUF_NAMESPACE_ID::UninterpretedOption* ExtensionRangeOptions::mutable_uninterpreted_option(int index) { + // @@protoc_insertion_point(field_mutable:google.protobuf.ExtensionRangeOptions.uninterpreted_option) + return _impl_.uninterpreted_option_.Mutable(index); +} +inline ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::UninterpretedOption >* +ExtensionRangeOptions::mutable_uninterpreted_option() { + // @@protoc_insertion_point(field_mutable_list:google.protobuf.ExtensionRangeOptions.uninterpreted_option) + return &_impl_.uninterpreted_option_; +} +inline const ::PROTOBUF_NAMESPACE_ID::UninterpretedOption& ExtensionRangeOptions::_internal_uninterpreted_option(int index) const { + return _impl_.uninterpreted_option_.Get(index); +} +inline const ::PROTOBUF_NAMESPACE_ID::UninterpretedOption& ExtensionRangeOptions::uninterpreted_option(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.ExtensionRangeOptions.uninterpreted_option) + return _internal_uninterpreted_option(index); +} +inline ::PROTOBUF_NAMESPACE_ID::UninterpretedOption* ExtensionRangeOptions::_internal_add_uninterpreted_option() { + return _impl_.uninterpreted_option_.Add(); +} +inline ::PROTOBUF_NAMESPACE_ID::UninterpretedOption* ExtensionRangeOptions::add_uninterpreted_option() { + ::PROTOBUF_NAMESPACE_ID::UninterpretedOption* _add = _internal_add_uninterpreted_option(); + // @@protoc_insertion_point(field_add:google.protobuf.ExtensionRangeOptions.uninterpreted_option) + return _add; +} +inline const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::UninterpretedOption >& +ExtensionRangeOptions::uninterpreted_option() const { + // @@protoc_insertion_point(field_list:google.protobuf.ExtensionRangeOptions.uninterpreted_option) + return _impl_.uninterpreted_option_; +} + +// ------------------------------------------------------------------- + +// FieldDescriptorProto + +// optional string name = 1; +inline bool FieldDescriptorProto::_internal_has_name() const { + bool value = (_impl_._has_bits_[0] & 0x00000001u) != 0; + return value; +} +inline bool FieldDescriptorProto::has_name() const { + return _internal_has_name(); +} +inline void FieldDescriptorProto::clear_name() { + _impl_.name_.ClearToEmpty(); + _impl_._has_bits_[0] &= ~0x00000001u; +} +inline const std::string& FieldDescriptorProto::name() const { + // @@protoc_insertion_point(field_get:google.protobuf.FieldDescriptorProto.name) + return _internal_name(); +} +template <typename ArgT0, typename... ArgT> +inline PROTOBUF_ALWAYS_INLINE +void FieldDescriptorProto::set_name(ArgT0&& arg0, ArgT... args) { + _impl_._has_bits_[0] |= 0x00000001u; + _impl_.name_.Set(static_cast<ArgT0 &&>(arg0), args..., GetArenaForAllocation()); + // @@protoc_insertion_point(field_set:google.protobuf.FieldDescriptorProto.name) +} +inline std::string* FieldDescriptorProto::mutable_name() { + std::string* _s = _internal_mutable_name(); + // @@protoc_insertion_point(field_mutable:google.protobuf.FieldDescriptorProto.name) + return _s; +} +inline const std::string& FieldDescriptorProto::_internal_name() const { + return _impl_.name_.Get(); +} +inline void FieldDescriptorProto::_internal_set_name(const std::string& value) { + _impl_._has_bits_[0] |= 0x00000001u; + _impl_.name_.Set(value, GetArenaForAllocation()); +} +inline std::string* FieldDescriptorProto::_internal_mutable_name() { + _impl_._has_bits_[0] |= 0x00000001u; + return _impl_.name_.Mutable(GetArenaForAllocation()); +} +inline std::string* FieldDescriptorProto::release_name() { + // @@protoc_insertion_point(field_release:google.protobuf.FieldDescriptorProto.name) + if (!_internal_has_name()) { + return nullptr; + } + _impl_._has_bits_[0] &= ~0x00000001u; + auto* p = _impl_.name_.Release(); +#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (_impl_.name_.IsDefault()) { + _impl_.name_.Set("", GetArenaForAllocation()); + } +#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + return p; +} +inline void FieldDescriptorProto::set_allocated_name(std::string* name) { + if (name != nullptr) { + _impl_._has_bits_[0] |= 0x00000001u; + } else { + _impl_._has_bits_[0] &= ~0x00000001u; + } + _impl_.name_.SetAllocated(name, GetArenaForAllocation()); +#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (_impl_.name_.IsDefault()) { + _impl_.name_.Set("", GetArenaForAllocation()); + } +#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + // @@protoc_insertion_point(field_set_allocated:google.protobuf.FieldDescriptorProto.name) +} + +// optional int32 number = 3; +inline bool FieldDescriptorProto::_internal_has_number() const { + bool value = (_impl_._has_bits_[0] & 0x00000040u) != 0; + return value; +} +inline bool FieldDescriptorProto::has_number() const { + return _internal_has_number(); +} +inline void FieldDescriptorProto::clear_number() { + _impl_.number_ = 0; + _impl_._has_bits_[0] &= ~0x00000040u; +} +inline int32_t FieldDescriptorProto::_internal_number() const { + return _impl_.number_; +} +inline int32_t FieldDescriptorProto::number() const { + // @@protoc_insertion_point(field_get:google.protobuf.FieldDescriptorProto.number) + return _internal_number(); +} +inline void FieldDescriptorProto::_internal_set_number(int32_t value) { + _impl_._has_bits_[0] |= 0x00000040u; + _impl_.number_ = value; +} +inline void FieldDescriptorProto::set_number(int32_t value) { + _internal_set_number(value); + // @@protoc_insertion_point(field_set:google.protobuf.FieldDescriptorProto.number) +} + +// optional .google.protobuf.FieldDescriptorProto.Label label = 4; +inline bool FieldDescriptorProto::_internal_has_label() const { + bool value = (_impl_._has_bits_[0] & 0x00000200u) != 0; + return value; +} +inline bool FieldDescriptorProto::has_label() const { + return _internal_has_label(); +} +inline void FieldDescriptorProto::clear_label() { + _impl_.label_ = 1; + _impl_._has_bits_[0] &= ~0x00000200u; +} +inline ::PROTOBUF_NAMESPACE_ID::FieldDescriptorProto_Label FieldDescriptorProto::_internal_label() const { + return static_cast< ::PROTOBUF_NAMESPACE_ID::FieldDescriptorProto_Label >(_impl_.label_); +} +inline ::PROTOBUF_NAMESPACE_ID::FieldDescriptorProto_Label FieldDescriptorProto::label() const { + // @@protoc_insertion_point(field_get:google.protobuf.FieldDescriptorProto.label) + return _internal_label(); +} +inline void FieldDescriptorProto::_internal_set_label(::PROTOBUF_NAMESPACE_ID::FieldDescriptorProto_Label value) { + assert(::PROTOBUF_NAMESPACE_ID::FieldDescriptorProto_Label_IsValid(value)); + _impl_._has_bits_[0] |= 0x00000200u; + _impl_.label_ = value; +} +inline void FieldDescriptorProto::set_label(::PROTOBUF_NAMESPACE_ID::FieldDescriptorProto_Label value) { + _internal_set_label(value); + // @@protoc_insertion_point(field_set:google.protobuf.FieldDescriptorProto.label) +} + +// optional .google.protobuf.FieldDescriptorProto.Type type = 5; +inline bool FieldDescriptorProto::_internal_has_type() const { + bool value = (_impl_._has_bits_[0] & 0x00000400u) != 0; + return value; +} +inline bool FieldDescriptorProto::has_type() const { + return _internal_has_type(); +} +inline void FieldDescriptorProto::clear_type() { + _impl_.type_ = 1; + _impl_._has_bits_[0] &= ~0x00000400u; +} +inline ::PROTOBUF_NAMESPACE_ID::FieldDescriptorProto_Type FieldDescriptorProto::_internal_type() const { + return static_cast< ::PROTOBUF_NAMESPACE_ID::FieldDescriptorProto_Type >(_impl_.type_); +} +inline ::PROTOBUF_NAMESPACE_ID::FieldDescriptorProto_Type FieldDescriptorProto::type() const { + // @@protoc_insertion_point(field_get:google.protobuf.FieldDescriptorProto.type) + return _internal_type(); +} +inline void FieldDescriptorProto::_internal_set_type(::PROTOBUF_NAMESPACE_ID::FieldDescriptorProto_Type value) { + assert(::PROTOBUF_NAMESPACE_ID::FieldDescriptorProto_Type_IsValid(value)); + _impl_._has_bits_[0] |= 0x00000400u; + _impl_.type_ = value; +} +inline void FieldDescriptorProto::set_type(::PROTOBUF_NAMESPACE_ID::FieldDescriptorProto_Type value) { + _internal_set_type(value); + // @@protoc_insertion_point(field_set:google.protobuf.FieldDescriptorProto.type) +} + +// optional string type_name = 6; +inline bool FieldDescriptorProto::_internal_has_type_name() const { + bool value = (_impl_._has_bits_[0] & 0x00000004u) != 0; + return value; +} +inline bool FieldDescriptorProto::has_type_name() const { + return _internal_has_type_name(); +} +inline void FieldDescriptorProto::clear_type_name() { + _impl_.type_name_.ClearToEmpty(); + _impl_._has_bits_[0] &= ~0x00000004u; +} +inline const std::string& FieldDescriptorProto::type_name() const { + // @@protoc_insertion_point(field_get:google.protobuf.FieldDescriptorProto.type_name) + return _internal_type_name(); +} +template <typename ArgT0, typename... ArgT> +inline PROTOBUF_ALWAYS_INLINE +void FieldDescriptorProto::set_type_name(ArgT0&& arg0, ArgT... args) { + _impl_._has_bits_[0] |= 0x00000004u; + _impl_.type_name_.Set(static_cast<ArgT0 &&>(arg0), args..., GetArenaForAllocation()); + // @@protoc_insertion_point(field_set:google.protobuf.FieldDescriptorProto.type_name) +} +inline std::string* FieldDescriptorProto::mutable_type_name() { + std::string* _s = _internal_mutable_type_name(); + // @@protoc_insertion_point(field_mutable:google.protobuf.FieldDescriptorProto.type_name) + return _s; +} +inline const std::string& FieldDescriptorProto::_internal_type_name() const { + return _impl_.type_name_.Get(); +} +inline void FieldDescriptorProto::_internal_set_type_name(const std::string& value) { + _impl_._has_bits_[0] |= 0x00000004u; + _impl_.type_name_.Set(value, GetArenaForAllocation()); +} +inline std::string* FieldDescriptorProto::_internal_mutable_type_name() { + _impl_._has_bits_[0] |= 0x00000004u; + return _impl_.type_name_.Mutable(GetArenaForAllocation()); +} +inline std::string* FieldDescriptorProto::release_type_name() { + // @@protoc_insertion_point(field_release:google.protobuf.FieldDescriptorProto.type_name) + if (!_internal_has_type_name()) { + return nullptr; + } + _impl_._has_bits_[0] &= ~0x00000004u; + auto* p = _impl_.type_name_.Release(); +#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (_impl_.type_name_.IsDefault()) { + _impl_.type_name_.Set("", GetArenaForAllocation()); + } +#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + return p; +} +inline void FieldDescriptorProto::set_allocated_type_name(std::string* type_name) { + if (type_name != nullptr) { + _impl_._has_bits_[0] |= 0x00000004u; + } else { + _impl_._has_bits_[0] &= ~0x00000004u; + } + _impl_.type_name_.SetAllocated(type_name, GetArenaForAllocation()); +#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (_impl_.type_name_.IsDefault()) { + _impl_.type_name_.Set("", GetArenaForAllocation()); + } +#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + // @@protoc_insertion_point(field_set_allocated:google.protobuf.FieldDescriptorProto.type_name) +} + +// optional string extendee = 2; +inline bool FieldDescriptorProto::_internal_has_extendee() const { + bool value = (_impl_._has_bits_[0] & 0x00000002u) != 0; + return value; +} +inline bool FieldDescriptorProto::has_extendee() const { + return _internal_has_extendee(); +} +inline void FieldDescriptorProto::clear_extendee() { + _impl_.extendee_.ClearToEmpty(); + _impl_._has_bits_[0] &= ~0x00000002u; +} +inline const std::string& FieldDescriptorProto::extendee() const { + // @@protoc_insertion_point(field_get:google.protobuf.FieldDescriptorProto.extendee) + return _internal_extendee(); +} +template <typename ArgT0, typename... ArgT> +inline PROTOBUF_ALWAYS_INLINE +void FieldDescriptorProto::set_extendee(ArgT0&& arg0, ArgT... args) { + _impl_._has_bits_[0] |= 0x00000002u; + _impl_.extendee_.Set(static_cast<ArgT0 &&>(arg0), args..., GetArenaForAllocation()); + // @@protoc_insertion_point(field_set:google.protobuf.FieldDescriptorProto.extendee) +} +inline std::string* FieldDescriptorProto::mutable_extendee() { + std::string* _s = _internal_mutable_extendee(); + // @@protoc_insertion_point(field_mutable:google.protobuf.FieldDescriptorProto.extendee) + return _s; +} +inline const std::string& FieldDescriptorProto::_internal_extendee() const { + return _impl_.extendee_.Get(); +} +inline void FieldDescriptorProto::_internal_set_extendee(const std::string& value) { + _impl_._has_bits_[0] |= 0x00000002u; + _impl_.extendee_.Set(value, GetArenaForAllocation()); +} +inline std::string* FieldDescriptorProto::_internal_mutable_extendee() { + _impl_._has_bits_[0] |= 0x00000002u; + return _impl_.extendee_.Mutable(GetArenaForAllocation()); +} +inline std::string* FieldDescriptorProto::release_extendee() { + // @@protoc_insertion_point(field_release:google.protobuf.FieldDescriptorProto.extendee) + if (!_internal_has_extendee()) { + return nullptr; + } + _impl_._has_bits_[0] &= ~0x00000002u; + auto* p = _impl_.extendee_.Release(); +#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (_impl_.extendee_.IsDefault()) { + _impl_.extendee_.Set("", GetArenaForAllocation()); + } +#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + return p; +} +inline void FieldDescriptorProto::set_allocated_extendee(std::string* extendee) { + if (extendee != nullptr) { + _impl_._has_bits_[0] |= 0x00000002u; + } else { + _impl_._has_bits_[0] &= ~0x00000002u; + } + _impl_.extendee_.SetAllocated(extendee, GetArenaForAllocation()); +#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (_impl_.extendee_.IsDefault()) { + _impl_.extendee_.Set("", GetArenaForAllocation()); + } +#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + // @@protoc_insertion_point(field_set_allocated:google.protobuf.FieldDescriptorProto.extendee) +} + +// optional string default_value = 7; +inline bool FieldDescriptorProto::_internal_has_default_value() const { + bool value = (_impl_._has_bits_[0] & 0x00000008u) != 0; + return value; +} +inline bool FieldDescriptorProto::has_default_value() const { + return _internal_has_default_value(); +} +inline void FieldDescriptorProto::clear_default_value() { + _impl_.default_value_.ClearToEmpty(); + _impl_._has_bits_[0] &= ~0x00000008u; +} +inline const std::string& FieldDescriptorProto::default_value() const { + // @@protoc_insertion_point(field_get:google.protobuf.FieldDescriptorProto.default_value) + return _internal_default_value(); +} +template <typename ArgT0, typename... ArgT> +inline PROTOBUF_ALWAYS_INLINE +void FieldDescriptorProto::set_default_value(ArgT0&& arg0, ArgT... args) { + _impl_._has_bits_[0] |= 0x00000008u; + _impl_.default_value_.Set(static_cast<ArgT0 &&>(arg0), args..., GetArenaForAllocation()); + // @@protoc_insertion_point(field_set:google.protobuf.FieldDescriptorProto.default_value) +} +inline std::string* FieldDescriptorProto::mutable_default_value() { + std::string* _s = _internal_mutable_default_value(); + // @@protoc_insertion_point(field_mutable:google.protobuf.FieldDescriptorProto.default_value) + return _s; +} +inline const std::string& FieldDescriptorProto::_internal_default_value() const { + return _impl_.default_value_.Get(); +} +inline void FieldDescriptorProto::_internal_set_default_value(const std::string& value) { + _impl_._has_bits_[0] |= 0x00000008u; + _impl_.default_value_.Set(value, GetArenaForAllocation()); +} +inline std::string* FieldDescriptorProto::_internal_mutable_default_value() { + _impl_._has_bits_[0] |= 0x00000008u; + return _impl_.default_value_.Mutable(GetArenaForAllocation()); +} +inline std::string* FieldDescriptorProto::release_default_value() { + // @@protoc_insertion_point(field_release:google.protobuf.FieldDescriptorProto.default_value) + if (!_internal_has_default_value()) { + return nullptr; + } + _impl_._has_bits_[0] &= ~0x00000008u; + auto* p = _impl_.default_value_.Release(); +#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (_impl_.default_value_.IsDefault()) { + _impl_.default_value_.Set("", GetArenaForAllocation()); + } +#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + return p; +} +inline void FieldDescriptorProto::set_allocated_default_value(std::string* default_value) { + if (default_value != nullptr) { + _impl_._has_bits_[0] |= 0x00000008u; + } else { + _impl_._has_bits_[0] &= ~0x00000008u; + } + _impl_.default_value_.SetAllocated(default_value, GetArenaForAllocation()); +#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (_impl_.default_value_.IsDefault()) { + _impl_.default_value_.Set("", GetArenaForAllocation()); + } +#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + // @@protoc_insertion_point(field_set_allocated:google.protobuf.FieldDescriptorProto.default_value) +} + +// optional int32 oneof_index = 9; +inline bool FieldDescriptorProto::_internal_has_oneof_index() const { + bool value = (_impl_._has_bits_[0] & 0x00000080u) != 0; + return value; +} +inline bool FieldDescriptorProto::has_oneof_index() const { + return _internal_has_oneof_index(); +} +inline void FieldDescriptorProto::clear_oneof_index() { + _impl_.oneof_index_ = 0; + _impl_._has_bits_[0] &= ~0x00000080u; +} +inline int32_t FieldDescriptorProto::_internal_oneof_index() const { + return _impl_.oneof_index_; +} +inline int32_t FieldDescriptorProto::oneof_index() const { + // @@protoc_insertion_point(field_get:google.protobuf.FieldDescriptorProto.oneof_index) + return _internal_oneof_index(); +} +inline void FieldDescriptorProto::_internal_set_oneof_index(int32_t value) { + _impl_._has_bits_[0] |= 0x00000080u; + _impl_.oneof_index_ = value; +} +inline void FieldDescriptorProto::set_oneof_index(int32_t value) { + _internal_set_oneof_index(value); + // @@protoc_insertion_point(field_set:google.protobuf.FieldDescriptorProto.oneof_index) +} + +// optional string json_name = 10; +inline bool FieldDescriptorProto::_internal_has_json_name() const { + bool value = (_impl_._has_bits_[0] & 0x00000010u) != 0; + return value; +} +inline bool FieldDescriptorProto::has_json_name() const { + return _internal_has_json_name(); +} +inline void FieldDescriptorProto::clear_json_name() { + _impl_.json_name_.ClearToEmpty(); + _impl_._has_bits_[0] &= ~0x00000010u; +} +inline const std::string& FieldDescriptorProto::json_name() const { + // @@protoc_insertion_point(field_get:google.protobuf.FieldDescriptorProto.json_name) + return _internal_json_name(); +} +template <typename ArgT0, typename... ArgT> +inline PROTOBUF_ALWAYS_INLINE +void FieldDescriptorProto::set_json_name(ArgT0&& arg0, ArgT... args) { + _impl_._has_bits_[0] |= 0x00000010u; + _impl_.json_name_.Set(static_cast<ArgT0 &&>(arg0), args..., GetArenaForAllocation()); + // @@protoc_insertion_point(field_set:google.protobuf.FieldDescriptorProto.json_name) +} +inline std::string* FieldDescriptorProto::mutable_json_name() { + std::string* _s = _internal_mutable_json_name(); + // @@protoc_insertion_point(field_mutable:google.protobuf.FieldDescriptorProto.json_name) + return _s; +} +inline const std::string& FieldDescriptorProto::_internal_json_name() const { + return _impl_.json_name_.Get(); +} +inline void FieldDescriptorProto::_internal_set_json_name(const std::string& value) { + _impl_._has_bits_[0] |= 0x00000010u; + _impl_.json_name_.Set(value, GetArenaForAllocation()); +} +inline std::string* FieldDescriptorProto::_internal_mutable_json_name() { + _impl_._has_bits_[0] |= 0x00000010u; + return _impl_.json_name_.Mutable(GetArenaForAllocation()); +} +inline std::string* FieldDescriptorProto::release_json_name() { + // @@protoc_insertion_point(field_release:google.protobuf.FieldDescriptorProto.json_name) + if (!_internal_has_json_name()) { + return nullptr; + } + _impl_._has_bits_[0] &= ~0x00000010u; + auto* p = _impl_.json_name_.Release(); +#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (_impl_.json_name_.IsDefault()) { + _impl_.json_name_.Set("", GetArenaForAllocation()); + } +#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + return p; +} +inline void FieldDescriptorProto::set_allocated_json_name(std::string* json_name) { + if (json_name != nullptr) { + _impl_._has_bits_[0] |= 0x00000010u; + } else { + _impl_._has_bits_[0] &= ~0x00000010u; + } + _impl_.json_name_.SetAllocated(json_name, GetArenaForAllocation()); +#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (_impl_.json_name_.IsDefault()) { + _impl_.json_name_.Set("", GetArenaForAllocation()); + } +#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + // @@protoc_insertion_point(field_set_allocated:google.protobuf.FieldDescriptorProto.json_name) +} + +// optional .google.protobuf.FieldOptions options = 8; +inline bool FieldDescriptorProto::_internal_has_options() const { + bool value = (_impl_._has_bits_[0] & 0x00000020u) != 0; + PROTOBUF_ASSUME(!value || _impl_.options_ != nullptr); + return value; +} +inline bool FieldDescriptorProto::has_options() const { + return _internal_has_options(); +} +inline void FieldDescriptorProto::clear_options() { + if (_impl_.options_ != nullptr) _impl_.options_->Clear(); + _impl_._has_bits_[0] &= ~0x00000020u; +} +inline const ::PROTOBUF_NAMESPACE_ID::FieldOptions& FieldDescriptorProto::_internal_options() const { + const ::PROTOBUF_NAMESPACE_ID::FieldOptions* p = _impl_.options_; + return p != nullptr ? *p : reinterpret_cast<const ::PROTOBUF_NAMESPACE_ID::FieldOptions&>( + ::PROTOBUF_NAMESPACE_ID::_FieldOptions_default_instance_); +} +inline const ::PROTOBUF_NAMESPACE_ID::FieldOptions& FieldDescriptorProto::options() const { + // @@protoc_insertion_point(field_get:google.protobuf.FieldDescriptorProto.options) + return _internal_options(); +} +inline void FieldDescriptorProto::unsafe_arena_set_allocated_options( + ::PROTOBUF_NAMESPACE_ID::FieldOptions* options) { + if (GetArenaForAllocation() == nullptr) { + delete reinterpret_cast<::PROTOBUF_NAMESPACE_ID::MessageLite*>(_impl_.options_); + } + _impl_.options_ = options; + if (options) { + _impl_._has_bits_[0] |= 0x00000020u; + } else { + _impl_._has_bits_[0] &= ~0x00000020u; + } + // @@protoc_insertion_point(field_unsafe_arena_set_allocated:google.protobuf.FieldDescriptorProto.options) +} +inline ::PROTOBUF_NAMESPACE_ID::FieldOptions* FieldDescriptorProto::release_options() { + _impl_._has_bits_[0] &= ~0x00000020u; + ::PROTOBUF_NAMESPACE_ID::FieldOptions* temp = _impl_.options_; + _impl_.options_ = nullptr; +#ifdef PROTOBUF_FORCE_COPY_IN_RELEASE + auto* old = reinterpret_cast<::PROTOBUF_NAMESPACE_ID::MessageLite*>(temp); + temp = ::PROTOBUF_NAMESPACE_ID::internal::DuplicateIfNonNull(temp); + if (GetArenaForAllocation() == nullptr) { delete old; } +#else // PROTOBUF_FORCE_COPY_IN_RELEASE + if (GetArenaForAllocation() != nullptr) { + temp = ::PROTOBUF_NAMESPACE_ID::internal::DuplicateIfNonNull(temp); + } +#endif // !PROTOBUF_FORCE_COPY_IN_RELEASE + return temp; +} +inline ::PROTOBUF_NAMESPACE_ID::FieldOptions* FieldDescriptorProto::unsafe_arena_release_options() { + // @@protoc_insertion_point(field_release:google.protobuf.FieldDescriptorProto.options) + _impl_._has_bits_[0] &= ~0x00000020u; + ::PROTOBUF_NAMESPACE_ID::FieldOptions* temp = _impl_.options_; + _impl_.options_ = nullptr; + return temp; +} +inline ::PROTOBUF_NAMESPACE_ID::FieldOptions* FieldDescriptorProto::_internal_mutable_options() { + _impl_._has_bits_[0] |= 0x00000020u; + if (_impl_.options_ == nullptr) { + auto* p = CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::FieldOptions>(GetArenaForAllocation()); + _impl_.options_ = p; + } + return _impl_.options_; +} +inline ::PROTOBUF_NAMESPACE_ID::FieldOptions* FieldDescriptorProto::mutable_options() { + ::PROTOBUF_NAMESPACE_ID::FieldOptions* _msg = _internal_mutable_options(); + // @@protoc_insertion_point(field_mutable:google.protobuf.FieldDescriptorProto.options) + return _msg; +} +inline void FieldDescriptorProto::set_allocated_options(::PROTOBUF_NAMESPACE_ID::FieldOptions* options) { + ::PROTOBUF_NAMESPACE_ID::Arena* message_arena = GetArenaForAllocation(); + if (message_arena == nullptr) { + delete _impl_.options_; + } + if (options) { + ::PROTOBUF_NAMESPACE_ID::Arena* submessage_arena = + ::PROTOBUF_NAMESPACE_ID::Arena::InternalGetOwningArena(options); + if (message_arena != submessage_arena) { + options = ::PROTOBUF_NAMESPACE_ID::internal::GetOwnedMessage( + message_arena, options, submessage_arena); + } + _impl_._has_bits_[0] |= 0x00000020u; + } else { + _impl_._has_bits_[0] &= ~0x00000020u; + } + _impl_.options_ = options; + // @@protoc_insertion_point(field_set_allocated:google.protobuf.FieldDescriptorProto.options) +} + +// optional bool proto3_optional = 17; +inline bool FieldDescriptorProto::_internal_has_proto3_optional() const { + bool value = (_impl_._has_bits_[0] & 0x00000100u) != 0; + return value; +} +inline bool FieldDescriptorProto::has_proto3_optional() const { + return _internal_has_proto3_optional(); +} +inline void FieldDescriptorProto::clear_proto3_optional() { + _impl_.proto3_optional_ = false; + _impl_._has_bits_[0] &= ~0x00000100u; +} +inline bool FieldDescriptorProto::_internal_proto3_optional() const { + return _impl_.proto3_optional_; +} +inline bool FieldDescriptorProto::proto3_optional() const { + // @@protoc_insertion_point(field_get:google.protobuf.FieldDescriptorProto.proto3_optional) + return _internal_proto3_optional(); +} +inline void FieldDescriptorProto::_internal_set_proto3_optional(bool value) { + _impl_._has_bits_[0] |= 0x00000100u; + _impl_.proto3_optional_ = value; +} +inline void FieldDescriptorProto::set_proto3_optional(bool value) { + _internal_set_proto3_optional(value); + // @@protoc_insertion_point(field_set:google.protobuf.FieldDescriptorProto.proto3_optional) +} + +// ------------------------------------------------------------------- + +// OneofDescriptorProto + +// optional string name = 1; +inline bool OneofDescriptorProto::_internal_has_name() const { + bool value = (_impl_._has_bits_[0] & 0x00000001u) != 0; + return value; +} +inline bool OneofDescriptorProto::has_name() const { + return _internal_has_name(); +} +inline void OneofDescriptorProto::clear_name() { + _impl_.name_.ClearToEmpty(); + _impl_._has_bits_[0] &= ~0x00000001u; +} +inline const std::string& OneofDescriptorProto::name() const { + // @@protoc_insertion_point(field_get:google.protobuf.OneofDescriptorProto.name) + return _internal_name(); +} +template <typename ArgT0, typename... ArgT> +inline PROTOBUF_ALWAYS_INLINE +void OneofDescriptorProto::set_name(ArgT0&& arg0, ArgT... args) { + _impl_._has_bits_[0] |= 0x00000001u; + _impl_.name_.Set(static_cast<ArgT0 &&>(arg0), args..., GetArenaForAllocation()); + // @@protoc_insertion_point(field_set:google.protobuf.OneofDescriptorProto.name) +} +inline std::string* OneofDescriptorProto::mutable_name() { + std::string* _s = _internal_mutable_name(); + // @@protoc_insertion_point(field_mutable:google.protobuf.OneofDescriptorProto.name) + return _s; +} +inline const std::string& OneofDescriptorProto::_internal_name() const { + return _impl_.name_.Get(); +} +inline void OneofDescriptorProto::_internal_set_name(const std::string& value) { + _impl_._has_bits_[0] |= 0x00000001u; + _impl_.name_.Set(value, GetArenaForAllocation()); +} +inline std::string* OneofDescriptorProto::_internal_mutable_name() { + _impl_._has_bits_[0] |= 0x00000001u; + return _impl_.name_.Mutable(GetArenaForAllocation()); +} +inline std::string* OneofDescriptorProto::release_name() { + // @@protoc_insertion_point(field_release:google.protobuf.OneofDescriptorProto.name) + if (!_internal_has_name()) { + return nullptr; + } + _impl_._has_bits_[0] &= ~0x00000001u; + auto* p = _impl_.name_.Release(); +#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (_impl_.name_.IsDefault()) { + _impl_.name_.Set("", GetArenaForAllocation()); + } +#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + return p; +} +inline void OneofDescriptorProto::set_allocated_name(std::string* name) { + if (name != nullptr) { + _impl_._has_bits_[0] |= 0x00000001u; + } else { + _impl_._has_bits_[0] &= ~0x00000001u; + } + _impl_.name_.SetAllocated(name, GetArenaForAllocation()); +#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (_impl_.name_.IsDefault()) { + _impl_.name_.Set("", GetArenaForAllocation()); + } +#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + // @@protoc_insertion_point(field_set_allocated:google.protobuf.OneofDescriptorProto.name) +} + +// optional .google.protobuf.OneofOptions options = 2; +inline bool OneofDescriptorProto::_internal_has_options() const { + bool value = (_impl_._has_bits_[0] & 0x00000002u) != 0; + PROTOBUF_ASSUME(!value || _impl_.options_ != nullptr); + return value; +} +inline bool OneofDescriptorProto::has_options() const { + return _internal_has_options(); +} +inline void OneofDescriptorProto::clear_options() { + if (_impl_.options_ != nullptr) _impl_.options_->Clear(); + _impl_._has_bits_[0] &= ~0x00000002u; +} +inline const ::PROTOBUF_NAMESPACE_ID::OneofOptions& OneofDescriptorProto::_internal_options() const { + const ::PROTOBUF_NAMESPACE_ID::OneofOptions* p = _impl_.options_; + return p != nullptr ? *p : reinterpret_cast<const ::PROTOBUF_NAMESPACE_ID::OneofOptions&>( + ::PROTOBUF_NAMESPACE_ID::_OneofOptions_default_instance_); +} +inline const ::PROTOBUF_NAMESPACE_ID::OneofOptions& OneofDescriptorProto::options() const { + // @@protoc_insertion_point(field_get:google.protobuf.OneofDescriptorProto.options) + return _internal_options(); +} +inline void OneofDescriptorProto::unsafe_arena_set_allocated_options( + ::PROTOBUF_NAMESPACE_ID::OneofOptions* options) { + if (GetArenaForAllocation() == nullptr) { + delete reinterpret_cast<::PROTOBUF_NAMESPACE_ID::MessageLite*>(_impl_.options_); + } + _impl_.options_ = options; + if (options) { + _impl_._has_bits_[0] |= 0x00000002u; + } else { + _impl_._has_bits_[0] &= ~0x00000002u; + } + // @@protoc_insertion_point(field_unsafe_arena_set_allocated:google.protobuf.OneofDescriptorProto.options) +} +inline ::PROTOBUF_NAMESPACE_ID::OneofOptions* OneofDescriptorProto::release_options() { + _impl_._has_bits_[0] &= ~0x00000002u; + ::PROTOBUF_NAMESPACE_ID::OneofOptions* temp = _impl_.options_; + _impl_.options_ = nullptr; +#ifdef PROTOBUF_FORCE_COPY_IN_RELEASE + auto* old = reinterpret_cast<::PROTOBUF_NAMESPACE_ID::MessageLite*>(temp); + temp = ::PROTOBUF_NAMESPACE_ID::internal::DuplicateIfNonNull(temp); + if (GetArenaForAllocation() == nullptr) { delete old; } +#else // PROTOBUF_FORCE_COPY_IN_RELEASE + if (GetArenaForAllocation() != nullptr) { + temp = ::PROTOBUF_NAMESPACE_ID::internal::DuplicateIfNonNull(temp); + } +#endif // !PROTOBUF_FORCE_COPY_IN_RELEASE + return temp; +} +inline ::PROTOBUF_NAMESPACE_ID::OneofOptions* OneofDescriptorProto::unsafe_arena_release_options() { + // @@protoc_insertion_point(field_release:google.protobuf.OneofDescriptorProto.options) + _impl_._has_bits_[0] &= ~0x00000002u; + ::PROTOBUF_NAMESPACE_ID::OneofOptions* temp = _impl_.options_; + _impl_.options_ = nullptr; + return temp; +} +inline ::PROTOBUF_NAMESPACE_ID::OneofOptions* OneofDescriptorProto::_internal_mutable_options() { + _impl_._has_bits_[0] |= 0x00000002u; + if (_impl_.options_ == nullptr) { + auto* p = CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::OneofOptions>(GetArenaForAllocation()); + _impl_.options_ = p; + } + return _impl_.options_; +} +inline ::PROTOBUF_NAMESPACE_ID::OneofOptions* OneofDescriptorProto::mutable_options() { + ::PROTOBUF_NAMESPACE_ID::OneofOptions* _msg = _internal_mutable_options(); + // @@protoc_insertion_point(field_mutable:google.protobuf.OneofDescriptorProto.options) + return _msg; +} +inline void OneofDescriptorProto::set_allocated_options(::PROTOBUF_NAMESPACE_ID::OneofOptions* options) { + ::PROTOBUF_NAMESPACE_ID::Arena* message_arena = GetArenaForAllocation(); + if (message_arena == nullptr) { + delete _impl_.options_; + } + if (options) { + ::PROTOBUF_NAMESPACE_ID::Arena* submessage_arena = + ::PROTOBUF_NAMESPACE_ID::Arena::InternalGetOwningArena(options); + if (message_arena != submessage_arena) { + options = ::PROTOBUF_NAMESPACE_ID::internal::GetOwnedMessage( + message_arena, options, submessage_arena); + } + _impl_._has_bits_[0] |= 0x00000002u; + } else { + _impl_._has_bits_[0] &= ~0x00000002u; + } + _impl_.options_ = options; + // @@protoc_insertion_point(field_set_allocated:google.protobuf.OneofDescriptorProto.options) +} + +// ------------------------------------------------------------------- + +// EnumDescriptorProto_EnumReservedRange + +// optional int32 start = 1; +inline bool EnumDescriptorProto_EnumReservedRange::_internal_has_start() const { + bool value = (_impl_._has_bits_[0] & 0x00000001u) != 0; + return value; +} +inline bool EnumDescriptorProto_EnumReservedRange::has_start() const { + return _internal_has_start(); +} +inline void EnumDescriptorProto_EnumReservedRange::clear_start() { + _impl_.start_ = 0; + _impl_._has_bits_[0] &= ~0x00000001u; +} +inline int32_t EnumDescriptorProto_EnumReservedRange::_internal_start() const { + return _impl_.start_; +} +inline int32_t EnumDescriptorProto_EnumReservedRange::start() const { + // @@protoc_insertion_point(field_get:google.protobuf.EnumDescriptorProto.EnumReservedRange.start) + return _internal_start(); +} +inline void EnumDescriptorProto_EnumReservedRange::_internal_set_start(int32_t value) { + _impl_._has_bits_[0] |= 0x00000001u; + _impl_.start_ = value; +} +inline void EnumDescriptorProto_EnumReservedRange::set_start(int32_t value) { + _internal_set_start(value); + // @@protoc_insertion_point(field_set:google.protobuf.EnumDescriptorProto.EnumReservedRange.start) +} + +// optional int32 end = 2; +inline bool EnumDescriptorProto_EnumReservedRange::_internal_has_end() const { + bool value = (_impl_._has_bits_[0] & 0x00000002u) != 0; + return value; +} +inline bool EnumDescriptorProto_EnumReservedRange::has_end() const { + return _internal_has_end(); +} +inline void EnumDescriptorProto_EnumReservedRange::clear_end() { + _impl_.end_ = 0; + _impl_._has_bits_[0] &= ~0x00000002u; +} +inline int32_t EnumDescriptorProto_EnumReservedRange::_internal_end() const { + return _impl_.end_; +} +inline int32_t EnumDescriptorProto_EnumReservedRange::end() const { + // @@protoc_insertion_point(field_get:google.protobuf.EnumDescriptorProto.EnumReservedRange.end) + return _internal_end(); +} +inline void EnumDescriptorProto_EnumReservedRange::_internal_set_end(int32_t value) { + _impl_._has_bits_[0] |= 0x00000002u; + _impl_.end_ = value; +} +inline void EnumDescriptorProto_EnumReservedRange::set_end(int32_t value) { + _internal_set_end(value); + // @@protoc_insertion_point(field_set:google.protobuf.EnumDescriptorProto.EnumReservedRange.end) +} + +// ------------------------------------------------------------------- + +// EnumDescriptorProto + +// optional string name = 1; +inline bool EnumDescriptorProto::_internal_has_name() const { + bool value = (_impl_._has_bits_[0] & 0x00000001u) != 0; + return value; +} +inline bool EnumDescriptorProto::has_name() const { + return _internal_has_name(); +} +inline void EnumDescriptorProto::clear_name() { + _impl_.name_.ClearToEmpty(); + _impl_._has_bits_[0] &= ~0x00000001u; +} +inline const std::string& EnumDescriptorProto::name() const { + // @@protoc_insertion_point(field_get:google.protobuf.EnumDescriptorProto.name) + return _internal_name(); +} +template <typename ArgT0, typename... ArgT> +inline PROTOBUF_ALWAYS_INLINE +void EnumDescriptorProto::set_name(ArgT0&& arg0, ArgT... args) { + _impl_._has_bits_[0] |= 0x00000001u; + _impl_.name_.Set(static_cast<ArgT0 &&>(arg0), args..., GetArenaForAllocation()); + // @@protoc_insertion_point(field_set:google.protobuf.EnumDescriptorProto.name) +} +inline std::string* EnumDescriptorProto::mutable_name() { + std::string* _s = _internal_mutable_name(); + // @@protoc_insertion_point(field_mutable:google.protobuf.EnumDescriptorProto.name) + return _s; +} +inline const std::string& EnumDescriptorProto::_internal_name() const { + return _impl_.name_.Get(); +} +inline void EnumDescriptorProto::_internal_set_name(const std::string& value) { + _impl_._has_bits_[0] |= 0x00000001u; + _impl_.name_.Set(value, GetArenaForAllocation()); +} +inline std::string* EnumDescriptorProto::_internal_mutable_name() { + _impl_._has_bits_[0] |= 0x00000001u; + return _impl_.name_.Mutable(GetArenaForAllocation()); +} +inline std::string* EnumDescriptorProto::release_name() { + // @@protoc_insertion_point(field_release:google.protobuf.EnumDescriptorProto.name) + if (!_internal_has_name()) { + return nullptr; + } + _impl_._has_bits_[0] &= ~0x00000001u; + auto* p = _impl_.name_.Release(); +#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (_impl_.name_.IsDefault()) { + _impl_.name_.Set("", GetArenaForAllocation()); + } +#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + return p; +} +inline void EnumDescriptorProto::set_allocated_name(std::string* name) { + if (name != nullptr) { + _impl_._has_bits_[0] |= 0x00000001u; + } else { + _impl_._has_bits_[0] &= ~0x00000001u; + } + _impl_.name_.SetAllocated(name, GetArenaForAllocation()); +#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (_impl_.name_.IsDefault()) { + _impl_.name_.Set("", GetArenaForAllocation()); + } +#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + // @@protoc_insertion_point(field_set_allocated:google.protobuf.EnumDescriptorProto.name) +} + +// repeated .google.protobuf.EnumValueDescriptorProto value = 2; +inline int EnumDescriptorProto::_internal_value_size() const { + return _impl_.value_.size(); +} +inline int EnumDescriptorProto::value_size() const { + return _internal_value_size(); +} +inline void EnumDescriptorProto::clear_value() { + _impl_.value_.Clear(); +} +inline ::PROTOBUF_NAMESPACE_ID::EnumValueDescriptorProto* EnumDescriptorProto::mutable_value(int index) { + // @@protoc_insertion_point(field_mutable:google.protobuf.EnumDescriptorProto.value) + return _impl_.value_.Mutable(index); +} +inline ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::EnumValueDescriptorProto >* +EnumDescriptorProto::mutable_value() { + // @@protoc_insertion_point(field_mutable_list:google.protobuf.EnumDescriptorProto.value) + return &_impl_.value_; +} +inline const ::PROTOBUF_NAMESPACE_ID::EnumValueDescriptorProto& EnumDescriptorProto::_internal_value(int index) const { + return _impl_.value_.Get(index); +} +inline const ::PROTOBUF_NAMESPACE_ID::EnumValueDescriptorProto& EnumDescriptorProto::value(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.EnumDescriptorProto.value) + return _internal_value(index); +} +inline ::PROTOBUF_NAMESPACE_ID::EnumValueDescriptorProto* EnumDescriptorProto::_internal_add_value() { + return _impl_.value_.Add(); +} +inline ::PROTOBUF_NAMESPACE_ID::EnumValueDescriptorProto* EnumDescriptorProto::add_value() { + ::PROTOBUF_NAMESPACE_ID::EnumValueDescriptorProto* _add = _internal_add_value(); + // @@protoc_insertion_point(field_add:google.protobuf.EnumDescriptorProto.value) + return _add; +} +inline const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::EnumValueDescriptorProto >& +EnumDescriptorProto::value() const { + // @@protoc_insertion_point(field_list:google.protobuf.EnumDescriptorProto.value) + return _impl_.value_; +} + +// optional .google.protobuf.EnumOptions options = 3; +inline bool EnumDescriptorProto::_internal_has_options() const { + bool value = (_impl_._has_bits_[0] & 0x00000002u) != 0; + PROTOBUF_ASSUME(!value || _impl_.options_ != nullptr); + return value; +} +inline bool EnumDescriptorProto::has_options() const { + return _internal_has_options(); +} +inline void EnumDescriptorProto::clear_options() { + if (_impl_.options_ != nullptr) _impl_.options_->Clear(); + _impl_._has_bits_[0] &= ~0x00000002u; +} +inline const ::PROTOBUF_NAMESPACE_ID::EnumOptions& EnumDescriptorProto::_internal_options() const { + const ::PROTOBUF_NAMESPACE_ID::EnumOptions* p = _impl_.options_; + return p != nullptr ? *p : reinterpret_cast<const ::PROTOBUF_NAMESPACE_ID::EnumOptions&>( + ::PROTOBUF_NAMESPACE_ID::_EnumOptions_default_instance_); +} +inline const ::PROTOBUF_NAMESPACE_ID::EnumOptions& EnumDescriptorProto::options() const { + // @@protoc_insertion_point(field_get:google.protobuf.EnumDescriptorProto.options) + return _internal_options(); +} +inline void EnumDescriptorProto::unsafe_arena_set_allocated_options( + ::PROTOBUF_NAMESPACE_ID::EnumOptions* options) { + if (GetArenaForAllocation() == nullptr) { + delete reinterpret_cast<::PROTOBUF_NAMESPACE_ID::MessageLite*>(_impl_.options_); + } + _impl_.options_ = options; + if (options) { + _impl_._has_bits_[0] |= 0x00000002u; + } else { + _impl_._has_bits_[0] &= ~0x00000002u; + } + // @@protoc_insertion_point(field_unsafe_arena_set_allocated:google.protobuf.EnumDescriptorProto.options) +} +inline ::PROTOBUF_NAMESPACE_ID::EnumOptions* EnumDescriptorProto::release_options() { + _impl_._has_bits_[0] &= ~0x00000002u; + ::PROTOBUF_NAMESPACE_ID::EnumOptions* temp = _impl_.options_; + _impl_.options_ = nullptr; +#ifdef PROTOBUF_FORCE_COPY_IN_RELEASE + auto* old = reinterpret_cast<::PROTOBUF_NAMESPACE_ID::MessageLite*>(temp); + temp = ::PROTOBUF_NAMESPACE_ID::internal::DuplicateIfNonNull(temp); + if (GetArenaForAllocation() == nullptr) { delete old; } +#else // PROTOBUF_FORCE_COPY_IN_RELEASE + if (GetArenaForAllocation() != nullptr) { + temp = ::PROTOBUF_NAMESPACE_ID::internal::DuplicateIfNonNull(temp); + } +#endif // !PROTOBUF_FORCE_COPY_IN_RELEASE + return temp; +} +inline ::PROTOBUF_NAMESPACE_ID::EnumOptions* EnumDescriptorProto::unsafe_arena_release_options() { + // @@protoc_insertion_point(field_release:google.protobuf.EnumDescriptorProto.options) + _impl_._has_bits_[0] &= ~0x00000002u; + ::PROTOBUF_NAMESPACE_ID::EnumOptions* temp = _impl_.options_; + _impl_.options_ = nullptr; + return temp; +} +inline ::PROTOBUF_NAMESPACE_ID::EnumOptions* EnumDescriptorProto::_internal_mutable_options() { + _impl_._has_bits_[0] |= 0x00000002u; + if (_impl_.options_ == nullptr) { + auto* p = CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::EnumOptions>(GetArenaForAllocation()); + _impl_.options_ = p; + } + return _impl_.options_; +} +inline ::PROTOBUF_NAMESPACE_ID::EnumOptions* EnumDescriptorProto::mutable_options() { + ::PROTOBUF_NAMESPACE_ID::EnumOptions* _msg = _internal_mutable_options(); + // @@protoc_insertion_point(field_mutable:google.protobuf.EnumDescriptorProto.options) + return _msg; +} +inline void EnumDescriptorProto::set_allocated_options(::PROTOBUF_NAMESPACE_ID::EnumOptions* options) { + ::PROTOBUF_NAMESPACE_ID::Arena* message_arena = GetArenaForAllocation(); + if (message_arena == nullptr) { + delete _impl_.options_; + } + if (options) { + ::PROTOBUF_NAMESPACE_ID::Arena* submessage_arena = + ::PROTOBUF_NAMESPACE_ID::Arena::InternalGetOwningArena(options); + if (message_arena != submessage_arena) { + options = ::PROTOBUF_NAMESPACE_ID::internal::GetOwnedMessage( + message_arena, options, submessage_arena); + } + _impl_._has_bits_[0] |= 0x00000002u; + } else { + _impl_._has_bits_[0] &= ~0x00000002u; + } + _impl_.options_ = options; + // @@protoc_insertion_point(field_set_allocated:google.protobuf.EnumDescriptorProto.options) +} + +// repeated .google.protobuf.EnumDescriptorProto.EnumReservedRange reserved_range = 4; +inline int EnumDescriptorProto::_internal_reserved_range_size() const { + return _impl_.reserved_range_.size(); +} +inline int EnumDescriptorProto::reserved_range_size() const { + return _internal_reserved_range_size(); +} +inline void EnumDescriptorProto::clear_reserved_range() { + _impl_.reserved_range_.Clear(); +} +inline ::PROTOBUF_NAMESPACE_ID::EnumDescriptorProto_EnumReservedRange* EnumDescriptorProto::mutable_reserved_range(int index) { + // @@protoc_insertion_point(field_mutable:google.protobuf.EnumDescriptorProto.reserved_range) + return _impl_.reserved_range_.Mutable(index); +} +inline ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::EnumDescriptorProto_EnumReservedRange >* +EnumDescriptorProto::mutable_reserved_range() { + // @@protoc_insertion_point(field_mutable_list:google.protobuf.EnumDescriptorProto.reserved_range) + return &_impl_.reserved_range_; +} +inline const ::PROTOBUF_NAMESPACE_ID::EnumDescriptorProto_EnumReservedRange& EnumDescriptorProto::_internal_reserved_range(int index) const { + return _impl_.reserved_range_.Get(index); +} +inline const ::PROTOBUF_NAMESPACE_ID::EnumDescriptorProto_EnumReservedRange& EnumDescriptorProto::reserved_range(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.EnumDescriptorProto.reserved_range) + return _internal_reserved_range(index); +} +inline ::PROTOBUF_NAMESPACE_ID::EnumDescriptorProto_EnumReservedRange* EnumDescriptorProto::_internal_add_reserved_range() { + return _impl_.reserved_range_.Add(); +} +inline ::PROTOBUF_NAMESPACE_ID::EnumDescriptorProto_EnumReservedRange* EnumDescriptorProto::add_reserved_range() { + ::PROTOBUF_NAMESPACE_ID::EnumDescriptorProto_EnumReservedRange* _add = _internal_add_reserved_range(); + // @@protoc_insertion_point(field_add:google.protobuf.EnumDescriptorProto.reserved_range) + return _add; +} +inline const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::EnumDescriptorProto_EnumReservedRange >& +EnumDescriptorProto::reserved_range() const { + // @@protoc_insertion_point(field_list:google.protobuf.EnumDescriptorProto.reserved_range) + return _impl_.reserved_range_; +} + +// repeated string reserved_name = 5; +inline int EnumDescriptorProto::_internal_reserved_name_size() const { + return _impl_.reserved_name_.size(); +} +inline int EnumDescriptorProto::reserved_name_size() const { + return _internal_reserved_name_size(); +} +inline void EnumDescriptorProto::clear_reserved_name() { + _impl_.reserved_name_.Clear(); +} +inline std::string* EnumDescriptorProto::add_reserved_name() { + std::string* _s = _internal_add_reserved_name(); + // @@protoc_insertion_point(field_add_mutable:google.protobuf.EnumDescriptorProto.reserved_name) + return _s; +} +inline const std::string& EnumDescriptorProto::_internal_reserved_name(int index) const { + return _impl_.reserved_name_.Get(index); +} +inline const std::string& EnumDescriptorProto::reserved_name(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.EnumDescriptorProto.reserved_name) + return _internal_reserved_name(index); +} +inline std::string* EnumDescriptorProto::mutable_reserved_name(int index) { + // @@protoc_insertion_point(field_mutable:google.protobuf.EnumDescriptorProto.reserved_name) + return _impl_.reserved_name_.Mutable(index); +} +inline void EnumDescriptorProto::set_reserved_name(int index, const std::string& value) { + _impl_.reserved_name_.Mutable(index)->assign(value); + // @@protoc_insertion_point(field_set:google.protobuf.EnumDescriptorProto.reserved_name) +} +inline void EnumDescriptorProto::set_reserved_name(int index, std::string&& value) { + _impl_.reserved_name_.Mutable(index)->assign(std::move(value)); + // @@protoc_insertion_point(field_set:google.protobuf.EnumDescriptorProto.reserved_name) +} +inline void EnumDescriptorProto::set_reserved_name(int index, const char* value) { + GOOGLE_DCHECK(value != nullptr); + _impl_.reserved_name_.Mutable(index)->assign(value); + // @@protoc_insertion_point(field_set_char:google.protobuf.EnumDescriptorProto.reserved_name) +} +inline void EnumDescriptorProto::set_reserved_name(int index, const char* value, size_t size) { + _impl_.reserved_name_.Mutable(index)->assign( + reinterpret_cast<const char*>(value), size); + // @@protoc_insertion_point(field_set_pointer:google.protobuf.EnumDescriptorProto.reserved_name) +} +inline std::string* EnumDescriptorProto::_internal_add_reserved_name() { + return _impl_.reserved_name_.Add(); +} +inline void EnumDescriptorProto::add_reserved_name(const std::string& value) { + _impl_.reserved_name_.Add()->assign(value); + // @@protoc_insertion_point(field_add:google.protobuf.EnumDescriptorProto.reserved_name) +} +inline void EnumDescriptorProto::add_reserved_name(std::string&& value) { + _impl_.reserved_name_.Add(std::move(value)); + // @@protoc_insertion_point(field_add:google.protobuf.EnumDescriptorProto.reserved_name) +} +inline void EnumDescriptorProto::add_reserved_name(const char* value) { + GOOGLE_DCHECK(value != nullptr); + _impl_.reserved_name_.Add()->assign(value); + // @@protoc_insertion_point(field_add_char:google.protobuf.EnumDescriptorProto.reserved_name) +} +inline void EnumDescriptorProto::add_reserved_name(const char* value, size_t size) { + _impl_.reserved_name_.Add()->assign(reinterpret_cast<const char*>(value), size); + // @@protoc_insertion_point(field_add_pointer:google.protobuf.EnumDescriptorProto.reserved_name) +} +inline const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField<std::string>& +EnumDescriptorProto::reserved_name() const { + // @@protoc_insertion_point(field_list:google.protobuf.EnumDescriptorProto.reserved_name) + return _impl_.reserved_name_; +} +inline ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField<std::string>* +EnumDescriptorProto::mutable_reserved_name() { + // @@protoc_insertion_point(field_mutable_list:google.protobuf.EnumDescriptorProto.reserved_name) + return &_impl_.reserved_name_; +} + +// ------------------------------------------------------------------- + +// EnumValueDescriptorProto + +// optional string name = 1; +inline bool EnumValueDescriptorProto::_internal_has_name() const { + bool value = (_impl_._has_bits_[0] & 0x00000001u) != 0; + return value; +} +inline bool EnumValueDescriptorProto::has_name() const { + return _internal_has_name(); +} +inline void EnumValueDescriptorProto::clear_name() { + _impl_.name_.ClearToEmpty(); + _impl_._has_bits_[0] &= ~0x00000001u; +} +inline const std::string& EnumValueDescriptorProto::name() const { + // @@protoc_insertion_point(field_get:google.protobuf.EnumValueDescriptorProto.name) + return _internal_name(); +} +template <typename ArgT0, typename... ArgT> +inline PROTOBUF_ALWAYS_INLINE +void EnumValueDescriptorProto::set_name(ArgT0&& arg0, ArgT... args) { + _impl_._has_bits_[0] |= 0x00000001u; + _impl_.name_.Set(static_cast<ArgT0 &&>(arg0), args..., GetArenaForAllocation()); + // @@protoc_insertion_point(field_set:google.protobuf.EnumValueDescriptorProto.name) +} +inline std::string* EnumValueDescriptorProto::mutable_name() { + std::string* _s = _internal_mutable_name(); + // @@protoc_insertion_point(field_mutable:google.protobuf.EnumValueDescriptorProto.name) + return _s; +} +inline const std::string& EnumValueDescriptorProto::_internal_name() const { + return _impl_.name_.Get(); +} +inline void EnumValueDescriptorProto::_internal_set_name(const std::string& value) { + _impl_._has_bits_[0] |= 0x00000001u; + _impl_.name_.Set(value, GetArenaForAllocation()); +} +inline std::string* EnumValueDescriptorProto::_internal_mutable_name() { + _impl_._has_bits_[0] |= 0x00000001u; + return _impl_.name_.Mutable(GetArenaForAllocation()); +} +inline std::string* EnumValueDescriptorProto::release_name() { + // @@protoc_insertion_point(field_release:google.protobuf.EnumValueDescriptorProto.name) + if (!_internal_has_name()) { + return nullptr; + } + _impl_._has_bits_[0] &= ~0x00000001u; + auto* p = _impl_.name_.Release(); +#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (_impl_.name_.IsDefault()) { + _impl_.name_.Set("", GetArenaForAllocation()); + } +#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + return p; +} +inline void EnumValueDescriptorProto::set_allocated_name(std::string* name) { + if (name != nullptr) { + _impl_._has_bits_[0] |= 0x00000001u; + } else { + _impl_._has_bits_[0] &= ~0x00000001u; + } + _impl_.name_.SetAllocated(name, GetArenaForAllocation()); +#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (_impl_.name_.IsDefault()) { + _impl_.name_.Set("", GetArenaForAllocation()); + } +#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + // @@protoc_insertion_point(field_set_allocated:google.protobuf.EnumValueDescriptorProto.name) +} + +// optional int32 number = 2; +inline bool EnumValueDescriptorProto::_internal_has_number() const { + bool value = (_impl_._has_bits_[0] & 0x00000004u) != 0; + return value; +} +inline bool EnumValueDescriptorProto::has_number() const { + return _internal_has_number(); +} +inline void EnumValueDescriptorProto::clear_number() { + _impl_.number_ = 0; + _impl_._has_bits_[0] &= ~0x00000004u; +} +inline int32_t EnumValueDescriptorProto::_internal_number() const { + return _impl_.number_; +} +inline int32_t EnumValueDescriptorProto::number() const { + // @@protoc_insertion_point(field_get:google.protobuf.EnumValueDescriptorProto.number) + return _internal_number(); +} +inline void EnumValueDescriptorProto::_internal_set_number(int32_t value) { + _impl_._has_bits_[0] |= 0x00000004u; + _impl_.number_ = value; +} +inline void EnumValueDescriptorProto::set_number(int32_t value) { + _internal_set_number(value); + // @@protoc_insertion_point(field_set:google.protobuf.EnumValueDescriptorProto.number) +} + +// optional .google.protobuf.EnumValueOptions options = 3; +inline bool EnumValueDescriptorProto::_internal_has_options() const { + bool value = (_impl_._has_bits_[0] & 0x00000002u) != 0; + PROTOBUF_ASSUME(!value || _impl_.options_ != nullptr); + return value; +} +inline bool EnumValueDescriptorProto::has_options() const { + return _internal_has_options(); +} +inline void EnumValueDescriptorProto::clear_options() { + if (_impl_.options_ != nullptr) _impl_.options_->Clear(); + _impl_._has_bits_[0] &= ~0x00000002u; +} +inline const ::PROTOBUF_NAMESPACE_ID::EnumValueOptions& EnumValueDescriptorProto::_internal_options() const { + const ::PROTOBUF_NAMESPACE_ID::EnumValueOptions* p = _impl_.options_; + return p != nullptr ? *p : reinterpret_cast<const ::PROTOBUF_NAMESPACE_ID::EnumValueOptions&>( + ::PROTOBUF_NAMESPACE_ID::_EnumValueOptions_default_instance_); +} +inline const ::PROTOBUF_NAMESPACE_ID::EnumValueOptions& EnumValueDescriptorProto::options() const { + // @@protoc_insertion_point(field_get:google.protobuf.EnumValueDescriptorProto.options) + return _internal_options(); +} +inline void EnumValueDescriptorProto::unsafe_arena_set_allocated_options( + ::PROTOBUF_NAMESPACE_ID::EnumValueOptions* options) { + if (GetArenaForAllocation() == nullptr) { + delete reinterpret_cast<::PROTOBUF_NAMESPACE_ID::MessageLite*>(_impl_.options_); + } + _impl_.options_ = options; + if (options) { + _impl_._has_bits_[0] |= 0x00000002u; + } else { + _impl_._has_bits_[0] &= ~0x00000002u; + } + // @@protoc_insertion_point(field_unsafe_arena_set_allocated:google.protobuf.EnumValueDescriptorProto.options) +} +inline ::PROTOBUF_NAMESPACE_ID::EnumValueOptions* EnumValueDescriptorProto::release_options() { + _impl_._has_bits_[0] &= ~0x00000002u; + ::PROTOBUF_NAMESPACE_ID::EnumValueOptions* temp = _impl_.options_; + _impl_.options_ = nullptr; +#ifdef PROTOBUF_FORCE_COPY_IN_RELEASE + auto* old = reinterpret_cast<::PROTOBUF_NAMESPACE_ID::MessageLite*>(temp); + temp = ::PROTOBUF_NAMESPACE_ID::internal::DuplicateIfNonNull(temp); + if (GetArenaForAllocation() == nullptr) { delete old; } +#else // PROTOBUF_FORCE_COPY_IN_RELEASE + if (GetArenaForAllocation() != nullptr) { + temp = ::PROTOBUF_NAMESPACE_ID::internal::DuplicateIfNonNull(temp); + } +#endif // !PROTOBUF_FORCE_COPY_IN_RELEASE + return temp; +} +inline ::PROTOBUF_NAMESPACE_ID::EnumValueOptions* EnumValueDescriptorProto::unsafe_arena_release_options() { + // @@protoc_insertion_point(field_release:google.protobuf.EnumValueDescriptorProto.options) + _impl_._has_bits_[0] &= ~0x00000002u; + ::PROTOBUF_NAMESPACE_ID::EnumValueOptions* temp = _impl_.options_; + _impl_.options_ = nullptr; + return temp; +} +inline ::PROTOBUF_NAMESPACE_ID::EnumValueOptions* EnumValueDescriptorProto::_internal_mutable_options() { + _impl_._has_bits_[0] |= 0x00000002u; + if (_impl_.options_ == nullptr) { + auto* p = CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::EnumValueOptions>(GetArenaForAllocation()); + _impl_.options_ = p; + } + return _impl_.options_; +} +inline ::PROTOBUF_NAMESPACE_ID::EnumValueOptions* EnumValueDescriptorProto::mutable_options() { + ::PROTOBUF_NAMESPACE_ID::EnumValueOptions* _msg = _internal_mutable_options(); + // @@protoc_insertion_point(field_mutable:google.protobuf.EnumValueDescriptorProto.options) + return _msg; +} +inline void EnumValueDescriptorProto::set_allocated_options(::PROTOBUF_NAMESPACE_ID::EnumValueOptions* options) { + ::PROTOBUF_NAMESPACE_ID::Arena* message_arena = GetArenaForAllocation(); + if (message_arena == nullptr) { + delete _impl_.options_; + } + if (options) { + ::PROTOBUF_NAMESPACE_ID::Arena* submessage_arena = + ::PROTOBUF_NAMESPACE_ID::Arena::InternalGetOwningArena(options); + if (message_arena != submessage_arena) { + options = ::PROTOBUF_NAMESPACE_ID::internal::GetOwnedMessage( + message_arena, options, submessage_arena); + } + _impl_._has_bits_[0] |= 0x00000002u; + } else { + _impl_._has_bits_[0] &= ~0x00000002u; + } + _impl_.options_ = options; + // @@protoc_insertion_point(field_set_allocated:google.protobuf.EnumValueDescriptorProto.options) +} + +// ------------------------------------------------------------------- + +// ServiceDescriptorProto + +// optional string name = 1; +inline bool ServiceDescriptorProto::_internal_has_name() const { + bool value = (_impl_._has_bits_[0] & 0x00000001u) != 0; + return value; +} +inline bool ServiceDescriptorProto::has_name() const { + return _internal_has_name(); +} +inline void ServiceDescriptorProto::clear_name() { + _impl_.name_.ClearToEmpty(); + _impl_._has_bits_[0] &= ~0x00000001u; +} +inline const std::string& ServiceDescriptorProto::name() const { + // @@protoc_insertion_point(field_get:google.protobuf.ServiceDescriptorProto.name) + return _internal_name(); +} +template <typename ArgT0, typename... ArgT> +inline PROTOBUF_ALWAYS_INLINE +void ServiceDescriptorProto::set_name(ArgT0&& arg0, ArgT... args) { + _impl_._has_bits_[0] |= 0x00000001u; + _impl_.name_.Set(static_cast<ArgT0 &&>(arg0), args..., GetArenaForAllocation()); + // @@protoc_insertion_point(field_set:google.protobuf.ServiceDescriptorProto.name) +} +inline std::string* ServiceDescriptorProto::mutable_name() { + std::string* _s = _internal_mutable_name(); + // @@protoc_insertion_point(field_mutable:google.protobuf.ServiceDescriptorProto.name) + return _s; +} +inline const std::string& ServiceDescriptorProto::_internal_name() const { + return _impl_.name_.Get(); +} +inline void ServiceDescriptorProto::_internal_set_name(const std::string& value) { + _impl_._has_bits_[0] |= 0x00000001u; + _impl_.name_.Set(value, GetArenaForAllocation()); +} +inline std::string* ServiceDescriptorProto::_internal_mutable_name() { + _impl_._has_bits_[0] |= 0x00000001u; + return _impl_.name_.Mutable(GetArenaForAllocation()); +} +inline std::string* ServiceDescriptorProto::release_name() { + // @@protoc_insertion_point(field_release:google.protobuf.ServiceDescriptorProto.name) + if (!_internal_has_name()) { + return nullptr; + } + _impl_._has_bits_[0] &= ~0x00000001u; + auto* p = _impl_.name_.Release(); +#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (_impl_.name_.IsDefault()) { + _impl_.name_.Set("", GetArenaForAllocation()); + } +#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + return p; +} +inline void ServiceDescriptorProto::set_allocated_name(std::string* name) { + if (name != nullptr) { + _impl_._has_bits_[0] |= 0x00000001u; + } else { + _impl_._has_bits_[0] &= ~0x00000001u; + } + _impl_.name_.SetAllocated(name, GetArenaForAllocation()); +#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (_impl_.name_.IsDefault()) { + _impl_.name_.Set("", GetArenaForAllocation()); + } +#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + // @@protoc_insertion_point(field_set_allocated:google.protobuf.ServiceDescriptorProto.name) +} + +// repeated .google.protobuf.MethodDescriptorProto method = 2; +inline int ServiceDescriptorProto::_internal_method_size() const { + return _impl_.method_.size(); +} +inline int ServiceDescriptorProto::method_size() const { + return _internal_method_size(); +} +inline void ServiceDescriptorProto::clear_method() { + _impl_.method_.Clear(); +} +inline ::PROTOBUF_NAMESPACE_ID::MethodDescriptorProto* ServiceDescriptorProto::mutable_method(int index) { + // @@protoc_insertion_point(field_mutable:google.protobuf.ServiceDescriptorProto.method) + return _impl_.method_.Mutable(index); +} +inline ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::MethodDescriptorProto >* +ServiceDescriptorProto::mutable_method() { + // @@protoc_insertion_point(field_mutable_list:google.protobuf.ServiceDescriptorProto.method) + return &_impl_.method_; +} +inline const ::PROTOBUF_NAMESPACE_ID::MethodDescriptorProto& ServiceDescriptorProto::_internal_method(int index) const { + return _impl_.method_.Get(index); +} +inline const ::PROTOBUF_NAMESPACE_ID::MethodDescriptorProto& ServiceDescriptorProto::method(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.ServiceDescriptorProto.method) + return _internal_method(index); +} +inline ::PROTOBUF_NAMESPACE_ID::MethodDescriptorProto* ServiceDescriptorProto::_internal_add_method() { + return _impl_.method_.Add(); +} +inline ::PROTOBUF_NAMESPACE_ID::MethodDescriptorProto* ServiceDescriptorProto::add_method() { + ::PROTOBUF_NAMESPACE_ID::MethodDescriptorProto* _add = _internal_add_method(); + // @@protoc_insertion_point(field_add:google.protobuf.ServiceDescriptorProto.method) + return _add; +} +inline const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::MethodDescriptorProto >& +ServiceDescriptorProto::method() const { + // @@protoc_insertion_point(field_list:google.protobuf.ServiceDescriptorProto.method) + return _impl_.method_; +} + +// optional .google.protobuf.ServiceOptions options = 3; +inline bool ServiceDescriptorProto::_internal_has_options() const { + bool value = (_impl_._has_bits_[0] & 0x00000002u) != 0; + PROTOBUF_ASSUME(!value || _impl_.options_ != nullptr); + return value; +} +inline bool ServiceDescriptorProto::has_options() const { + return _internal_has_options(); +} +inline void ServiceDescriptorProto::clear_options() { + if (_impl_.options_ != nullptr) _impl_.options_->Clear(); + _impl_._has_bits_[0] &= ~0x00000002u; +} +inline const ::PROTOBUF_NAMESPACE_ID::ServiceOptions& ServiceDescriptorProto::_internal_options() const { + const ::PROTOBUF_NAMESPACE_ID::ServiceOptions* p = _impl_.options_; + return p != nullptr ? *p : reinterpret_cast<const ::PROTOBUF_NAMESPACE_ID::ServiceOptions&>( + ::PROTOBUF_NAMESPACE_ID::_ServiceOptions_default_instance_); +} +inline const ::PROTOBUF_NAMESPACE_ID::ServiceOptions& ServiceDescriptorProto::options() const { + // @@protoc_insertion_point(field_get:google.protobuf.ServiceDescriptorProto.options) + return _internal_options(); +} +inline void ServiceDescriptorProto::unsafe_arena_set_allocated_options( + ::PROTOBUF_NAMESPACE_ID::ServiceOptions* options) { + if (GetArenaForAllocation() == nullptr) { + delete reinterpret_cast<::PROTOBUF_NAMESPACE_ID::MessageLite*>(_impl_.options_); + } + _impl_.options_ = options; + if (options) { + _impl_._has_bits_[0] |= 0x00000002u; + } else { + _impl_._has_bits_[0] &= ~0x00000002u; + } + // @@protoc_insertion_point(field_unsafe_arena_set_allocated:google.protobuf.ServiceDescriptorProto.options) +} +inline ::PROTOBUF_NAMESPACE_ID::ServiceOptions* ServiceDescriptorProto::release_options() { + _impl_._has_bits_[0] &= ~0x00000002u; + ::PROTOBUF_NAMESPACE_ID::ServiceOptions* temp = _impl_.options_; + _impl_.options_ = nullptr; +#ifdef PROTOBUF_FORCE_COPY_IN_RELEASE + auto* old = reinterpret_cast<::PROTOBUF_NAMESPACE_ID::MessageLite*>(temp); + temp = ::PROTOBUF_NAMESPACE_ID::internal::DuplicateIfNonNull(temp); + if (GetArenaForAllocation() == nullptr) { delete old; } +#else // PROTOBUF_FORCE_COPY_IN_RELEASE + if (GetArenaForAllocation() != nullptr) { + temp = ::PROTOBUF_NAMESPACE_ID::internal::DuplicateIfNonNull(temp); + } +#endif // !PROTOBUF_FORCE_COPY_IN_RELEASE + return temp; +} +inline ::PROTOBUF_NAMESPACE_ID::ServiceOptions* ServiceDescriptorProto::unsafe_arena_release_options() { + // @@protoc_insertion_point(field_release:google.protobuf.ServiceDescriptorProto.options) + _impl_._has_bits_[0] &= ~0x00000002u; + ::PROTOBUF_NAMESPACE_ID::ServiceOptions* temp = _impl_.options_; + _impl_.options_ = nullptr; + return temp; +} +inline ::PROTOBUF_NAMESPACE_ID::ServiceOptions* ServiceDescriptorProto::_internal_mutable_options() { + _impl_._has_bits_[0] |= 0x00000002u; + if (_impl_.options_ == nullptr) { + auto* p = CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::ServiceOptions>(GetArenaForAllocation()); + _impl_.options_ = p; + } + return _impl_.options_; +} +inline ::PROTOBUF_NAMESPACE_ID::ServiceOptions* ServiceDescriptorProto::mutable_options() { + ::PROTOBUF_NAMESPACE_ID::ServiceOptions* _msg = _internal_mutable_options(); + // @@protoc_insertion_point(field_mutable:google.protobuf.ServiceDescriptorProto.options) + return _msg; +} +inline void ServiceDescriptorProto::set_allocated_options(::PROTOBUF_NAMESPACE_ID::ServiceOptions* options) { + ::PROTOBUF_NAMESPACE_ID::Arena* message_arena = GetArenaForAllocation(); + if (message_arena == nullptr) { + delete _impl_.options_; + } + if (options) { + ::PROTOBUF_NAMESPACE_ID::Arena* submessage_arena = + ::PROTOBUF_NAMESPACE_ID::Arena::InternalGetOwningArena(options); + if (message_arena != submessage_arena) { + options = ::PROTOBUF_NAMESPACE_ID::internal::GetOwnedMessage( + message_arena, options, submessage_arena); + } + _impl_._has_bits_[0] |= 0x00000002u; + } else { + _impl_._has_bits_[0] &= ~0x00000002u; + } + _impl_.options_ = options; + // @@protoc_insertion_point(field_set_allocated:google.protobuf.ServiceDescriptorProto.options) +} + +// ------------------------------------------------------------------- + +// MethodDescriptorProto + +// optional string name = 1; +inline bool MethodDescriptorProto::_internal_has_name() const { + bool value = (_impl_._has_bits_[0] & 0x00000001u) != 0; + return value; +} +inline bool MethodDescriptorProto::has_name() const { + return _internal_has_name(); +} +inline void MethodDescriptorProto::clear_name() { + _impl_.name_.ClearToEmpty(); + _impl_._has_bits_[0] &= ~0x00000001u; +} +inline const std::string& MethodDescriptorProto::name() const { + // @@protoc_insertion_point(field_get:google.protobuf.MethodDescriptorProto.name) + return _internal_name(); +} +template <typename ArgT0, typename... ArgT> +inline PROTOBUF_ALWAYS_INLINE +void MethodDescriptorProto::set_name(ArgT0&& arg0, ArgT... args) { + _impl_._has_bits_[0] |= 0x00000001u; + _impl_.name_.Set(static_cast<ArgT0 &&>(arg0), args..., GetArenaForAllocation()); + // @@protoc_insertion_point(field_set:google.protobuf.MethodDescriptorProto.name) +} +inline std::string* MethodDescriptorProto::mutable_name() { + std::string* _s = _internal_mutable_name(); + // @@protoc_insertion_point(field_mutable:google.protobuf.MethodDescriptorProto.name) + return _s; +} +inline const std::string& MethodDescriptorProto::_internal_name() const { + return _impl_.name_.Get(); +} +inline void MethodDescriptorProto::_internal_set_name(const std::string& value) { + _impl_._has_bits_[0] |= 0x00000001u; + _impl_.name_.Set(value, GetArenaForAllocation()); +} +inline std::string* MethodDescriptorProto::_internal_mutable_name() { + _impl_._has_bits_[0] |= 0x00000001u; + return _impl_.name_.Mutable(GetArenaForAllocation()); +} +inline std::string* MethodDescriptorProto::release_name() { + // @@protoc_insertion_point(field_release:google.protobuf.MethodDescriptorProto.name) + if (!_internal_has_name()) { + return nullptr; + } + _impl_._has_bits_[0] &= ~0x00000001u; + auto* p = _impl_.name_.Release(); +#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (_impl_.name_.IsDefault()) { + _impl_.name_.Set("", GetArenaForAllocation()); + } +#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + return p; +} +inline void MethodDescriptorProto::set_allocated_name(std::string* name) { + if (name != nullptr) { + _impl_._has_bits_[0] |= 0x00000001u; + } else { + _impl_._has_bits_[0] &= ~0x00000001u; + } + _impl_.name_.SetAllocated(name, GetArenaForAllocation()); +#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (_impl_.name_.IsDefault()) { + _impl_.name_.Set("", GetArenaForAllocation()); + } +#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + // @@protoc_insertion_point(field_set_allocated:google.protobuf.MethodDescriptorProto.name) +} + +// optional string input_type = 2; +inline bool MethodDescriptorProto::_internal_has_input_type() const { + bool value = (_impl_._has_bits_[0] & 0x00000002u) != 0; + return value; +} +inline bool MethodDescriptorProto::has_input_type() const { + return _internal_has_input_type(); +} +inline void MethodDescriptorProto::clear_input_type() { + _impl_.input_type_.ClearToEmpty(); + _impl_._has_bits_[0] &= ~0x00000002u; +} +inline const std::string& MethodDescriptorProto::input_type() const { + // @@protoc_insertion_point(field_get:google.protobuf.MethodDescriptorProto.input_type) + return _internal_input_type(); +} +template <typename ArgT0, typename... ArgT> +inline PROTOBUF_ALWAYS_INLINE +void MethodDescriptorProto::set_input_type(ArgT0&& arg0, ArgT... args) { + _impl_._has_bits_[0] |= 0x00000002u; + _impl_.input_type_.Set(static_cast<ArgT0 &&>(arg0), args..., GetArenaForAllocation()); + // @@protoc_insertion_point(field_set:google.protobuf.MethodDescriptorProto.input_type) +} +inline std::string* MethodDescriptorProto::mutable_input_type() { + std::string* _s = _internal_mutable_input_type(); + // @@protoc_insertion_point(field_mutable:google.protobuf.MethodDescriptorProto.input_type) + return _s; +} +inline const std::string& MethodDescriptorProto::_internal_input_type() const { + return _impl_.input_type_.Get(); +} +inline void MethodDescriptorProto::_internal_set_input_type(const std::string& value) { + _impl_._has_bits_[0] |= 0x00000002u; + _impl_.input_type_.Set(value, GetArenaForAllocation()); +} +inline std::string* MethodDescriptorProto::_internal_mutable_input_type() { + _impl_._has_bits_[0] |= 0x00000002u; + return _impl_.input_type_.Mutable(GetArenaForAllocation()); +} +inline std::string* MethodDescriptorProto::release_input_type() { + // @@protoc_insertion_point(field_release:google.protobuf.MethodDescriptorProto.input_type) + if (!_internal_has_input_type()) { + return nullptr; + } + _impl_._has_bits_[0] &= ~0x00000002u; + auto* p = _impl_.input_type_.Release(); +#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (_impl_.input_type_.IsDefault()) { + _impl_.input_type_.Set("", GetArenaForAllocation()); + } +#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + return p; +} +inline void MethodDescriptorProto::set_allocated_input_type(std::string* input_type) { + if (input_type != nullptr) { + _impl_._has_bits_[0] |= 0x00000002u; + } else { + _impl_._has_bits_[0] &= ~0x00000002u; + } + _impl_.input_type_.SetAllocated(input_type, GetArenaForAllocation()); +#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (_impl_.input_type_.IsDefault()) { + _impl_.input_type_.Set("", GetArenaForAllocation()); + } +#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + // @@protoc_insertion_point(field_set_allocated:google.protobuf.MethodDescriptorProto.input_type) +} + +// optional string output_type = 3; +inline bool MethodDescriptorProto::_internal_has_output_type() const { + bool value = (_impl_._has_bits_[0] & 0x00000004u) != 0; + return value; +} +inline bool MethodDescriptorProto::has_output_type() const { + return _internal_has_output_type(); +} +inline void MethodDescriptorProto::clear_output_type() { + _impl_.output_type_.ClearToEmpty(); + _impl_._has_bits_[0] &= ~0x00000004u; +} +inline const std::string& MethodDescriptorProto::output_type() const { + // @@protoc_insertion_point(field_get:google.protobuf.MethodDescriptorProto.output_type) + return _internal_output_type(); +} +template <typename ArgT0, typename... ArgT> +inline PROTOBUF_ALWAYS_INLINE +void MethodDescriptorProto::set_output_type(ArgT0&& arg0, ArgT... args) { + _impl_._has_bits_[0] |= 0x00000004u; + _impl_.output_type_.Set(static_cast<ArgT0 &&>(arg0), args..., GetArenaForAllocation()); + // @@protoc_insertion_point(field_set:google.protobuf.MethodDescriptorProto.output_type) +} +inline std::string* MethodDescriptorProto::mutable_output_type() { + std::string* _s = _internal_mutable_output_type(); + // @@protoc_insertion_point(field_mutable:google.protobuf.MethodDescriptorProto.output_type) + return _s; +} +inline const std::string& MethodDescriptorProto::_internal_output_type() const { + return _impl_.output_type_.Get(); +} +inline void MethodDescriptorProto::_internal_set_output_type(const std::string& value) { + _impl_._has_bits_[0] |= 0x00000004u; + _impl_.output_type_.Set(value, GetArenaForAllocation()); +} +inline std::string* MethodDescriptorProto::_internal_mutable_output_type() { + _impl_._has_bits_[0] |= 0x00000004u; + return _impl_.output_type_.Mutable(GetArenaForAllocation()); +} +inline std::string* MethodDescriptorProto::release_output_type() { + // @@protoc_insertion_point(field_release:google.protobuf.MethodDescriptorProto.output_type) + if (!_internal_has_output_type()) { + return nullptr; + } + _impl_._has_bits_[0] &= ~0x00000004u; + auto* p = _impl_.output_type_.Release(); +#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (_impl_.output_type_.IsDefault()) { + _impl_.output_type_.Set("", GetArenaForAllocation()); + } +#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + return p; +} +inline void MethodDescriptorProto::set_allocated_output_type(std::string* output_type) { + if (output_type != nullptr) { + _impl_._has_bits_[0] |= 0x00000004u; + } else { + _impl_._has_bits_[0] &= ~0x00000004u; + } + _impl_.output_type_.SetAllocated(output_type, GetArenaForAllocation()); +#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (_impl_.output_type_.IsDefault()) { + _impl_.output_type_.Set("", GetArenaForAllocation()); + } +#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + // @@protoc_insertion_point(field_set_allocated:google.protobuf.MethodDescriptorProto.output_type) +} + +// optional .google.protobuf.MethodOptions options = 4; +inline bool MethodDescriptorProto::_internal_has_options() const { + bool value = (_impl_._has_bits_[0] & 0x00000008u) != 0; + PROTOBUF_ASSUME(!value || _impl_.options_ != nullptr); + return value; +} +inline bool MethodDescriptorProto::has_options() const { + return _internal_has_options(); +} +inline void MethodDescriptorProto::clear_options() { + if (_impl_.options_ != nullptr) _impl_.options_->Clear(); + _impl_._has_bits_[0] &= ~0x00000008u; +} +inline const ::PROTOBUF_NAMESPACE_ID::MethodOptions& MethodDescriptorProto::_internal_options() const { + const ::PROTOBUF_NAMESPACE_ID::MethodOptions* p = _impl_.options_; + return p != nullptr ? *p : reinterpret_cast<const ::PROTOBUF_NAMESPACE_ID::MethodOptions&>( + ::PROTOBUF_NAMESPACE_ID::_MethodOptions_default_instance_); +} +inline const ::PROTOBUF_NAMESPACE_ID::MethodOptions& MethodDescriptorProto::options() const { + // @@protoc_insertion_point(field_get:google.protobuf.MethodDescriptorProto.options) + return _internal_options(); +} +inline void MethodDescriptorProto::unsafe_arena_set_allocated_options( + ::PROTOBUF_NAMESPACE_ID::MethodOptions* options) { + if (GetArenaForAllocation() == nullptr) { + delete reinterpret_cast<::PROTOBUF_NAMESPACE_ID::MessageLite*>(_impl_.options_); + } + _impl_.options_ = options; + if (options) { + _impl_._has_bits_[0] |= 0x00000008u; + } else { + _impl_._has_bits_[0] &= ~0x00000008u; + } + // @@protoc_insertion_point(field_unsafe_arena_set_allocated:google.protobuf.MethodDescriptorProto.options) +} +inline ::PROTOBUF_NAMESPACE_ID::MethodOptions* MethodDescriptorProto::release_options() { + _impl_._has_bits_[0] &= ~0x00000008u; + ::PROTOBUF_NAMESPACE_ID::MethodOptions* temp = _impl_.options_; + _impl_.options_ = nullptr; +#ifdef PROTOBUF_FORCE_COPY_IN_RELEASE + auto* old = reinterpret_cast<::PROTOBUF_NAMESPACE_ID::MessageLite*>(temp); + temp = ::PROTOBUF_NAMESPACE_ID::internal::DuplicateIfNonNull(temp); + if (GetArenaForAllocation() == nullptr) { delete old; } +#else // PROTOBUF_FORCE_COPY_IN_RELEASE + if (GetArenaForAllocation() != nullptr) { + temp = ::PROTOBUF_NAMESPACE_ID::internal::DuplicateIfNonNull(temp); + } +#endif // !PROTOBUF_FORCE_COPY_IN_RELEASE + return temp; +} +inline ::PROTOBUF_NAMESPACE_ID::MethodOptions* MethodDescriptorProto::unsafe_arena_release_options() { + // @@protoc_insertion_point(field_release:google.protobuf.MethodDescriptorProto.options) + _impl_._has_bits_[0] &= ~0x00000008u; + ::PROTOBUF_NAMESPACE_ID::MethodOptions* temp = _impl_.options_; + _impl_.options_ = nullptr; + return temp; +} +inline ::PROTOBUF_NAMESPACE_ID::MethodOptions* MethodDescriptorProto::_internal_mutable_options() { + _impl_._has_bits_[0] |= 0x00000008u; + if (_impl_.options_ == nullptr) { + auto* p = CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::MethodOptions>(GetArenaForAllocation()); + _impl_.options_ = p; + } + return _impl_.options_; +} +inline ::PROTOBUF_NAMESPACE_ID::MethodOptions* MethodDescriptorProto::mutable_options() { + ::PROTOBUF_NAMESPACE_ID::MethodOptions* _msg = _internal_mutable_options(); + // @@protoc_insertion_point(field_mutable:google.protobuf.MethodDescriptorProto.options) + return _msg; +} +inline void MethodDescriptorProto::set_allocated_options(::PROTOBUF_NAMESPACE_ID::MethodOptions* options) { + ::PROTOBUF_NAMESPACE_ID::Arena* message_arena = GetArenaForAllocation(); + if (message_arena == nullptr) { + delete _impl_.options_; + } + if (options) { + ::PROTOBUF_NAMESPACE_ID::Arena* submessage_arena = + ::PROTOBUF_NAMESPACE_ID::Arena::InternalGetOwningArena(options); + if (message_arena != submessage_arena) { + options = ::PROTOBUF_NAMESPACE_ID::internal::GetOwnedMessage( + message_arena, options, submessage_arena); + } + _impl_._has_bits_[0] |= 0x00000008u; + } else { + _impl_._has_bits_[0] &= ~0x00000008u; + } + _impl_.options_ = options; + // @@protoc_insertion_point(field_set_allocated:google.protobuf.MethodDescriptorProto.options) +} + +// optional bool client_streaming = 5 [default = false]; +inline bool MethodDescriptorProto::_internal_has_client_streaming() const { + bool value = (_impl_._has_bits_[0] & 0x00000010u) != 0; + return value; +} +inline bool MethodDescriptorProto::has_client_streaming() const { + return _internal_has_client_streaming(); +} +inline void MethodDescriptorProto::clear_client_streaming() { + _impl_.client_streaming_ = false; + _impl_._has_bits_[0] &= ~0x00000010u; +} +inline bool MethodDescriptorProto::_internal_client_streaming() const { + return _impl_.client_streaming_; +} +inline bool MethodDescriptorProto::client_streaming() const { + // @@protoc_insertion_point(field_get:google.protobuf.MethodDescriptorProto.client_streaming) + return _internal_client_streaming(); +} +inline void MethodDescriptorProto::_internal_set_client_streaming(bool value) { + _impl_._has_bits_[0] |= 0x00000010u; + _impl_.client_streaming_ = value; +} +inline void MethodDescriptorProto::set_client_streaming(bool value) { + _internal_set_client_streaming(value); + // @@protoc_insertion_point(field_set:google.protobuf.MethodDescriptorProto.client_streaming) +} + +// optional bool server_streaming = 6 [default = false]; +inline bool MethodDescriptorProto::_internal_has_server_streaming() const { + bool value = (_impl_._has_bits_[0] & 0x00000020u) != 0; + return value; +} +inline bool MethodDescriptorProto::has_server_streaming() const { + return _internal_has_server_streaming(); +} +inline void MethodDescriptorProto::clear_server_streaming() { + _impl_.server_streaming_ = false; + _impl_._has_bits_[0] &= ~0x00000020u; +} +inline bool MethodDescriptorProto::_internal_server_streaming() const { + return _impl_.server_streaming_; +} +inline bool MethodDescriptorProto::server_streaming() const { + // @@protoc_insertion_point(field_get:google.protobuf.MethodDescriptorProto.server_streaming) + return _internal_server_streaming(); +} +inline void MethodDescriptorProto::_internal_set_server_streaming(bool value) { + _impl_._has_bits_[0] |= 0x00000020u; + _impl_.server_streaming_ = value; +} +inline void MethodDescriptorProto::set_server_streaming(bool value) { + _internal_set_server_streaming(value); + // @@protoc_insertion_point(field_set:google.protobuf.MethodDescriptorProto.server_streaming) +} + +// ------------------------------------------------------------------- + +// FileOptions + +// optional string java_package = 1; +inline bool FileOptions::_internal_has_java_package() const { + bool value = (_impl_._has_bits_[0] & 0x00000001u) != 0; + return value; +} +inline bool FileOptions::has_java_package() const { + return _internal_has_java_package(); +} +inline void FileOptions::clear_java_package() { + _impl_.java_package_.ClearToEmpty(); + _impl_._has_bits_[0] &= ~0x00000001u; +} +inline const std::string& FileOptions::java_package() const { + // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.java_package) + return _internal_java_package(); +} +template <typename ArgT0, typename... ArgT> +inline PROTOBUF_ALWAYS_INLINE +void FileOptions::set_java_package(ArgT0&& arg0, ArgT... args) { + _impl_._has_bits_[0] |= 0x00000001u; + _impl_.java_package_.Set(static_cast<ArgT0 &&>(arg0), args..., GetArenaForAllocation()); + // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.java_package) +} +inline std::string* FileOptions::mutable_java_package() { + std::string* _s = _internal_mutable_java_package(); + // @@protoc_insertion_point(field_mutable:google.protobuf.FileOptions.java_package) + return _s; +} +inline const std::string& FileOptions::_internal_java_package() const { + return _impl_.java_package_.Get(); +} +inline void FileOptions::_internal_set_java_package(const std::string& value) { + _impl_._has_bits_[0] |= 0x00000001u; + _impl_.java_package_.Set(value, GetArenaForAllocation()); +} +inline std::string* FileOptions::_internal_mutable_java_package() { + _impl_._has_bits_[0] |= 0x00000001u; + return _impl_.java_package_.Mutable(GetArenaForAllocation()); +} +inline std::string* FileOptions::release_java_package() { + // @@protoc_insertion_point(field_release:google.protobuf.FileOptions.java_package) + if (!_internal_has_java_package()) { + return nullptr; + } + _impl_._has_bits_[0] &= ~0x00000001u; + auto* p = _impl_.java_package_.Release(); +#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (_impl_.java_package_.IsDefault()) { + _impl_.java_package_.Set("", GetArenaForAllocation()); + } +#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + return p; +} +inline void FileOptions::set_allocated_java_package(std::string* java_package) { + if (java_package != nullptr) { + _impl_._has_bits_[0] |= 0x00000001u; + } else { + _impl_._has_bits_[0] &= ~0x00000001u; + } + _impl_.java_package_.SetAllocated(java_package, GetArenaForAllocation()); +#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (_impl_.java_package_.IsDefault()) { + _impl_.java_package_.Set("", GetArenaForAllocation()); + } +#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + // @@protoc_insertion_point(field_set_allocated:google.protobuf.FileOptions.java_package) +} + +// optional string java_outer_classname = 8; +inline bool FileOptions::_internal_has_java_outer_classname() const { + bool value = (_impl_._has_bits_[0] & 0x00000002u) != 0; + return value; +} +inline bool FileOptions::has_java_outer_classname() const { + return _internal_has_java_outer_classname(); +} +inline void FileOptions::clear_java_outer_classname() { + _impl_.java_outer_classname_.ClearToEmpty(); + _impl_._has_bits_[0] &= ~0x00000002u; +} +inline const std::string& FileOptions::java_outer_classname() const { + // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.java_outer_classname) + return _internal_java_outer_classname(); +} +template <typename ArgT0, typename... ArgT> +inline PROTOBUF_ALWAYS_INLINE +void FileOptions::set_java_outer_classname(ArgT0&& arg0, ArgT... args) { + _impl_._has_bits_[0] |= 0x00000002u; + _impl_.java_outer_classname_.Set(static_cast<ArgT0 &&>(arg0), args..., GetArenaForAllocation()); + // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.java_outer_classname) +} +inline std::string* FileOptions::mutable_java_outer_classname() { + std::string* _s = _internal_mutable_java_outer_classname(); + // @@protoc_insertion_point(field_mutable:google.protobuf.FileOptions.java_outer_classname) + return _s; +} +inline const std::string& FileOptions::_internal_java_outer_classname() const { + return _impl_.java_outer_classname_.Get(); +} +inline void FileOptions::_internal_set_java_outer_classname(const std::string& value) { + _impl_._has_bits_[0] |= 0x00000002u; + _impl_.java_outer_classname_.Set(value, GetArenaForAllocation()); +} +inline std::string* FileOptions::_internal_mutable_java_outer_classname() { + _impl_._has_bits_[0] |= 0x00000002u; + return _impl_.java_outer_classname_.Mutable(GetArenaForAllocation()); +} +inline std::string* FileOptions::release_java_outer_classname() { + // @@protoc_insertion_point(field_release:google.protobuf.FileOptions.java_outer_classname) + if (!_internal_has_java_outer_classname()) { + return nullptr; + } + _impl_._has_bits_[0] &= ~0x00000002u; + auto* p = _impl_.java_outer_classname_.Release(); +#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (_impl_.java_outer_classname_.IsDefault()) { + _impl_.java_outer_classname_.Set("", GetArenaForAllocation()); + } +#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + return p; +} +inline void FileOptions::set_allocated_java_outer_classname(std::string* java_outer_classname) { + if (java_outer_classname != nullptr) { + _impl_._has_bits_[0] |= 0x00000002u; + } else { + _impl_._has_bits_[0] &= ~0x00000002u; + } + _impl_.java_outer_classname_.SetAllocated(java_outer_classname, GetArenaForAllocation()); +#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (_impl_.java_outer_classname_.IsDefault()) { + _impl_.java_outer_classname_.Set("", GetArenaForAllocation()); + } +#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + // @@protoc_insertion_point(field_set_allocated:google.protobuf.FileOptions.java_outer_classname) +} + +// optional bool java_multiple_files = 10 [default = false]; +inline bool FileOptions::_internal_has_java_multiple_files() const { + bool value = (_impl_._has_bits_[0] & 0x00000400u) != 0; + return value; +} +inline bool FileOptions::has_java_multiple_files() const { + return _internal_has_java_multiple_files(); +} +inline void FileOptions::clear_java_multiple_files() { + _impl_.java_multiple_files_ = false; + _impl_._has_bits_[0] &= ~0x00000400u; +} +inline bool FileOptions::_internal_java_multiple_files() const { + return _impl_.java_multiple_files_; +} +inline bool FileOptions::java_multiple_files() const { + // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.java_multiple_files) + return _internal_java_multiple_files(); +} +inline void FileOptions::_internal_set_java_multiple_files(bool value) { + _impl_._has_bits_[0] |= 0x00000400u; + _impl_.java_multiple_files_ = value; +} +inline void FileOptions::set_java_multiple_files(bool value) { + _internal_set_java_multiple_files(value); + // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.java_multiple_files) +} + +// optional bool java_generate_equals_and_hash = 20 [deprecated = true]; +inline bool FileOptions::_internal_has_java_generate_equals_and_hash() const { + bool value = (_impl_._has_bits_[0] & 0x00000800u) != 0; + return value; +} +inline bool FileOptions::has_java_generate_equals_and_hash() const { + return _internal_has_java_generate_equals_and_hash(); +} +inline void FileOptions::clear_java_generate_equals_and_hash() { + _impl_.java_generate_equals_and_hash_ = false; + _impl_._has_bits_[0] &= ~0x00000800u; +} +inline bool FileOptions::_internal_java_generate_equals_and_hash() const { + return _impl_.java_generate_equals_and_hash_; +} +inline bool FileOptions::java_generate_equals_and_hash() const { + // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.java_generate_equals_and_hash) + return _internal_java_generate_equals_and_hash(); +} +inline void FileOptions::_internal_set_java_generate_equals_and_hash(bool value) { + _impl_._has_bits_[0] |= 0x00000800u; + _impl_.java_generate_equals_and_hash_ = value; +} +inline void FileOptions::set_java_generate_equals_and_hash(bool value) { + _internal_set_java_generate_equals_and_hash(value); + // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.java_generate_equals_and_hash) +} + +// optional bool java_string_check_utf8 = 27 [default = false]; +inline bool FileOptions::_internal_has_java_string_check_utf8() const { + bool value = (_impl_._has_bits_[0] & 0x00001000u) != 0; + return value; +} +inline bool FileOptions::has_java_string_check_utf8() const { + return _internal_has_java_string_check_utf8(); +} +inline void FileOptions::clear_java_string_check_utf8() { + _impl_.java_string_check_utf8_ = false; + _impl_._has_bits_[0] &= ~0x00001000u; +} +inline bool FileOptions::_internal_java_string_check_utf8() const { + return _impl_.java_string_check_utf8_; +} +inline bool FileOptions::java_string_check_utf8() const { + // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.java_string_check_utf8) + return _internal_java_string_check_utf8(); +} +inline void FileOptions::_internal_set_java_string_check_utf8(bool value) { + _impl_._has_bits_[0] |= 0x00001000u; + _impl_.java_string_check_utf8_ = value; +} +inline void FileOptions::set_java_string_check_utf8(bool value) { + _internal_set_java_string_check_utf8(value); + // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.java_string_check_utf8) +} + +// optional .google.protobuf.FileOptions.OptimizeMode optimize_for = 9 [default = SPEED]; +inline bool FileOptions::_internal_has_optimize_for() const { + bool value = (_impl_._has_bits_[0] & 0x00040000u) != 0; + return value; +} +inline bool FileOptions::has_optimize_for() const { + return _internal_has_optimize_for(); +} +inline void FileOptions::clear_optimize_for() { + _impl_.optimize_for_ = 1; + _impl_._has_bits_[0] &= ~0x00040000u; +} +inline ::PROTOBUF_NAMESPACE_ID::FileOptions_OptimizeMode FileOptions::_internal_optimize_for() const { + return static_cast< ::PROTOBUF_NAMESPACE_ID::FileOptions_OptimizeMode >(_impl_.optimize_for_); +} +inline ::PROTOBUF_NAMESPACE_ID::FileOptions_OptimizeMode FileOptions::optimize_for() const { + // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.optimize_for) + return _internal_optimize_for(); +} +inline void FileOptions::_internal_set_optimize_for(::PROTOBUF_NAMESPACE_ID::FileOptions_OptimizeMode value) { + assert(::PROTOBUF_NAMESPACE_ID::FileOptions_OptimizeMode_IsValid(value)); + _impl_._has_bits_[0] |= 0x00040000u; + _impl_.optimize_for_ = value; +} +inline void FileOptions::set_optimize_for(::PROTOBUF_NAMESPACE_ID::FileOptions_OptimizeMode value) { + _internal_set_optimize_for(value); + // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.optimize_for) +} + +// optional string go_package = 11; +inline bool FileOptions::_internal_has_go_package() const { + bool value = (_impl_._has_bits_[0] & 0x00000004u) != 0; + return value; +} +inline bool FileOptions::has_go_package() const { + return _internal_has_go_package(); +} +inline void FileOptions::clear_go_package() { + _impl_.go_package_.ClearToEmpty(); + _impl_._has_bits_[0] &= ~0x00000004u; +} +inline const std::string& FileOptions::go_package() const { + // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.go_package) + return _internal_go_package(); +} +template <typename ArgT0, typename... ArgT> +inline PROTOBUF_ALWAYS_INLINE +void FileOptions::set_go_package(ArgT0&& arg0, ArgT... args) { + _impl_._has_bits_[0] |= 0x00000004u; + _impl_.go_package_.Set(static_cast<ArgT0 &&>(arg0), args..., GetArenaForAllocation()); + // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.go_package) +} +inline std::string* FileOptions::mutable_go_package() { + std::string* _s = _internal_mutable_go_package(); + // @@protoc_insertion_point(field_mutable:google.protobuf.FileOptions.go_package) + return _s; +} +inline const std::string& FileOptions::_internal_go_package() const { + return _impl_.go_package_.Get(); +} +inline void FileOptions::_internal_set_go_package(const std::string& value) { + _impl_._has_bits_[0] |= 0x00000004u; + _impl_.go_package_.Set(value, GetArenaForAllocation()); +} +inline std::string* FileOptions::_internal_mutable_go_package() { + _impl_._has_bits_[0] |= 0x00000004u; + return _impl_.go_package_.Mutable(GetArenaForAllocation()); +} +inline std::string* FileOptions::release_go_package() { + // @@protoc_insertion_point(field_release:google.protobuf.FileOptions.go_package) + if (!_internal_has_go_package()) { + return nullptr; + } + _impl_._has_bits_[0] &= ~0x00000004u; + auto* p = _impl_.go_package_.Release(); +#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (_impl_.go_package_.IsDefault()) { + _impl_.go_package_.Set("", GetArenaForAllocation()); + } +#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + return p; +} +inline void FileOptions::set_allocated_go_package(std::string* go_package) { + if (go_package != nullptr) { + _impl_._has_bits_[0] |= 0x00000004u; + } else { + _impl_._has_bits_[0] &= ~0x00000004u; + } + _impl_.go_package_.SetAllocated(go_package, GetArenaForAllocation()); +#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (_impl_.go_package_.IsDefault()) { + _impl_.go_package_.Set("", GetArenaForAllocation()); + } +#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + // @@protoc_insertion_point(field_set_allocated:google.protobuf.FileOptions.go_package) +} + +// optional bool cc_generic_services = 16 [default = false]; +inline bool FileOptions::_internal_has_cc_generic_services() const { + bool value = (_impl_._has_bits_[0] & 0x00002000u) != 0; + return value; +} +inline bool FileOptions::has_cc_generic_services() const { + return _internal_has_cc_generic_services(); +} +inline void FileOptions::clear_cc_generic_services() { + _impl_.cc_generic_services_ = false; + _impl_._has_bits_[0] &= ~0x00002000u; +} +inline bool FileOptions::_internal_cc_generic_services() const { + return _impl_.cc_generic_services_; +} +inline bool FileOptions::cc_generic_services() const { + // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.cc_generic_services) + return _internal_cc_generic_services(); +} +inline void FileOptions::_internal_set_cc_generic_services(bool value) { + _impl_._has_bits_[0] |= 0x00002000u; + _impl_.cc_generic_services_ = value; +} +inline void FileOptions::set_cc_generic_services(bool value) { + _internal_set_cc_generic_services(value); + // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.cc_generic_services) +} + +// optional bool java_generic_services = 17 [default = false]; +inline bool FileOptions::_internal_has_java_generic_services() const { + bool value = (_impl_._has_bits_[0] & 0x00004000u) != 0; + return value; +} +inline bool FileOptions::has_java_generic_services() const { + return _internal_has_java_generic_services(); +} +inline void FileOptions::clear_java_generic_services() { + _impl_.java_generic_services_ = false; + _impl_._has_bits_[0] &= ~0x00004000u; +} +inline bool FileOptions::_internal_java_generic_services() const { + return _impl_.java_generic_services_; +} +inline bool FileOptions::java_generic_services() const { + // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.java_generic_services) + return _internal_java_generic_services(); +} +inline void FileOptions::_internal_set_java_generic_services(bool value) { + _impl_._has_bits_[0] |= 0x00004000u; + _impl_.java_generic_services_ = value; +} +inline void FileOptions::set_java_generic_services(bool value) { + _internal_set_java_generic_services(value); + // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.java_generic_services) +} + +// optional bool py_generic_services = 18 [default = false]; +inline bool FileOptions::_internal_has_py_generic_services() const { + bool value = (_impl_._has_bits_[0] & 0x00008000u) != 0; + return value; +} +inline bool FileOptions::has_py_generic_services() const { + return _internal_has_py_generic_services(); +} +inline void FileOptions::clear_py_generic_services() { + _impl_.py_generic_services_ = false; + _impl_._has_bits_[0] &= ~0x00008000u; +} +inline bool FileOptions::_internal_py_generic_services() const { + return _impl_.py_generic_services_; +} +inline bool FileOptions::py_generic_services() const { + // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.py_generic_services) + return _internal_py_generic_services(); +} +inline void FileOptions::_internal_set_py_generic_services(bool value) { + _impl_._has_bits_[0] |= 0x00008000u; + _impl_.py_generic_services_ = value; +} +inline void FileOptions::set_py_generic_services(bool value) { + _internal_set_py_generic_services(value); + // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.py_generic_services) +} + +// optional bool php_generic_services = 42 [default = false]; +inline bool FileOptions::_internal_has_php_generic_services() const { + bool value = (_impl_._has_bits_[0] & 0x00010000u) != 0; + return value; +} +inline bool FileOptions::has_php_generic_services() const { + return _internal_has_php_generic_services(); +} +inline void FileOptions::clear_php_generic_services() { + _impl_.php_generic_services_ = false; + _impl_._has_bits_[0] &= ~0x00010000u; +} +inline bool FileOptions::_internal_php_generic_services() const { + return _impl_.php_generic_services_; +} +inline bool FileOptions::php_generic_services() const { + // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.php_generic_services) + return _internal_php_generic_services(); +} +inline void FileOptions::_internal_set_php_generic_services(bool value) { + _impl_._has_bits_[0] |= 0x00010000u; + _impl_.php_generic_services_ = value; +} +inline void FileOptions::set_php_generic_services(bool value) { + _internal_set_php_generic_services(value); + // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.php_generic_services) +} + +// optional bool deprecated = 23 [default = false]; +inline bool FileOptions::_internal_has_deprecated() const { + bool value = (_impl_._has_bits_[0] & 0x00020000u) != 0; + return value; +} +inline bool FileOptions::has_deprecated() const { + return _internal_has_deprecated(); +} +inline void FileOptions::clear_deprecated() { + _impl_.deprecated_ = false; + _impl_._has_bits_[0] &= ~0x00020000u; +} +inline bool FileOptions::_internal_deprecated() const { + return _impl_.deprecated_; +} +inline bool FileOptions::deprecated() const { + // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.deprecated) + return _internal_deprecated(); +} +inline void FileOptions::_internal_set_deprecated(bool value) { + _impl_._has_bits_[0] |= 0x00020000u; + _impl_.deprecated_ = value; +} +inline void FileOptions::set_deprecated(bool value) { + _internal_set_deprecated(value); + // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.deprecated) +} + +// optional bool cc_enable_arenas = 31 [default = true]; +inline bool FileOptions::_internal_has_cc_enable_arenas() const { + bool value = (_impl_._has_bits_[0] & 0x00080000u) != 0; + return value; +} +inline bool FileOptions::has_cc_enable_arenas() const { + return _internal_has_cc_enable_arenas(); +} +inline void FileOptions::clear_cc_enable_arenas() { + _impl_.cc_enable_arenas_ = true; + _impl_._has_bits_[0] &= ~0x00080000u; +} +inline bool FileOptions::_internal_cc_enable_arenas() const { + return _impl_.cc_enable_arenas_; +} +inline bool FileOptions::cc_enable_arenas() const { + // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.cc_enable_arenas) + return _internal_cc_enable_arenas(); +} +inline void FileOptions::_internal_set_cc_enable_arenas(bool value) { + _impl_._has_bits_[0] |= 0x00080000u; + _impl_.cc_enable_arenas_ = value; +} +inline void FileOptions::set_cc_enable_arenas(bool value) { + _internal_set_cc_enable_arenas(value); + // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.cc_enable_arenas) +} + +// optional string objc_class_prefix = 36; +inline bool FileOptions::_internal_has_objc_class_prefix() const { + bool value = (_impl_._has_bits_[0] & 0x00000008u) != 0; + return value; +} +inline bool FileOptions::has_objc_class_prefix() const { + return _internal_has_objc_class_prefix(); +} +inline void FileOptions::clear_objc_class_prefix() { + _impl_.objc_class_prefix_.ClearToEmpty(); + _impl_._has_bits_[0] &= ~0x00000008u; +} +inline const std::string& FileOptions::objc_class_prefix() const { + // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.objc_class_prefix) + return _internal_objc_class_prefix(); +} +template <typename ArgT0, typename... ArgT> +inline PROTOBUF_ALWAYS_INLINE +void FileOptions::set_objc_class_prefix(ArgT0&& arg0, ArgT... args) { + _impl_._has_bits_[0] |= 0x00000008u; + _impl_.objc_class_prefix_.Set(static_cast<ArgT0 &&>(arg0), args..., GetArenaForAllocation()); + // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.objc_class_prefix) +} +inline std::string* FileOptions::mutable_objc_class_prefix() { + std::string* _s = _internal_mutable_objc_class_prefix(); + // @@protoc_insertion_point(field_mutable:google.protobuf.FileOptions.objc_class_prefix) + return _s; +} +inline const std::string& FileOptions::_internal_objc_class_prefix() const { + return _impl_.objc_class_prefix_.Get(); +} +inline void FileOptions::_internal_set_objc_class_prefix(const std::string& value) { + _impl_._has_bits_[0] |= 0x00000008u; + _impl_.objc_class_prefix_.Set(value, GetArenaForAllocation()); +} +inline std::string* FileOptions::_internal_mutable_objc_class_prefix() { + _impl_._has_bits_[0] |= 0x00000008u; + return _impl_.objc_class_prefix_.Mutable(GetArenaForAllocation()); +} +inline std::string* FileOptions::release_objc_class_prefix() { + // @@protoc_insertion_point(field_release:google.protobuf.FileOptions.objc_class_prefix) + if (!_internal_has_objc_class_prefix()) { + return nullptr; + } + _impl_._has_bits_[0] &= ~0x00000008u; + auto* p = _impl_.objc_class_prefix_.Release(); +#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (_impl_.objc_class_prefix_.IsDefault()) { + _impl_.objc_class_prefix_.Set("", GetArenaForAllocation()); + } +#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + return p; +} +inline void FileOptions::set_allocated_objc_class_prefix(std::string* objc_class_prefix) { + if (objc_class_prefix != nullptr) { + _impl_._has_bits_[0] |= 0x00000008u; + } else { + _impl_._has_bits_[0] &= ~0x00000008u; + } + _impl_.objc_class_prefix_.SetAllocated(objc_class_prefix, GetArenaForAllocation()); +#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (_impl_.objc_class_prefix_.IsDefault()) { + _impl_.objc_class_prefix_.Set("", GetArenaForAllocation()); + } +#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + // @@protoc_insertion_point(field_set_allocated:google.protobuf.FileOptions.objc_class_prefix) +} + +// optional string csharp_namespace = 37; +inline bool FileOptions::_internal_has_csharp_namespace() const { + bool value = (_impl_._has_bits_[0] & 0x00000010u) != 0; + return value; +} +inline bool FileOptions::has_csharp_namespace() const { + return _internal_has_csharp_namespace(); +} +inline void FileOptions::clear_csharp_namespace() { + _impl_.csharp_namespace_.ClearToEmpty(); + _impl_._has_bits_[0] &= ~0x00000010u; +} +inline const std::string& FileOptions::csharp_namespace() const { + // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.csharp_namespace) + return _internal_csharp_namespace(); +} +template <typename ArgT0, typename... ArgT> +inline PROTOBUF_ALWAYS_INLINE +void FileOptions::set_csharp_namespace(ArgT0&& arg0, ArgT... args) { + _impl_._has_bits_[0] |= 0x00000010u; + _impl_.csharp_namespace_.Set(static_cast<ArgT0 &&>(arg0), args..., GetArenaForAllocation()); + // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.csharp_namespace) +} +inline std::string* FileOptions::mutable_csharp_namespace() { + std::string* _s = _internal_mutable_csharp_namespace(); + // @@protoc_insertion_point(field_mutable:google.protobuf.FileOptions.csharp_namespace) + return _s; +} +inline const std::string& FileOptions::_internal_csharp_namespace() const { + return _impl_.csharp_namespace_.Get(); +} +inline void FileOptions::_internal_set_csharp_namespace(const std::string& value) { + _impl_._has_bits_[0] |= 0x00000010u; + _impl_.csharp_namespace_.Set(value, GetArenaForAllocation()); +} +inline std::string* FileOptions::_internal_mutable_csharp_namespace() { + _impl_._has_bits_[0] |= 0x00000010u; + return _impl_.csharp_namespace_.Mutable(GetArenaForAllocation()); +} +inline std::string* FileOptions::release_csharp_namespace() { + // @@protoc_insertion_point(field_release:google.protobuf.FileOptions.csharp_namespace) + if (!_internal_has_csharp_namespace()) { + return nullptr; + } + _impl_._has_bits_[0] &= ~0x00000010u; + auto* p = _impl_.csharp_namespace_.Release(); +#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (_impl_.csharp_namespace_.IsDefault()) { + _impl_.csharp_namespace_.Set("", GetArenaForAllocation()); + } +#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + return p; +} +inline void FileOptions::set_allocated_csharp_namespace(std::string* csharp_namespace) { + if (csharp_namespace != nullptr) { + _impl_._has_bits_[0] |= 0x00000010u; + } else { + _impl_._has_bits_[0] &= ~0x00000010u; + } + _impl_.csharp_namespace_.SetAllocated(csharp_namespace, GetArenaForAllocation()); +#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (_impl_.csharp_namespace_.IsDefault()) { + _impl_.csharp_namespace_.Set("", GetArenaForAllocation()); + } +#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + // @@protoc_insertion_point(field_set_allocated:google.protobuf.FileOptions.csharp_namespace) +} + +// optional string swift_prefix = 39; +inline bool FileOptions::_internal_has_swift_prefix() const { + bool value = (_impl_._has_bits_[0] & 0x00000020u) != 0; + return value; +} +inline bool FileOptions::has_swift_prefix() const { + return _internal_has_swift_prefix(); +} +inline void FileOptions::clear_swift_prefix() { + _impl_.swift_prefix_.ClearToEmpty(); + _impl_._has_bits_[0] &= ~0x00000020u; +} +inline const std::string& FileOptions::swift_prefix() const { + // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.swift_prefix) + return _internal_swift_prefix(); +} +template <typename ArgT0, typename... ArgT> +inline PROTOBUF_ALWAYS_INLINE +void FileOptions::set_swift_prefix(ArgT0&& arg0, ArgT... args) { + _impl_._has_bits_[0] |= 0x00000020u; + _impl_.swift_prefix_.Set(static_cast<ArgT0 &&>(arg0), args..., GetArenaForAllocation()); + // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.swift_prefix) +} +inline std::string* FileOptions::mutable_swift_prefix() { + std::string* _s = _internal_mutable_swift_prefix(); + // @@protoc_insertion_point(field_mutable:google.protobuf.FileOptions.swift_prefix) + return _s; +} +inline const std::string& FileOptions::_internal_swift_prefix() const { + return _impl_.swift_prefix_.Get(); +} +inline void FileOptions::_internal_set_swift_prefix(const std::string& value) { + _impl_._has_bits_[0] |= 0x00000020u; + _impl_.swift_prefix_.Set(value, GetArenaForAllocation()); +} +inline std::string* FileOptions::_internal_mutable_swift_prefix() { + _impl_._has_bits_[0] |= 0x00000020u; + return _impl_.swift_prefix_.Mutable(GetArenaForAllocation()); +} +inline std::string* FileOptions::release_swift_prefix() { + // @@protoc_insertion_point(field_release:google.protobuf.FileOptions.swift_prefix) + if (!_internal_has_swift_prefix()) { + return nullptr; + } + _impl_._has_bits_[0] &= ~0x00000020u; + auto* p = _impl_.swift_prefix_.Release(); +#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (_impl_.swift_prefix_.IsDefault()) { + _impl_.swift_prefix_.Set("", GetArenaForAllocation()); + } +#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + return p; +} +inline void FileOptions::set_allocated_swift_prefix(std::string* swift_prefix) { + if (swift_prefix != nullptr) { + _impl_._has_bits_[0] |= 0x00000020u; + } else { + _impl_._has_bits_[0] &= ~0x00000020u; + } + _impl_.swift_prefix_.SetAllocated(swift_prefix, GetArenaForAllocation()); +#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (_impl_.swift_prefix_.IsDefault()) { + _impl_.swift_prefix_.Set("", GetArenaForAllocation()); + } +#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + // @@protoc_insertion_point(field_set_allocated:google.protobuf.FileOptions.swift_prefix) +} + +// optional string php_class_prefix = 40; +inline bool FileOptions::_internal_has_php_class_prefix() const { + bool value = (_impl_._has_bits_[0] & 0x00000040u) != 0; + return value; +} +inline bool FileOptions::has_php_class_prefix() const { + return _internal_has_php_class_prefix(); +} +inline void FileOptions::clear_php_class_prefix() { + _impl_.php_class_prefix_.ClearToEmpty(); + _impl_._has_bits_[0] &= ~0x00000040u; +} +inline const std::string& FileOptions::php_class_prefix() const { + // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.php_class_prefix) + return _internal_php_class_prefix(); +} +template <typename ArgT0, typename... ArgT> +inline PROTOBUF_ALWAYS_INLINE +void FileOptions::set_php_class_prefix(ArgT0&& arg0, ArgT... args) { + _impl_._has_bits_[0] |= 0x00000040u; + _impl_.php_class_prefix_.Set(static_cast<ArgT0 &&>(arg0), args..., GetArenaForAllocation()); + // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.php_class_prefix) +} +inline std::string* FileOptions::mutable_php_class_prefix() { + std::string* _s = _internal_mutable_php_class_prefix(); + // @@protoc_insertion_point(field_mutable:google.protobuf.FileOptions.php_class_prefix) + return _s; +} +inline const std::string& FileOptions::_internal_php_class_prefix() const { + return _impl_.php_class_prefix_.Get(); +} +inline void FileOptions::_internal_set_php_class_prefix(const std::string& value) { + _impl_._has_bits_[0] |= 0x00000040u; + _impl_.php_class_prefix_.Set(value, GetArenaForAllocation()); +} +inline std::string* FileOptions::_internal_mutable_php_class_prefix() { + _impl_._has_bits_[0] |= 0x00000040u; + return _impl_.php_class_prefix_.Mutable(GetArenaForAllocation()); +} +inline std::string* FileOptions::release_php_class_prefix() { + // @@protoc_insertion_point(field_release:google.protobuf.FileOptions.php_class_prefix) + if (!_internal_has_php_class_prefix()) { + return nullptr; + } + _impl_._has_bits_[0] &= ~0x00000040u; + auto* p = _impl_.php_class_prefix_.Release(); +#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (_impl_.php_class_prefix_.IsDefault()) { + _impl_.php_class_prefix_.Set("", GetArenaForAllocation()); + } +#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + return p; +} +inline void FileOptions::set_allocated_php_class_prefix(std::string* php_class_prefix) { + if (php_class_prefix != nullptr) { + _impl_._has_bits_[0] |= 0x00000040u; + } else { + _impl_._has_bits_[0] &= ~0x00000040u; + } + _impl_.php_class_prefix_.SetAllocated(php_class_prefix, GetArenaForAllocation()); +#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (_impl_.php_class_prefix_.IsDefault()) { + _impl_.php_class_prefix_.Set("", GetArenaForAllocation()); + } +#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + // @@protoc_insertion_point(field_set_allocated:google.protobuf.FileOptions.php_class_prefix) +} + +// optional string php_namespace = 41; +inline bool FileOptions::_internal_has_php_namespace() const { + bool value = (_impl_._has_bits_[0] & 0x00000080u) != 0; + return value; +} +inline bool FileOptions::has_php_namespace() const { + return _internal_has_php_namespace(); +} +inline void FileOptions::clear_php_namespace() { + _impl_.php_namespace_.ClearToEmpty(); + _impl_._has_bits_[0] &= ~0x00000080u; +} +inline const std::string& FileOptions::php_namespace() const { + // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.php_namespace) + return _internal_php_namespace(); +} +template <typename ArgT0, typename... ArgT> +inline PROTOBUF_ALWAYS_INLINE +void FileOptions::set_php_namespace(ArgT0&& arg0, ArgT... args) { + _impl_._has_bits_[0] |= 0x00000080u; + _impl_.php_namespace_.Set(static_cast<ArgT0 &&>(arg0), args..., GetArenaForAllocation()); + // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.php_namespace) +} +inline std::string* FileOptions::mutable_php_namespace() { + std::string* _s = _internal_mutable_php_namespace(); + // @@protoc_insertion_point(field_mutable:google.protobuf.FileOptions.php_namespace) + return _s; +} +inline const std::string& FileOptions::_internal_php_namespace() const { + return _impl_.php_namespace_.Get(); +} +inline void FileOptions::_internal_set_php_namespace(const std::string& value) { + _impl_._has_bits_[0] |= 0x00000080u; + _impl_.php_namespace_.Set(value, GetArenaForAllocation()); +} +inline std::string* FileOptions::_internal_mutable_php_namespace() { + _impl_._has_bits_[0] |= 0x00000080u; + return _impl_.php_namespace_.Mutable(GetArenaForAllocation()); +} +inline std::string* FileOptions::release_php_namespace() { + // @@protoc_insertion_point(field_release:google.protobuf.FileOptions.php_namespace) + if (!_internal_has_php_namespace()) { + return nullptr; + } + _impl_._has_bits_[0] &= ~0x00000080u; + auto* p = _impl_.php_namespace_.Release(); +#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (_impl_.php_namespace_.IsDefault()) { + _impl_.php_namespace_.Set("", GetArenaForAllocation()); + } +#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + return p; +} +inline void FileOptions::set_allocated_php_namespace(std::string* php_namespace) { + if (php_namespace != nullptr) { + _impl_._has_bits_[0] |= 0x00000080u; + } else { + _impl_._has_bits_[0] &= ~0x00000080u; + } + _impl_.php_namespace_.SetAllocated(php_namespace, GetArenaForAllocation()); +#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (_impl_.php_namespace_.IsDefault()) { + _impl_.php_namespace_.Set("", GetArenaForAllocation()); + } +#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + // @@protoc_insertion_point(field_set_allocated:google.protobuf.FileOptions.php_namespace) +} + +// optional string php_metadata_namespace = 44; +inline bool FileOptions::_internal_has_php_metadata_namespace() const { + bool value = (_impl_._has_bits_[0] & 0x00000100u) != 0; + return value; +} +inline bool FileOptions::has_php_metadata_namespace() const { + return _internal_has_php_metadata_namespace(); +} +inline void FileOptions::clear_php_metadata_namespace() { + _impl_.php_metadata_namespace_.ClearToEmpty(); + _impl_._has_bits_[0] &= ~0x00000100u; +} +inline const std::string& FileOptions::php_metadata_namespace() const { + // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.php_metadata_namespace) + return _internal_php_metadata_namespace(); +} +template <typename ArgT0, typename... ArgT> +inline PROTOBUF_ALWAYS_INLINE +void FileOptions::set_php_metadata_namespace(ArgT0&& arg0, ArgT... args) { + _impl_._has_bits_[0] |= 0x00000100u; + _impl_.php_metadata_namespace_.Set(static_cast<ArgT0 &&>(arg0), args..., GetArenaForAllocation()); + // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.php_metadata_namespace) +} +inline std::string* FileOptions::mutable_php_metadata_namespace() { + std::string* _s = _internal_mutable_php_metadata_namespace(); + // @@protoc_insertion_point(field_mutable:google.protobuf.FileOptions.php_metadata_namespace) + return _s; +} +inline const std::string& FileOptions::_internal_php_metadata_namespace() const { + return _impl_.php_metadata_namespace_.Get(); +} +inline void FileOptions::_internal_set_php_metadata_namespace(const std::string& value) { + _impl_._has_bits_[0] |= 0x00000100u; + _impl_.php_metadata_namespace_.Set(value, GetArenaForAllocation()); +} +inline std::string* FileOptions::_internal_mutable_php_metadata_namespace() { + _impl_._has_bits_[0] |= 0x00000100u; + return _impl_.php_metadata_namespace_.Mutable(GetArenaForAllocation()); +} +inline std::string* FileOptions::release_php_metadata_namespace() { + // @@protoc_insertion_point(field_release:google.protobuf.FileOptions.php_metadata_namespace) + if (!_internal_has_php_metadata_namespace()) { + return nullptr; + } + _impl_._has_bits_[0] &= ~0x00000100u; + auto* p = _impl_.php_metadata_namespace_.Release(); +#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (_impl_.php_metadata_namespace_.IsDefault()) { + _impl_.php_metadata_namespace_.Set("", GetArenaForAllocation()); + } +#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + return p; +} +inline void FileOptions::set_allocated_php_metadata_namespace(std::string* php_metadata_namespace) { + if (php_metadata_namespace != nullptr) { + _impl_._has_bits_[0] |= 0x00000100u; + } else { + _impl_._has_bits_[0] &= ~0x00000100u; + } + _impl_.php_metadata_namespace_.SetAllocated(php_metadata_namespace, GetArenaForAllocation()); +#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (_impl_.php_metadata_namespace_.IsDefault()) { + _impl_.php_metadata_namespace_.Set("", GetArenaForAllocation()); + } +#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + // @@protoc_insertion_point(field_set_allocated:google.protobuf.FileOptions.php_metadata_namespace) +} + +// optional string ruby_package = 45; +inline bool FileOptions::_internal_has_ruby_package() const { + bool value = (_impl_._has_bits_[0] & 0x00000200u) != 0; + return value; +} +inline bool FileOptions::has_ruby_package() const { + return _internal_has_ruby_package(); +} +inline void FileOptions::clear_ruby_package() { + _impl_.ruby_package_.ClearToEmpty(); + _impl_._has_bits_[0] &= ~0x00000200u; +} +inline const std::string& FileOptions::ruby_package() const { + // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.ruby_package) + return _internal_ruby_package(); +} +template <typename ArgT0, typename... ArgT> +inline PROTOBUF_ALWAYS_INLINE +void FileOptions::set_ruby_package(ArgT0&& arg0, ArgT... args) { + _impl_._has_bits_[0] |= 0x00000200u; + _impl_.ruby_package_.Set(static_cast<ArgT0 &&>(arg0), args..., GetArenaForAllocation()); + // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.ruby_package) +} +inline std::string* FileOptions::mutable_ruby_package() { + std::string* _s = _internal_mutable_ruby_package(); + // @@protoc_insertion_point(field_mutable:google.protobuf.FileOptions.ruby_package) + return _s; +} +inline const std::string& FileOptions::_internal_ruby_package() const { + return _impl_.ruby_package_.Get(); +} +inline void FileOptions::_internal_set_ruby_package(const std::string& value) { + _impl_._has_bits_[0] |= 0x00000200u; + _impl_.ruby_package_.Set(value, GetArenaForAllocation()); +} +inline std::string* FileOptions::_internal_mutable_ruby_package() { + _impl_._has_bits_[0] |= 0x00000200u; + return _impl_.ruby_package_.Mutable(GetArenaForAllocation()); +} +inline std::string* FileOptions::release_ruby_package() { + // @@protoc_insertion_point(field_release:google.protobuf.FileOptions.ruby_package) + if (!_internal_has_ruby_package()) { + return nullptr; + } + _impl_._has_bits_[0] &= ~0x00000200u; + auto* p = _impl_.ruby_package_.Release(); +#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (_impl_.ruby_package_.IsDefault()) { + _impl_.ruby_package_.Set("", GetArenaForAllocation()); + } +#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + return p; +} +inline void FileOptions::set_allocated_ruby_package(std::string* ruby_package) { + if (ruby_package != nullptr) { + _impl_._has_bits_[0] |= 0x00000200u; + } else { + _impl_._has_bits_[0] &= ~0x00000200u; + } + _impl_.ruby_package_.SetAllocated(ruby_package, GetArenaForAllocation()); +#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (_impl_.ruby_package_.IsDefault()) { + _impl_.ruby_package_.Set("", GetArenaForAllocation()); + } +#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + // @@protoc_insertion_point(field_set_allocated:google.protobuf.FileOptions.ruby_package) +} + +// repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; +inline int FileOptions::_internal_uninterpreted_option_size() const { + return _impl_.uninterpreted_option_.size(); +} +inline int FileOptions::uninterpreted_option_size() const { + return _internal_uninterpreted_option_size(); +} +inline void FileOptions::clear_uninterpreted_option() { + _impl_.uninterpreted_option_.Clear(); +} +inline ::PROTOBUF_NAMESPACE_ID::UninterpretedOption* FileOptions::mutable_uninterpreted_option(int index) { + // @@protoc_insertion_point(field_mutable:google.protobuf.FileOptions.uninterpreted_option) + return _impl_.uninterpreted_option_.Mutable(index); +} +inline ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::UninterpretedOption >* +FileOptions::mutable_uninterpreted_option() { + // @@protoc_insertion_point(field_mutable_list:google.protobuf.FileOptions.uninterpreted_option) + return &_impl_.uninterpreted_option_; +} +inline const ::PROTOBUF_NAMESPACE_ID::UninterpretedOption& FileOptions::_internal_uninterpreted_option(int index) const { + return _impl_.uninterpreted_option_.Get(index); +} +inline const ::PROTOBUF_NAMESPACE_ID::UninterpretedOption& FileOptions::uninterpreted_option(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.uninterpreted_option) + return _internal_uninterpreted_option(index); +} +inline ::PROTOBUF_NAMESPACE_ID::UninterpretedOption* FileOptions::_internal_add_uninterpreted_option() { + return _impl_.uninterpreted_option_.Add(); +} +inline ::PROTOBUF_NAMESPACE_ID::UninterpretedOption* FileOptions::add_uninterpreted_option() { + ::PROTOBUF_NAMESPACE_ID::UninterpretedOption* _add = _internal_add_uninterpreted_option(); + // @@protoc_insertion_point(field_add:google.protobuf.FileOptions.uninterpreted_option) + return _add; +} +inline const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::UninterpretedOption >& +FileOptions::uninterpreted_option() const { + // @@protoc_insertion_point(field_list:google.protobuf.FileOptions.uninterpreted_option) + return _impl_.uninterpreted_option_; +} + +// ------------------------------------------------------------------- + +// MessageOptions + +// optional bool message_set_wire_format = 1 [default = false]; +inline bool MessageOptions::_internal_has_message_set_wire_format() const { + bool value = (_impl_._has_bits_[0] & 0x00000001u) != 0; + return value; +} +inline bool MessageOptions::has_message_set_wire_format() const { + return _internal_has_message_set_wire_format(); +} +inline void MessageOptions::clear_message_set_wire_format() { + _impl_.message_set_wire_format_ = false; + _impl_._has_bits_[0] &= ~0x00000001u; +} +inline bool MessageOptions::_internal_message_set_wire_format() const { + return _impl_.message_set_wire_format_; +} +inline bool MessageOptions::message_set_wire_format() const { + // @@protoc_insertion_point(field_get:google.protobuf.MessageOptions.message_set_wire_format) + return _internal_message_set_wire_format(); +} +inline void MessageOptions::_internal_set_message_set_wire_format(bool value) { + _impl_._has_bits_[0] |= 0x00000001u; + _impl_.message_set_wire_format_ = value; +} +inline void MessageOptions::set_message_set_wire_format(bool value) { + _internal_set_message_set_wire_format(value); + // @@protoc_insertion_point(field_set:google.protobuf.MessageOptions.message_set_wire_format) +} + +// optional bool no_standard_descriptor_accessor = 2 [default = false]; +inline bool MessageOptions::_internal_has_no_standard_descriptor_accessor() const { + bool value = (_impl_._has_bits_[0] & 0x00000002u) != 0; + return value; +} +inline bool MessageOptions::has_no_standard_descriptor_accessor() const { + return _internal_has_no_standard_descriptor_accessor(); +} +inline void MessageOptions::clear_no_standard_descriptor_accessor() { + _impl_.no_standard_descriptor_accessor_ = false; + _impl_._has_bits_[0] &= ~0x00000002u; +} +inline bool MessageOptions::_internal_no_standard_descriptor_accessor() const { + return _impl_.no_standard_descriptor_accessor_; +} +inline bool MessageOptions::no_standard_descriptor_accessor() const { + // @@protoc_insertion_point(field_get:google.protobuf.MessageOptions.no_standard_descriptor_accessor) + return _internal_no_standard_descriptor_accessor(); +} +inline void MessageOptions::_internal_set_no_standard_descriptor_accessor(bool value) { + _impl_._has_bits_[0] |= 0x00000002u; + _impl_.no_standard_descriptor_accessor_ = value; +} +inline void MessageOptions::set_no_standard_descriptor_accessor(bool value) { + _internal_set_no_standard_descriptor_accessor(value); + // @@protoc_insertion_point(field_set:google.protobuf.MessageOptions.no_standard_descriptor_accessor) +} + +// optional bool deprecated = 3 [default = false]; +inline bool MessageOptions::_internal_has_deprecated() const { + bool value = (_impl_._has_bits_[0] & 0x00000004u) != 0; + return value; +} +inline bool MessageOptions::has_deprecated() const { + return _internal_has_deprecated(); +} +inline void MessageOptions::clear_deprecated() { + _impl_.deprecated_ = false; + _impl_._has_bits_[0] &= ~0x00000004u; +} +inline bool MessageOptions::_internal_deprecated() const { + return _impl_.deprecated_; +} +inline bool MessageOptions::deprecated() const { + // @@protoc_insertion_point(field_get:google.protobuf.MessageOptions.deprecated) + return _internal_deprecated(); +} +inline void MessageOptions::_internal_set_deprecated(bool value) { + _impl_._has_bits_[0] |= 0x00000004u; + _impl_.deprecated_ = value; +} +inline void MessageOptions::set_deprecated(bool value) { + _internal_set_deprecated(value); + // @@protoc_insertion_point(field_set:google.protobuf.MessageOptions.deprecated) +} + +// optional bool map_entry = 7; +inline bool MessageOptions::_internal_has_map_entry() const { + bool value = (_impl_._has_bits_[0] & 0x00000008u) != 0; + return value; +} +inline bool MessageOptions::has_map_entry() const { + return _internal_has_map_entry(); +} +inline void MessageOptions::clear_map_entry() { + _impl_.map_entry_ = false; + _impl_._has_bits_[0] &= ~0x00000008u; +} +inline bool MessageOptions::_internal_map_entry() const { + return _impl_.map_entry_; +} +inline bool MessageOptions::map_entry() const { + // @@protoc_insertion_point(field_get:google.protobuf.MessageOptions.map_entry) + return _internal_map_entry(); +} +inline void MessageOptions::_internal_set_map_entry(bool value) { + _impl_._has_bits_[0] |= 0x00000008u; + _impl_.map_entry_ = value; +} +inline void MessageOptions::set_map_entry(bool value) { + _internal_set_map_entry(value); + // @@protoc_insertion_point(field_set:google.protobuf.MessageOptions.map_entry) +} + +// repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; +inline int MessageOptions::_internal_uninterpreted_option_size() const { + return _impl_.uninterpreted_option_.size(); +} +inline int MessageOptions::uninterpreted_option_size() const { + return _internal_uninterpreted_option_size(); +} +inline void MessageOptions::clear_uninterpreted_option() { + _impl_.uninterpreted_option_.Clear(); +} +inline ::PROTOBUF_NAMESPACE_ID::UninterpretedOption* MessageOptions::mutable_uninterpreted_option(int index) { + // @@protoc_insertion_point(field_mutable:google.protobuf.MessageOptions.uninterpreted_option) + return _impl_.uninterpreted_option_.Mutable(index); +} +inline ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::UninterpretedOption >* +MessageOptions::mutable_uninterpreted_option() { + // @@protoc_insertion_point(field_mutable_list:google.protobuf.MessageOptions.uninterpreted_option) + return &_impl_.uninterpreted_option_; +} +inline const ::PROTOBUF_NAMESPACE_ID::UninterpretedOption& MessageOptions::_internal_uninterpreted_option(int index) const { + return _impl_.uninterpreted_option_.Get(index); +} +inline const ::PROTOBUF_NAMESPACE_ID::UninterpretedOption& MessageOptions::uninterpreted_option(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.MessageOptions.uninterpreted_option) + return _internal_uninterpreted_option(index); +} +inline ::PROTOBUF_NAMESPACE_ID::UninterpretedOption* MessageOptions::_internal_add_uninterpreted_option() { + return _impl_.uninterpreted_option_.Add(); +} +inline ::PROTOBUF_NAMESPACE_ID::UninterpretedOption* MessageOptions::add_uninterpreted_option() { + ::PROTOBUF_NAMESPACE_ID::UninterpretedOption* _add = _internal_add_uninterpreted_option(); + // @@protoc_insertion_point(field_add:google.protobuf.MessageOptions.uninterpreted_option) + return _add; +} +inline const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::UninterpretedOption >& +MessageOptions::uninterpreted_option() const { + // @@protoc_insertion_point(field_list:google.protobuf.MessageOptions.uninterpreted_option) + return _impl_.uninterpreted_option_; +} + +// ------------------------------------------------------------------- + +// FieldOptions + +// optional .google.protobuf.FieldOptions.CType ctype = 1 [default = STRING]; +inline bool FieldOptions::_internal_has_ctype() const { + bool value = (_impl_._has_bits_[0] & 0x00000001u) != 0; + return value; +} +inline bool FieldOptions::has_ctype() const { + return _internal_has_ctype(); +} +inline void FieldOptions::clear_ctype() { + _impl_.ctype_ = 0; + _impl_._has_bits_[0] &= ~0x00000001u; +} +inline ::PROTOBUF_NAMESPACE_ID::FieldOptions_CType FieldOptions::_internal_ctype() const { + return static_cast< ::PROTOBUF_NAMESPACE_ID::FieldOptions_CType >(_impl_.ctype_); +} +inline ::PROTOBUF_NAMESPACE_ID::FieldOptions_CType FieldOptions::ctype() const { + // @@protoc_insertion_point(field_get:google.protobuf.FieldOptions.ctype) + return _internal_ctype(); +} +inline void FieldOptions::_internal_set_ctype(::PROTOBUF_NAMESPACE_ID::FieldOptions_CType value) { + assert(::PROTOBUF_NAMESPACE_ID::FieldOptions_CType_IsValid(value)); + _impl_._has_bits_[0] |= 0x00000001u; + _impl_.ctype_ = value; +} +inline void FieldOptions::set_ctype(::PROTOBUF_NAMESPACE_ID::FieldOptions_CType value) { + _internal_set_ctype(value); + // @@protoc_insertion_point(field_set:google.protobuf.FieldOptions.ctype) +} + +// optional bool packed = 2; +inline bool FieldOptions::_internal_has_packed() const { + bool value = (_impl_._has_bits_[0] & 0x00000004u) != 0; + return value; +} +inline bool FieldOptions::has_packed() const { + return _internal_has_packed(); +} +inline void FieldOptions::clear_packed() { + _impl_.packed_ = false; + _impl_._has_bits_[0] &= ~0x00000004u; +} +inline bool FieldOptions::_internal_packed() const { + return _impl_.packed_; +} +inline bool FieldOptions::packed() const { + // @@protoc_insertion_point(field_get:google.protobuf.FieldOptions.packed) + return _internal_packed(); +} +inline void FieldOptions::_internal_set_packed(bool value) { + _impl_._has_bits_[0] |= 0x00000004u; + _impl_.packed_ = value; +} +inline void FieldOptions::set_packed(bool value) { + _internal_set_packed(value); + // @@protoc_insertion_point(field_set:google.protobuf.FieldOptions.packed) +} + +// optional .google.protobuf.FieldOptions.JSType jstype = 6 [default = JS_NORMAL]; +inline bool FieldOptions::_internal_has_jstype() const { + bool value = (_impl_._has_bits_[0] & 0x00000002u) != 0; + return value; +} +inline bool FieldOptions::has_jstype() const { + return _internal_has_jstype(); +} +inline void FieldOptions::clear_jstype() { + _impl_.jstype_ = 0; + _impl_._has_bits_[0] &= ~0x00000002u; +} +inline ::PROTOBUF_NAMESPACE_ID::FieldOptions_JSType FieldOptions::_internal_jstype() const { + return static_cast< ::PROTOBUF_NAMESPACE_ID::FieldOptions_JSType >(_impl_.jstype_); +} +inline ::PROTOBUF_NAMESPACE_ID::FieldOptions_JSType FieldOptions::jstype() const { + // @@protoc_insertion_point(field_get:google.protobuf.FieldOptions.jstype) + return _internal_jstype(); +} +inline void FieldOptions::_internal_set_jstype(::PROTOBUF_NAMESPACE_ID::FieldOptions_JSType value) { + assert(::PROTOBUF_NAMESPACE_ID::FieldOptions_JSType_IsValid(value)); + _impl_._has_bits_[0] |= 0x00000002u; + _impl_.jstype_ = value; +} +inline void FieldOptions::set_jstype(::PROTOBUF_NAMESPACE_ID::FieldOptions_JSType value) { + _internal_set_jstype(value); + // @@protoc_insertion_point(field_set:google.protobuf.FieldOptions.jstype) +} + +// optional bool lazy = 5 [default = false]; +inline bool FieldOptions::_internal_has_lazy() const { + bool value = (_impl_._has_bits_[0] & 0x00000008u) != 0; + return value; +} +inline bool FieldOptions::has_lazy() const { + return _internal_has_lazy(); +} +inline void FieldOptions::clear_lazy() { + _impl_.lazy_ = false; + _impl_._has_bits_[0] &= ~0x00000008u; +} +inline bool FieldOptions::_internal_lazy() const { + return _impl_.lazy_; +} +inline bool FieldOptions::lazy() const { + // @@protoc_insertion_point(field_get:google.protobuf.FieldOptions.lazy) + return _internal_lazy(); +} +inline void FieldOptions::_internal_set_lazy(bool value) { + _impl_._has_bits_[0] |= 0x00000008u; + _impl_.lazy_ = value; +} +inline void FieldOptions::set_lazy(bool value) { + _internal_set_lazy(value); + // @@protoc_insertion_point(field_set:google.protobuf.FieldOptions.lazy) +} + +// optional bool unverified_lazy = 15 [default = false]; +inline bool FieldOptions::_internal_has_unverified_lazy() const { + bool value = (_impl_._has_bits_[0] & 0x00000010u) != 0; + return value; +} +inline bool FieldOptions::has_unverified_lazy() const { + return _internal_has_unverified_lazy(); +} +inline void FieldOptions::clear_unverified_lazy() { + _impl_.unverified_lazy_ = false; + _impl_._has_bits_[0] &= ~0x00000010u; +} +inline bool FieldOptions::_internal_unverified_lazy() const { + return _impl_.unverified_lazy_; +} +inline bool FieldOptions::unverified_lazy() const { + // @@protoc_insertion_point(field_get:google.protobuf.FieldOptions.unverified_lazy) + return _internal_unverified_lazy(); +} +inline void FieldOptions::_internal_set_unverified_lazy(bool value) { + _impl_._has_bits_[0] |= 0x00000010u; + _impl_.unverified_lazy_ = value; +} +inline void FieldOptions::set_unverified_lazy(bool value) { + _internal_set_unverified_lazy(value); + // @@protoc_insertion_point(field_set:google.protobuf.FieldOptions.unverified_lazy) +} + +// optional bool deprecated = 3 [default = false]; +inline bool FieldOptions::_internal_has_deprecated() const { + bool value = (_impl_._has_bits_[0] & 0x00000020u) != 0; + return value; +} +inline bool FieldOptions::has_deprecated() const { + return _internal_has_deprecated(); +} +inline void FieldOptions::clear_deprecated() { + _impl_.deprecated_ = false; + _impl_._has_bits_[0] &= ~0x00000020u; +} +inline bool FieldOptions::_internal_deprecated() const { + return _impl_.deprecated_; +} +inline bool FieldOptions::deprecated() const { + // @@protoc_insertion_point(field_get:google.protobuf.FieldOptions.deprecated) + return _internal_deprecated(); +} +inline void FieldOptions::_internal_set_deprecated(bool value) { + _impl_._has_bits_[0] |= 0x00000020u; + _impl_.deprecated_ = value; +} +inline void FieldOptions::set_deprecated(bool value) { + _internal_set_deprecated(value); + // @@protoc_insertion_point(field_set:google.protobuf.FieldOptions.deprecated) +} + +// optional bool weak = 10 [default = false]; +inline bool FieldOptions::_internal_has_weak() const { + bool value = (_impl_._has_bits_[0] & 0x00000040u) != 0; + return value; +} +inline bool FieldOptions::has_weak() const { + return _internal_has_weak(); +} +inline void FieldOptions::clear_weak() { + _impl_.weak_ = false; + _impl_._has_bits_[0] &= ~0x00000040u; +} +inline bool FieldOptions::_internal_weak() const { + return _impl_.weak_; +} +inline bool FieldOptions::weak() const { + // @@protoc_insertion_point(field_get:google.protobuf.FieldOptions.weak) + return _internal_weak(); +} +inline void FieldOptions::_internal_set_weak(bool value) { + _impl_._has_bits_[0] |= 0x00000040u; + _impl_.weak_ = value; +} +inline void FieldOptions::set_weak(bool value) { + _internal_set_weak(value); + // @@protoc_insertion_point(field_set:google.protobuf.FieldOptions.weak) +} + +// repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; +inline int FieldOptions::_internal_uninterpreted_option_size() const { + return _impl_.uninterpreted_option_.size(); +} +inline int FieldOptions::uninterpreted_option_size() const { + return _internal_uninterpreted_option_size(); +} +inline void FieldOptions::clear_uninterpreted_option() { + _impl_.uninterpreted_option_.Clear(); +} +inline ::PROTOBUF_NAMESPACE_ID::UninterpretedOption* FieldOptions::mutable_uninterpreted_option(int index) { + // @@protoc_insertion_point(field_mutable:google.protobuf.FieldOptions.uninterpreted_option) + return _impl_.uninterpreted_option_.Mutable(index); +} +inline ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::UninterpretedOption >* +FieldOptions::mutable_uninterpreted_option() { + // @@protoc_insertion_point(field_mutable_list:google.protobuf.FieldOptions.uninterpreted_option) + return &_impl_.uninterpreted_option_; +} +inline const ::PROTOBUF_NAMESPACE_ID::UninterpretedOption& FieldOptions::_internal_uninterpreted_option(int index) const { + return _impl_.uninterpreted_option_.Get(index); +} +inline const ::PROTOBUF_NAMESPACE_ID::UninterpretedOption& FieldOptions::uninterpreted_option(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.FieldOptions.uninterpreted_option) + return _internal_uninterpreted_option(index); +} +inline ::PROTOBUF_NAMESPACE_ID::UninterpretedOption* FieldOptions::_internal_add_uninterpreted_option() { + return _impl_.uninterpreted_option_.Add(); +} +inline ::PROTOBUF_NAMESPACE_ID::UninterpretedOption* FieldOptions::add_uninterpreted_option() { + ::PROTOBUF_NAMESPACE_ID::UninterpretedOption* _add = _internal_add_uninterpreted_option(); + // @@protoc_insertion_point(field_add:google.protobuf.FieldOptions.uninterpreted_option) + return _add; +} +inline const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::UninterpretedOption >& +FieldOptions::uninterpreted_option() const { + // @@protoc_insertion_point(field_list:google.protobuf.FieldOptions.uninterpreted_option) + return _impl_.uninterpreted_option_; +} + +// ------------------------------------------------------------------- + +// OneofOptions + +// repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; +inline int OneofOptions::_internal_uninterpreted_option_size() const { + return _impl_.uninterpreted_option_.size(); +} +inline int OneofOptions::uninterpreted_option_size() const { + return _internal_uninterpreted_option_size(); +} +inline void OneofOptions::clear_uninterpreted_option() { + _impl_.uninterpreted_option_.Clear(); +} +inline ::PROTOBUF_NAMESPACE_ID::UninterpretedOption* OneofOptions::mutable_uninterpreted_option(int index) { + // @@protoc_insertion_point(field_mutable:google.protobuf.OneofOptions.uninterpreted_option) + return _impl_.uninterpreted_option_.Mutable(index); +} +inline ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::UninterpretedOption >* +OneofOptions::mutable_uninterpreted_option() { + // @@protoc_insertion_point(field_mutable_list:google.protobuf.OneofOptions.uninterpreted_option) + return &_impl_.uninterpreted_option_; +} +inline const ::PROTOBUF_NAMESPACE_ID::UninterpretedOption& OneofOptions::_internal_uninterpreted_option(int index) const { + return _impl_.uninterpreted_option_.Get(index); +} +inline const ::PROTOBUF_NAMESPACE_ID::UninterpretedOption& OneofOptions::uninterpreted_option(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.OneofOptions.uninterpreted_option) + return _internal_uninterpreted_option(index); +} +inline ::PROTOBUF_NAMESPACE_ID::UninterpretedOption* OneofOptions::_internal_add_uninterpreted_option() { + return _impl_.uninterpreted_option_.Add(); +} +inline ::PROTOBUF_NAMESPACE_ID::UninterpretedOption* OneofOptions::add_uninterpreted_option() { + ::PROTOBUF_NAMESPACE_ID::UninterpretedOption* _add = _internal_add_uninterpreted_option(); + // @@protoc_insertion_point(field_add:google.protobuf.OneofOptions.uninterpreted_option) + return _add; +} +inline const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::UninterpretedOption >& +OneofOptions::uninterpreted_option() const { + // @@protoc_insertion_point(field_list:google.protobuf.OneofOptions.uninterpreted_option) + return _impl_.uninterpreted_option_; +} + +// ------------------------------------------------------------------- + +// EnumOptions + +// optional bool allow_alias = 2; +inline bool EnumOptions::_internal_has_allow_alias() const { + bool value = (_impl_._has_bits_[0] & 0x00000001u) != 0; + return value; +} +inline bool EnumOptions::has_allow_alias() const { + return _internal_has_allow_alias(); +} +inline void EnumOptions::clear_allow_alias() { + _impl_.allow_alias_ = false; + _impl_._has_bits_[0] &= ~0x00000001u; +} +inline bool EnumOptions::_internal_allow_alias() const { + return _impl_.allow_alias_; +} +inline bool EnumOptions::allow_alias() const { + // @@protoc_insertion_point(field_get:google.protobuf.EnumOptions.allow_alias) + return _internal_allow_alias(); +} +inline void EnumOptions::_internal_set_allow_alias(bool value) { + _impl_._has_bits_[0] |= 0x00000001u; + _impl_.allow_alias_ = value; +} +inline void EnumOptions::set_allow_alias(bool value) { + _internal_set_allow_alias(value); + // @@protoc_insertion_point(field_set:google.protobuf.EnumOptions.allow_alias) +} + +// optional bool deprecated = 3 [default = false]; +inline bool EnumOptions::_internal_has_deprecated() const { + bool value = (_impl_._has_bits_[0] & 0x00000002u) != 0; + return value; +} +inline bool EnumOptions::has_deprecated() const { + return _internal_has_deprecated(); +} +inline void EnumOptions::clear_deprecated() { + _impl_.deprecated_ = false; + _impl_._has_bits_[0] &= ~0x00000002u; +} +inline bool EnumOptions::_internal_deprecated() const { + return _impl_.deprecated_; +} +inline bool EnumOptions::deprecated() const { + // @@protoc_insertion_point(field_get:google.protobuf.EnumOptions.deprecated) + return _internal_deprecated(); +} +inline void EnumOptions::_internal_set_deprecated(bool value) { + _impl_._has_bits_[0] |= 0x00000002u; + _impl_.deprecated_ = value; +} +inline void EnumOptions::set_deprecated(bool value) { + _internal_set_deprecated(value); + // @@protoc_insertion_point(field_set:google.protobuf.EnumOptions.deprecated) +} + +// repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; +inline int EnumOptions::_internal_uninterpreted_option_size() const { + return _impl_.uninterpreted_option_.size(); +} +inline int EnumOptions::uninterpreted_option_size() const { + return _internal_uninterpreted_option_size(); +} +inline void EnumOptions::clear_uninterpreted_option() { + _impl_.uninterpreted_option_.Clear(); +} +inline ::PROTOBUF_NAMESPACE_ID::UninterpretedOption* EnumOptions::mutable_uninterpreted_option(int index) { + // @@protoc_insertion_point(field_mutable:google.protobuf.EnumOptions.uninterpreted_option) + return _impl_.uninterpreted_option_.Mutable(index); +} +inline ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::UninterpretedOption >* +EnumOptions::mutable_uninterpreted_option() { + // @@protoc_insertion_point(field_mutable_list:google.protobuf.EnumOptions.uninterpreted_option) + return &_impl_.uninterpreted_option_; +} +inline const ::PROTOBUF_NAMESPACE_ID::UninterpretedOption& EnumOptions::_internal_uninterpreted_option(int index) const { + return _impl_.uninterpreted_option_.Get(index); +} +inline const ::PROTOBUF_NAMESPACE_ID::UninterpretedOption& EnumOptions::uninterpreted_option(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.EnumOptions.uninterpreted_option) + return _internal_uninterpreted_option(index); +} +inline ::PROTOBUF_NAMESPACE_ID::UninterpretedOption* EnumOptions::_internal_add_uninterpreted_option() { + return _impl_.uninterpreted_option_.Add(); +} +inline ::PROTOBUF_NAMESPACE_ID::UninterpretedOption* EnumOptions::add_uninterpreted_option() { + ::PROTOBUF_NAMESPACE_ID::UninterpretedOption* _add = _internal_add_uninterpreted_option(); + // @@protoc_insertion_point(field_add:google.protobuf.EnumOptions.uninterpreted_option) + return _add; +} +inline const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::UninterpretedOption >& +EnumOptions::uninterpreted_option() const { + // @@protoc_insertion_point(field_list:google.protobuf.EnumOptions.uninterpreted_option) + return _impl_.uninterpreted_option_; +} + +// ------------------------------------------------------------------- + +// EnumValueOptions + +// optional bool deprecated = 1 [default = false]; +inline bool EnumValueOptions::_internal_has_deprecated() const { + bool value = (_impl_._has_bits_[0] & 0x00000001u) != 0; + return value; +} +inline bool EnumValueOptions::has_deprecated() const { + return _internal_has_deprecated(); +} +inline void EnumValueOptions::clear_deprecated() { + _impl_.deprecated_ = false; + _impl_._has_bits_[0] &= ~0x00000001u; +} +inline bool EnumValueOptions::_internal_deprecated() const { + return _impl_.deprecated_; +} +inline bool EnumValueOptions::deprecated() const { + // @@protoc_insertion_point(field_get:google.protobuf.EnumValueOptions.deprecated) + return _internal_deprecated(); +} +inline void EnumValueOptions::_internal_set_deprecated(bool value) { + _impl_._has_bits_[0] |= 0x00000001u; + _impl_.deprecated_ = value; +} +inline void EnumValueOptions::set_deprecated(bool value) { + _internal_set_deprecated(value); + // @@protoc_insertion_point(field_set:google.protobuf.EnumValueOptions.deprecated) +} + +// repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; +inline int EnumValueOptions::_internal_uninterpreted_option_size() const { + return _impl_.uninterpreted_option_.size(); +} +inline int EnumValueOptions::uninterpreted_option_size() const { + return _internal_uninterpreted_option_size(); +} +inline void EnumValueOptions::clear_uninterpreted_option() { + _impl_.uninterpreted_option_.Clear(); +} +inline ::PROTOBUF_NAMESPACE_ID::UninterpretedOption* EnumValueOptions::mutable_uninterpreted_option(int index) { + // @@protoc_insertion_point(field_mutable:google.protobuf.EnumValueOptions.uninterpreted_option) + return _impl_.uninterpreted_option_.Mutable(index); +} +inline ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::UninterpretedOption >* +EnumValueOptions::mutable_uninterpreted_option() { + // @@protoc_insertion_point(field_mutable_list:google.protobuf.EnumValueOptions.uninterpreted_option) + return &_impl_.uninterpreted_option_; +} +inline const ::PROTOBUF_NAMESPACE_ID::UninterpretedOption& EnumValueOptions::_internal_uninterpreted_option(int index) const { + return _impl_.uninterpreted_option_.Get(index); +} +inline const ::PROTOBUF_NAMESPACE_ID::UninterpretedOption& EnumValueOptions::uninterpreted_option(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.EnumValueOptions.uninterpreted_option) + return _internal_uninterpreted_option(index); +} +inline ::PROTOBUF_NAMESPACE_ID::UninterpretedOption* EnumValueOptions::_internal_add_uninterpreted_option() { + return _impl_.uninterpreted_option_.Add(); +} +inline ::PROTOBUF_NAMESPACE_ID::UninterpretedOption* EnumValueOptions::add_uninterpreted_option() { + ::PROTOBUF_NAMESPACE_ID::UninterpretedOption* _add = _internal_add_uninterpreted_option(); + // @@protoc_insertion_point(field_add:google.protobuf.EnumValueOptions.uninterpreted_option) + return _add; +} +inline const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::UninterpretedOption >& +EnumValueOptions::uninterpreted_option() const { + // @@protoc_insertion_point(field_list:google.protobuf.EnumValueOptions.uninterpreted_option) + return _impl_.uninterpreted_option_; +} + +// ------------------------------------------------------------------- + +// ServiceOptions + +// optional bool deprecated = 33 [default = false]; +inline bool ServiceOptions::_internal_has_deprecated() const { + bool value = (_impl_._has_bits_[0] & 0x00000001u) != 0; + return value; +} +inline bool ServiceOptions::has_deprecated() const { + return _internal_has_deprecated(); +} +inline void ServiceOptions::clear_deprecated() { + _impl_.deprecated_ = false; + _impl_._has_bits_[0] &= ~0x00000001u; +} +inline bool ServiceOptions::_internal_deprecated() const { + return _impl_.deprecated_; +} +inline bool ServiceOptions::deprecated() const { + // @@protoc_insertion_point(field_get:google.protobuf.ServiceOptions.deprecated) + return _internal_deprecated(); +} +inline void ServiceOptions::_internal_set_deprecated(bool value) { + _impl_._has_bits_[0] |= 0x00000001u; + _impl_.deprecated_ = value; +} +inline void ServiceOptions::set_deprecated(bool value) { + _internal_set_deprecated(value); + // @@protoc_insertion_point(field_set:google.protobuf.ServiceOptions.deprecated) +} + +// repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; +inline int ServiceOptions::_internal_uninterpreted_option_size() const { + return _impl_.uninterpreted_option_.size(); +} +inline int ServiceOptions::uninterpreted_option_size() const { + return _internal_uninterpreted_option_size(); +} +inline void ServiceOptions::clear_uninterpreted_option() { + _impl_.uninterpreted_option_.Clear(); +} +inline ::PROTOBUF_NAMESPACE_ID::UninterpretedOption* ServiceOptions::mutable_uninterpreted_option(int index) { + // @@protoc_insertion_point(field_mutable:google.protobuf.ServiceOptions.uninterpreted_option) + return _impl_.uninterpreted_option_.Mutable(index); +} +inline ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::UninterpretedOption >* +ServiceOptions::mutable_uninterpreted_option() { + // @@protoc_insertion_point(field_mutable_list:google.protobuf.ServiceOptions.uninterpreted_option) + return &_impl_.uninterpreted_option_; +} +inline const ::PROTOBUF_NAMESPACE_ID::UninterpretedOption& ServiceOptions::_internal_uninterpreted_option(int index) const { + return _impl_.uninterpreted_option_.Get(index); +} +inline const ::PROTOBUF_NAMESPACE_ID::UninterpretedOption& ServiceOptions::uninterpreted_option(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.ServiceOptions.uninterpreted_option) + return _internal_uninterpreted_option(index); +} +inline ::PROTOBUF_NAMESPACE_ID::UninterpretedOption* ServiceOptions::_internal_add_uninterpreted_option() { + return _impl_.uninterpreted_option_.Add(); +} +inline ::PROTOBUF_NAMESPACE_ID::UninterpretedOption* ServiceOptions::add_uninterpreted_option() { + ::PROTOBUF_NAMESPACE_ID::UninterpretedOption* _add = _internal_add_uninterpreted_option(); + // @@protoc_insertion_point(field_add:google.protobuf.ServiceOptions.uninterpreted_option) + return _add; +} +inline const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::UninterpretedOption >& +ServiceOptions::uninterpreted_option() const { + // @@protoc_insertion_point(field_list:google.protobuf.ServiceOptions.uninterpreted_option) + return _impl_.uninterpreted_option_; +} + +// ------------------------------------------------------------------- + +// MethodOptions + +// optional bool deprecated = 33 [default = false]; +inline bool MethodOptions::_internal_has_deprecated() const { + bool value = (_impl_._has_bits_[0] & 0x00000001u) != 0; + return value; +} +inline bool MethodOptions::has_deprecated() const { + return _internal_has_deprecated(); +} +inline void MethodOptions::clear_deprecated() { + _impl_.deprecated_ = false; + _impl_._has_bits_[0] &= ~0x00000001u; +} +inline bool MethodOptions::_internal_deprecated() const { + return _impl_.deprecated_; +} +inline bool MethodOptions::deprecated() const { + // @@protoc_insertion_point(field_get:google.protobuf.MethodOptions.deprecated) + return _internal_deprecated(); +} +inline void MethodOptions::_internal_set_deprecated(bool value) { + _impl_._has_bits_[0] |= 0x00000001u; + _impl_.deprecated_ = value; +} +inline void MethodOptions::set_deprecated(bool value) { + _internal_set_deprecated(value); + // @@protoc_insertion_point(field_set:google.protobuf.MethodOptions.deprecated) +} + +// optional .google.protobuf.MethodOptions.IdempotencyLevel idempotency_level = 34 [default = IDEMPOTENCY_UNKNOWN]; +inline bool MethodOptions::_internal_has_idempotency_level() const { + bool value = (_impl_._has_bits_[0] & 0x00000002u) != 0; + return value; +} +inline bool MethodOptions::has_idempotency_level() const { + return _internal_has_idempotency_level(); +} +inline void MethodOptions::clear_idempotency_level() { + _impl_.idempotency_level_ = 0; + _impl_._has_bits_[0] &= ~0x00000002u; +} +inline ::PROTOBUF_NAMESPACE_ID::MethodOptions_IdempotencyLevel MethodOptions::_internal_idempotency_level() const { + return static_cast< ::PROTOBUF_NAMESPACE_ID::MethodOptions_IdempotencyLevel >(_impl_.idempotency_level_); +} +inline ::PROTOBUF_NAMESPACE_ID::MethodOptions_IdempotencyLevel MethodOptions::idempotency_level() const { + // @@protoc_insertion_point(field_get:google.protobuf.MethodOptions.idempotency_level) + return _internal_idempotency_level(); +} +inline void MethodOptions::_internal_set_idempotency_level(::PROTOBUF_NAMESPACE_ID::MethodOptions_IdempotencyLevel value) { + assert(::PROTOBUF_NAMESPACE_ID::MethodOptions_IdempotencyLevel_IsValid(value)); + _impl_._has_bits_[0] |= 0x00000002u; + _impl_.idempotency_level_ = value; +} +inline void MethodOptions::set_idempotency_level(::PROTOBUF_NAMESPACE_ID::MethodOptions_IdempotencyLevel value) { + _internal_set_idempotency_level(value); + // @@protoc_insertion_point(field_set:google.protobuf.MethodOptions.idempotency_level) +} + +// repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; +inline int MethodOptions::_internal_uninterpreted_option_size() const { + return _impl_.uninterpreted_option_.size(); +} +inline int MethodOptions::uninterpreted_option_size() const { + return _internal_uninterpreted_option_size(); +} +inline void MethodOptions::clear_uninterpreted_option() { + _impl_.uninterpreted_option_.Clear(); +} +inline ::PROTOBUF_NAMESPACE_ID::UninterpretedOption* MethodOptions::mutable_uninterpreted_option(int index) { + // @@protoc_insertion_point(field_mutable:google.protobuf.MethodOptions.uninterpreted_option) + return _impl_.uninterpreted_option_.Mutable(index); +} +inline ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::UninterpretedOption >* +MethodOptions::mutable_uninterpreted_option() { + // @@protoc_insertion_point(field_mutable_list:google.protobuf.MethodOptions.uninterpreted_option) + return &_impl_.uninterpreted_option_; +} +inline const ::PROTOBUF_NAMESPACE_ID::UninterpretedOption& MethodOptions::_internal_uninterpreted_option(int index) const { + return _impl_.uninterpreted_option_.Get(index); +} +inline const ::PROTOBUF_NAMESPACE_ID::UninterpretedOption& MethodOptions::uninterpreted_option(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.MethodOptions.uninterpreted_option) + return _internal_uninterpreted_option(index); +} +inline ::PROTOBUF_NAMESPACE_ID::UninterpretedOption* MethodOptions::_internal_add_uninterpreted_option() { + return _impl_.uninterpreted_option_.Add(); +} +inline ::PROTOBUF_NAMESPACE_ID::UninterpretedOption* MethodOptions::add_uninterpreted_option() { + ::PROTOBUF_NAMESPACE_ID::UninterpretedOption* _add = _internal_add_uninterpreted_option(); + // @@protoc_insertion_point(field_add:google.protobuf.MethodOptions.uninterpreted_option) + return _add; +} +inline const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::UninterpretedOption >& +MethodOptions::uninterpreted_option() const { + // @@protoc_insertion_point(field_list:google.protobuf.MethodOptions.uninterpreted_option) + return _impl_.uninterpreted_option_; +} + +// ------------------------------------------------------------------- + +// UninterpretedOption_NamePart + +// required string name_part = 1; +inline bool UninterpretedOption_NamePart::_internal_has_name_part() const { + bool value = (_impl_._has_bits_[0] & 0x00000001u) != 0; + return value; +} +inline bool UninterpretedOption_NamePart::has_name_part() const { + return _internal_has_name_part(); +} +inline void UninterpretedOption_NamePart::clear_name_part() { + _impl_.name_part_.ClearToEmpty(); + _impl_._has_bits_[0] &= ~0x00000001u; +} +inline const std::string& UninterpretedOption_NamePart::name_part() const { + // @@protoc_insertion_point(field_get:google.protobuf.UninterpretedOption.NamePart.name_part) + return _internal_name_part(); +} +template <typename ArgT0, typename... ArgT> +inline PROTOBUF_ALWAYS_INLINE +void UninterpretedOption_NamePart::set_name_part(ArgT0&& arg0, ArgT... args) { + _impl_._has_bits_[0] |= 0x00000001u; + _impl_.name_part_.Set(static_cast<ArgT0 &&>(arg0), args..., GetArenaForAllocation()); + // @@protoc_insertion_point(field_set:google.protobuf.UninterpretedOption.NamePart.name_part) +} +inline std::string* UninterpretedOption_NamePart::mutable_name_part() { + std::string* _s = _internal_mutable_name_part(); + // @@protoc_insertion_point(field_mutable:google.protobuf.UninterpretedOption.NamePart.name_part) + return _s; +} +inline const std::string& UninterpretedOption_NamePart::_internal_name_part() const { + return _impl_.name_part_.Get(); +} +inline void UninterpretedOption_NamePart::_internal_set_name_part(const std::string& value) { + _impl_._has_bits_[0] |= 0x00000001u; + _impl_.name_part_.Set(value, GetArenaForAllocation()); +} +inline std::string* UninterpretedOption_NamePart::_internal_mutable_name_part() { + _impl_._has_bits_[0] |= 0x00000001u; + return _impl_.name_part_.Mutable(GetArenaForAllocation()); +} +inline std::string* UninterpretedOption_NamePart::release_name_part() { + // @@protoc_insertion_point(field_release:google.protobuf.UninterpretedOption.NamePart.name_part) + if (!_internal_has_name_part()) { + return nullptr; + } + _impl_._has_bits_[0] &= ~0x00000001u; + auto* p = _impl_.name_part_.Release(); +#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (_impl_.name_part_.IsDefault()) { + _impl_.name_part_.Set("", GetArenaForAllocation()); + } +#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + return p; +} +inline void UninterpretedOption_NamePart::set_allocated_name_part(std::string* name_part) { + if (name_part != nullptr) { + _impl_._has_bits_[0] |= 0x00000001u; + } else { + _impl_._has_bits_[0] &= ~0x00000001u; + } + _impl_.name_part_.SetAllocated(name_part, GetArenaForAllocation()); +#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (_impl_.name_part_.IsDefault()) { + _impl_.name_part_.Set("", GetArenaForAllocation()); + } +#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + // @@protoc_insertion_point(field_set_allocated:google.protobuf.UninterpretedOption.NamePart.name_part) +} + +// required bool is_extension = 2; +inline bool UninterpretedOption_NamePart::_internal_has_is_extension() const { + bool value = (_impl_._has_bits_[0] & 0x00000002u) != 0; + return value; +} +inline bool UninterpretedOption_NamePart::has_is_extension() const { + return _internal_has_is_extension(); +} +inline void UninterpretedOption_NamePart::clear_is_extension() { + _impl_.is_extension_ = false; + _impl_._has_bits_[0] &= ~0x00000002u; +} +inline bool UninterpretedOption_NamePart::_internal_is_extension() const { + return _impl_.is_extension_; +} +inline bool UninterpretedOption_NamePart::is_extension() const { + // @@protoc_insertion_point(field_get:google.protobuf.UninterpretedOption.NamePart.is_extension) + return _internal_is_extension(); +} +inline void UninterpretedOption_NamePart::_internal_set_is_extension(bool value) { + _impl_._has_bits_[0] |= 0x00000002u; + _impl_.is_extension_ = value; +} +inline void UninterpretedOption_NamePart::set_is_extension(bool value) { + _internal_set_is_extension(value); + // @@protoc_insertion_point(field_set:google.protobuf.UninterpretedOption.NamePart.is_extension) +} + +// ------------------------------------------------------------------- + +// UninterpretedOption + +// repeated .google.protobuf.UninterpretedOption.NamePart name = 2; +inline int UninterpretedOption::_internal_name_size() const { + return _impl_.name_.size(); +} +inline int UninterpretedOption::name_size() const { + return _internal_name_size(); +} +inline void UninterpretedOption::clear_name() { + _impl_.name_.Clear(); +} +inline ::PROTOBUF_NAMESPACE_ID::UninterpretedOption_NamePart* UninterpretedOption::mutable_name(int index) { + // @@protoc_insertion_point(field_mutable:google.protobuf.UninterpretedOption.name) + return _impl_.name_.Mutable(index); +} +inline ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::UninterpretedOption_NamePart >* +UninterpretedOption::mutable_name() { + // @@protoc_insertion_point(field_mutable_list:google.protobuf.UninterpretedOption.name) + return &_impl_.name_; +} +inline const ::PROTOBUF_NAMESPACE_ID::UninterpretedOption_NamePart& UninterpretedOption::_internal_name(int index) const { + return _impl_.name_.Get(index); +} +inline const ::PROTOBUF_NAMESPACE_ID::UninterpretedOption_NamePart& UninterpretedOption::name(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.UninterpretedOption.name) + return _internal_name(index); +} +inline ::PROTOBUF_NAMESPACE_ID::UninterpretedOption_NamePart* UninterpretedOption::_internal_add_name() { + return _impl_.name_.Add(); +} +inline ::PROTOBUF_NAMESPACE_ID::UninterpretedOption_NamePart* UninterpretedOption::add_name() { + ::PROTOBUF_NAMESPACE_ID::UninterpretedOption_NamePart* _add = _internal_add_name(); + // @@protoc_insertion_point(field_add:google.protobuf.UninterpretedOption.name) + return _add; +} +inline const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::UninterpretedOption_NamePart >& +UninterpretedOption::name() const { + // @@protoc_insertion_point(field_list:google.protobuf.UninterpretedOption.name) + return _impl_.name_; +} + +// optional string identifier_value = 3; +inline bool UninterpretedOption::_internal_has_identifier_value() const { + bool value = (_impl_._has_bits_[0] & 0x00000001u) != 0; + return value; +} +inline bool UninterpretedOption::has_identifier_value() const { + return _internal_has_identifier_value(); +} +inline void UninterpretedOption::clear_identifier_value() { + _impl_.identifier_value_.ClearToEmpty(); + _impl_._has_bits_[0] &= ~0x00000001u; +} +inline const std::string& UninterpretedOption::identifier_value() const { + // @@protoc_insertion_point(field_get:google.protobuf.UninterpretedOption.identifier_value) + return _internal_identifier_value(); +} +template <typename ArgT0, typename... ArgT> +inline PROTOBUF_ALWAYS_INLINE +void UninterpretedOption::set_identifier_value(ArgT0&& arg0, ArgT... args) { + _impl_._has_bits_[0] |= 0x00000001u; + _impl_.identifier_value_.Set(static_cast<ArgT0 &&>(arg0), args..., GetArenaForAllocation()); + // @@protoc_insertion_point(field_set:google.protobuf.UninterpretedOption.identifier_value) +} +inline std::string* UninterpretedOption::mutable_identifier_value() { + std::string* _s = _internal_mutable_identifier_value(); + // @@protoc_insertion_point(field_mutable:google.protobuf.UninterpretedOption.identifier_value) + return _s; +} +inline const std::string& UninterpretedOption::_internal_identifier_value() const { + return _impl_.identifier_value_.Get(); +} +inline void UninterpretedOption::_internal_set_identifier_value(const std::string& value) { + _impl_._has_bits_[0] |= 0x00000001u; + _impl_.identifier_value_.Set(value, GetArenaForAllocation()); +} +inline std::string* UninterpretedOption::_internal_mutable_identifier_value() { + _impl_._has_bits_[0] |= 0x00000001u; + return _impl_.identifier_value_.Mutable(GetArenaForAllocation()); +} +inline std::string* UninterpretedOption::release_identifier_value() { + // @@protoc_insertion_point(field_release:google.protobuf.UninterpretedOption.identifier_value) + if (!_internal_has_identifier_value()) { + return nullptr; + } + _impl_._has_bits_[0] &= ~0x00000001u; + auto* p = _impl_.identifier_value_.Release(); +#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (_impl_.identifier_value_.IsDefault()) { + _impl_.identifier_value_.Set("", GetArenaForAllocation()); + } +#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + return p; +} +inline void UninterpretedOption::set_allocated_identifier_value(std::string* identifier_value) { + if (identifier_value != nullptr) { + _impl_._has_bits_[0] |= 0x00000001u; + } else { + _impl_._has_bits_[0] &= ~0x00000001u; + } + _impl_.identifier_value_.SetAllocated(identifier_value, GetArenaForAllocation()); +#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (_impl_.identifier_value_.IsDefault()) { + _impl_.identifier_value_.Set("", GetArenaForAllocation()); + } +#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + // @@protoc_insertion_point(field_set_allocated:google.protobuf.UninterpretedOption.identifier_value) +} + +// optional uint64 positive_int_value = 4; +inline bool UninterpretedOption::_internal_has_positive_int_value() const { + bool value = (_impl_._has_bits_[0] & 0x00000008u) != 0; + return value; +} +inline bool UninterpretedOption::has_positive_int_value() const { + return _internal_has_positive_int_value(); +} +inline void UninterpretedOption::clear_positive_int_value() { + _impl_.positive_int_value_ = uint64_t{0u}; + _impl_._has_bits_[0] &= ~0x00000008u; +} +inline uint64_t UninterpretedOption::_internal_positive_int_value() const { + return _impl_.positive_int_value_; +} +inline uint64_t UninterpretedOption::positive_int_value() const { + // @@protoc_insertion_point(field_get:google.protobuf.UninterpretedOption.positive_int_value) + return _internal_positive_int_value(); +} +inline void UninterpretedOption::_internal_set_positive_int_value(uint64_t value) { + _impl_._has_bits_[0] |= 0x00000008u; + _impl_.positive_int_value_ = value; +} +inline void UninterpretedOption::set_positive_int_value(uint64_t value) { + _internal_set_positive_int_value(value); + // @@protoc_insertion_point(field_set:google.protobuf.UninterpretedOption.positive_int_value) +} + +// optional int64 negative_int_value = 5; +inline bool UninterpretedOption::_internal_has_negative_int_value() const { + bool value = (_impl_._has_bits_[0] & 0x00000010u) != 0; + return value; +} +inline bool UninterpretedOption::has_negative_int_value() const { + return _internal_has_negative_int_value(); +} +inline void UninterpretedOption::clear_negative_int_value() { + _impl_.negative_int_value_ = int64_t{0}; + _impl_._has_bits_[0] &= ~0x00000010u; +} +inline int64_t UninterpretedOption::_internal_negative_int_value() const { + return _impl_.negative_int_value_; +} +inline int64_t UninterpretedOption::negative_int_value() const { + // @@protoc_insertion_point(field_get:google.protobuf.UninterpretedOption.negative_int_value) + return _internal_negative_int_value(); +} +inline void UninterpretedOption::_internal_set_negative_int_value(int64_t value) { + _impl_._has_bits_[0] |= 0x00000010u; + _impl_.negative_int_value_ = value; +} +inline void UninterpretedOption::set_negative_int_value(int64_t value) { + _internal_set_negative_int_value(value); + // @@protoc_insertion_point(field_set:google.protobuf.UninterpretedOption.negative_int_value) +} + +// optional double double_value = 6; +inline bool UninterpretedOption::_internal_has_double_value() const { + bool value = (_impl_._has_bits_[0] & 0x00000020u) != 0; + return value; +} +inline bool UninterpretedOption::has_double_value() const { + return _internal_has_double_value(); +} +inline void UninterpretedOption::clear_double_value() { + _impl_.double_value_ = 0; + _impl_._has_bits_[0] &= ~0x00000020u; +} +inline double UninterpretedOption::_internal_double_value() const { + return _impl_.double_value_; +} +inline double UninterpretedOption::double_value() const { + // @@protoc_insertion_point(field_get:google.protobuf.UninterpretedOption.double_value) + return _internal_double_value(); +} +inline void UninterpretedOption::_internal_set_double_value(double value) { + _impl_._has_bits_[0] |= 0x00000020u; + _impl_.double_value_ = value; +} +inline void UninterpretedOption::set_double_value(double value) { + _internal_set_double_value(value); + // @@protoc_insertion_point(field_set:google.protobuf.UninterpretedOption.double_value) +} + +// optional bytes string_value = 7; +inline bool UninterpretedOption::_internal_has_string_value() const { + bool value = (_impl_._has_bits_[0] & 0x00000002u) != 0; + return value; +} +inline bool UninterpretedOption::has_string_value() const { + return _internal_has_string_value(); +} +inline void UninterpretedOption::clear_string_value() { + _impl_.string_value_.ClearToEmpty(); + _impl_._has_bits_[0] &= ~0x00000002u; +} +inline const std::string& UninterpretedOption::string_value() const { + // @@protoc_insertion_point(field_get:google.protobuf.UninterpretedOption.string_value) + return _internal_string_value(); +} +template <typename ArgT0, typename... ArgT> +inline PROTOBUF_ALWAYS_INLINE +void UninterpretedOption::set_string_value(ArgT0&& arg0, ArgT... args) { + _impl_._has_bits_[0] |= 0x00000002u; + _impl_.string_value_.SetBytes(static_cast<ArgT0 &&>(arg0), args..., GetArenaForAllocation()); + // @@protoc_insertion_point(field_set:google.protobuf.UninterpretedOption.string_value) +} +inline std::string* UninterpretedOption::mutable_string_value() { + std::string* _s = _internal_mutable_string_value(); + // @@protoc_insertion_point(field_mutable:google.protobuf.UninterpretedOption.string_value) + return _s; +} +inline const std::string& UninterpretedOption::_internal_string_value() const { + return _impl_.string_value_.Get(); +} +inline void UninterpretedOption::_internal_set_string_value(const std::string& value) { + _impl_._has_bits_[0] |= 0x00000002u; + _impl_.string_value_.Set(value, GetArenaForAllocation()); +} +inline std::string* UninterpretedOption::_internal_mutable_string_value() { + _impl_._has_bits_[0] |= 0x00000002u; + return _impl_.string_value_.Mutable(GetArenaForAllocation()); +} +inline std::string* UninterpretedOption::release_string_value() { + // @@protoc_insertion_point(field_release:google.protobuf.UninterpretedOption.string_value) + if (!_internal_has_string_value()) { + return nullptr; + } + _impl_._has_bits_[0] &= ~0x00000002u; + auto* p = _impl_.string_value_.Release(); +#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (_impl_.string_value_.IsDefault()) { + _impl_.string_value_.Set("", GetArenaForAllocation()); + } +#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + return p; +} +inline void UninterpretedOption::set_allocated_string_value(std::string* string_value) { + if (string_value != nullptr) { + _impl_._has_bits_[0] |= 0x00000002u; + } else { + _impl_._has_bits_[0] &= ~0x00000002u; + } + _impl_.string_value_.SetAllocated(string_value, GetArenaForAllocation()); +#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (_impl_.string_value_.IsDefault()) { + _impl_.string_value_.Set("", GetArenaForAllocation()); + } +#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + // @@protoc_insertion_point(field_set_allocated:google.protobuf.UninterpretedOption.string_value) +} + +// optional string aggregate_value = 8; +inline bool UninterpretedOption::_internal_has_aggregate_value() const { + bool value = (_impl_._has_bits_[0] & 0x00000004u) != 0; + return value; +} +inline bool UninterpretedOption::has_aggregate_value() const { + return _internal_has_aggregate_value(); +} +inline void UninterpretedOption::clear_aggregate_value() { + _impl_.aggregate_value_.ClearToEmpty(); + _impl_._has_bits_[0] &= ~0x00000004u; +} +inline const std::string& UninterpretedOption::aggregate_value() const { + // @@protoc_insertion_point(field_get:google.protobuf.UninterpretedOption.aggregate_value) + return _internal_aggregate_value(); +} +template <typename ArgT0, typename... ArgT> +inline PROTOBUF_ALWAYS_INLINE +void UninterpretedOption::set_aggregate_value(ArgT0&& arg0, ArgT... args) { + _impl_._has_bits_[0] |= 0x00000004u; + _impl_.aggregate_value_.Set(static_cast<ArgT0 &&>(arg0), args..., GetArenaForAllocation()); + // @@protoc_insertion_point(field_set:google.protobuf.UninterpretedOption.aggregate_value) +} +inline std::string* UninterpretedOption::mutable_aggregate_value() { + std::string* _s = _internal_mutable_aggregate_value(); + // @@protoc_insertion_point(field_mutable:google.protobuf.UninterpretedOption.aggregate_value) + return _s; +} +inline const std::string& UninterpretedOption::_internal_aggregate_value() const { + return _impl_.aggregate_value_.Get(); +} +inline void UninterpretedOption::_internal_set_aggregate_value(const std::string& value) { + _impl_._has_bits_[0] |= 0x00000004u; + _impl_.aggregate_value_.Set(value, GetArenaForAllocation()); +} +inline std::string* UninterpretedOption::_internal_mutable_aggregate_value() { + _impl_._has_bits_[0] |= 0x00000004u; + return _impl_.aggregate_value_.Mutable(GetArenaForAllocation()); +} +inline std::string* UninterpretedOption::release_aggregate_value() { + // @@protoc_insertion_point(field_release:google.protobuf.UninterpretedOption.aggregate_value) + if (!_internal_has_aggregate_value()) { + return nullptr; + } + _impl_._has_bits_[0] &= ~0x00000004u; + auto* p = _impl_.aggregate_value_.Release(); +#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (_impl_.aggregate_value_.IsDefault()) { + _impl_.aggregate_value_.Set("", GetArenaForAllocation()); + } +#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + return p; +} +inline void UninterpretedOption::set_allocated_aggregate_value(std::string* aggregate_value) { + if (aggregate_value != nullptr) { + _impl_._has_bits_[0] |= 0x00000004u; + } else { + _impl_._has_bits_[0] &= ~0x00000004u; + } + _impl_.aggregate_value_.SetAllocated(aggregate_value, GetArenaForAllocation()); +#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (_impl_.aggregate_value_.IsDefault()) { + _impl_.aggregate_value_.Set("", GetArenaForAllocation()); + } +#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + // @@protoc_insertion_point(field_set_allocated:google.protobuf.UninterpretedOption.aggregate_value) +} + +// ------------------------------------------------------------------- + +// SourceCodeInfo_Location + +// repeated int32 path = 1 [packed = true]; +inline int SourceCodeInfo_Location::_internal_path_size() const { + return _impl_.path_.size(); +} +inline int SourceCodeInfo_Location::path_size() const { + return _internal_path_size(); +} +inline void SourceCodeInfo_Location::clear_path() { + _impl_.path_.Clear(); +} +inline int32_t SourceCodeInfo_Location::_internal_path(int index) const { + return _impl_.path_.Get(index); +} +inline int32_t SourceCodeInfo_Location::path(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.SourceCodeInfo.Location.path) + return _internal_path(index); +} +inline void SourceCodeInfo_Location::set_path(int index, int32_t value) { + _impl_.path_.Set(index, value); + // @@protoc_insertion_point(field_set:google.protobuf.SourceCodeInfo.Location.path) +} +inline void SourceCodeInfo_Location::_internal_add_path(int32_t value) { + _impl_.path_.Add(value); +} +inline void SourceCodeInfo_Location::add_path(int32_t value) { + _internal_add_path(value); + // @@protoc_insertion_point(field_add:google.protobuf.SourceCodeInfo.Location.path) +} +inline const ::PROTOBUF_NAMESPACE_ID::RepeatedField< int32_t >& +SourceCodeInfo_Location::_internal_path() const { + return _impl_.path_; +} +inline const ::PROTOBUF_NAMESPACE_ID::RepeatedField< int32_t >& +SourceCodeInfo_Location::path() const { + // @@protoc_insertion_point(field_list:google.protobuf.SourceCodeInfo.Location.path) + return _internal_path(); +} +inline ::PROTOBUF_NAMESPACE_ID::RepeatedField< int32_t >* +SourceCodeInfo_Location::_internal_mutable_path() { + return &_impl_.path_; +} +inline ::PROTOBUF_NAMESPACE_ID::RepeatedField< int32_t >* +SourceCodeInfo_Location::mutable_path() { + // @@protoc_insertion_point(field_mutable_list:google.protobuf.SourceCodeInfo.Location.path) + return _internal_mutable_path(); +} + +// repeated int32 span = 2 [packed = true]; +inline int SourceCodeInfo_Location::_internal_span_size() const { + return _impl_.span_.size(); +} +inline int SourceCodeInfo_Location::span_size() const { + return _internal_span_size(); +} +inline void SourceCodeInfo_Location::clear_span() { + _impl_.span_.Clear(); +} +inline int32_t SourceCodeInfo_Location::_internal_span(int index) const { + return _impl_.span_.Get(index); +} +inline int32_t SourceCodeInfo_Location::span(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.SourceCodeInfo.Location.span) + return _internal_span(index); +} +inline void SourceCodeInfo_Location::set_span(int index, int32_t value) { + _impl_.span_.Set(index, value); + // @@protoc_insertion_point(field_set:google.protobuf.SourceCodeInfo.Location.span) +} +inline void SourceCodeInfo_Location::_internal_add_span(int32_t value) { + _impl_.span_.Add(value); +} +inline void SourceCodeInfo_Location::add_span(int32_t value) { + _internal_add_span(value); + // @@protoc_insertion_point(field_add:google.protobuf.SourceCodeInfo.Location.span) +} +inline const ::PROTOBUF_NAMESPACE_ID::RepeatedField< int32_t >& +SourceCodeInfo_Location::_internal_span() const { + return _impl_.span_; +} +inline const ::PROTOBUF_NAMESPACE_ID::RepeatedField< int32_t >& +SourceCodeInfo_Location::span() const { + // @@protoc_insertion_point(field_list:google.protobuf.SourceCodeInfo.Location.span) + return _internal_span(); +} +inline ::PROTOBUF_NAMESPACE_ID::RepeatedField< int32_t >* +SourceCodeInfo_Location::_internal_mutable_span() { + return &_impl_.span_; +} +inline ::PROTOBUF_NAMESPACE_ID::RepeatedField< int32_t >* +SourceCodeInfo_Location::mutable_span() { + // @@protoc_insertion_point(field_mutable_list:google.protobuf.SourceCodeInfo.Location.span) + return _internal_mutable_span(); +} + +// optional string leading_comments = 3; +inline bool SourceCodeInfo_Location::_internal_has_leading_comments() const { + bool value = (_impl_._has_bits_[0] & 0x00000001u) != 0; + return value; +} +inline bool SourceCodeInfo_Location::has_leading_comments() const { + return _internal_has_leading_comments(); +} +inline void SourceCodeInfo_Location::clear_leading_comments() { + _impl_.leading_comments_.ClearToEmpty(); + _impl_._has_bits_[0] &= ~0x00000001u; +} +inline const std::string& SourceCodeInfo_Location::leading_comments() const { + // @@protoc_insertion_point(field_get:google.protobuf.SourceCodeInfo.Location.leading_comments) + return _internal_leading_comments(); +} +template <typename ArgT0, typename... ArgT> +inline PROTOBUF_ALWAYS_INLINE +void SourceCodeInfo_Location::set_leading_comments(ArgT0&& arg0, ArgT... args) { + _impl_._has_bits_[0] |= 0x00000001u; + _impl_.leading_comments_.Set(static_cast<ArgT0 &&>(arg0), args..., GetArenaForAllocation()); + // @@protoc_insertion_point(field_set:google.protobuf.SourceCodeInfo.Location.leading_comments) +} +inline std::string* SourceCodeInfo_Location::mutable_leading_comments() { + std::string* _s = _internal_mutable_leading_comments(); + // @@protoc_insertion_point(field_mutable:google.protobuf.SourceCodeInfo.Location.leading_comments) + return _s; +} +inline const std::string& SourceCodeInfo_Location::_internal_leading_comments() const { + return _impl_.leading_comments_.Get(); +} +inline void SourceCodeInfo_Location::_internal_set_leading_comments(const std::string& value) { + _impl_._has_bits_[0] |= 0x00000001u; + _impl_.leading_comments_.Set(value, GetArenaForAllocation()); +} +inline std::string* SourceCodeInfo_Location::_internal_mutable_leading_comments() { + _impl_._has_bits_[0] |= 0x00000001u; + return _impl_.leading_comments_.Mutable(GetArenaForAllocation()); +} +inline std::string* SourceCodeInfo_Location::release_leading_comments() { + // @@protoc_insertion_point(field_release:google.protobuf.SourceCodeInfo.Location.leading_comments) + if (!_internal_has_leading_comments()) { + return nullptr; + } + _impl_._has_bits_[0] &= ~0x00000001u; + auto* p = _impl_.leading_comments_.Release(); +#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (_impl_.leading_comments_.IsDefault()) { + _impl_.leading_comments_.Set("", GetArenaForAllocation()); + } +#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + return p; +} +inline void SourceCodeInfo_Location::set_allocated_leading_comments(std::string* leading_comments) { + if (leading_comments != nullptr) { + _impl_._has_bits_[0] |= 0x00000001u; + } else { + _impl_._has_bits_[0] &= ~0x00000001u; + } + _impl_.leading_comments_.SetAllocated(leading_comments, GetArenaForAllocation()); +#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (_impl_.leading_comments_.IsDefault()) { + _impl_.leading_comments_.Set("", GetArenaForAllocation()); + } +#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + // @@protoc_insertion_point(field_set_allocated:google.protobuf.SourceCodeInfo.Location.leading_comments) +} + +// optional string trailing_comments = 4; +inline bool SourceCodeInfo_Location::_internal_has_trailing_comments() const { + bool value = (_impl_._has_bits_[0] & 0x00000002u) != 0; + return value; +} +inline bool SourceCodeInfo_Location::has_trailing_comments() const { + return _internal_has_trailing_comments(); +} +inline void SourceCodeInfo_Location::clear_trailing_comments() { + _impl_.trailing_comments_.ClearToEmpty(); + _impl_._has_bits_[0] &= ~0x00000002u; +} +inline const std::string& SourceCodeInfo_Location::trailing_comments() const { + // @@protoc_insertion_point(field_get:google.protobuf.SourceCodeInfo.Location.trailing_comments) + return _internal_trailing_comments(); +} +template <typename ArgT0, typename... ArgT> +inline PROTOBUF_ALWAYS_INLINE +void SourceCodeInfo_Location::set_trailing_comments(ArgT0&& arg0, ArgT... args) { + _impl_._has_bits_[0] |= 0x00000002u; + _impl_.trailing_comments_.Set(static_cast<ArgT0 &&>(arg0), args..., GetArenaForAllocation()); + // @@protoc_insertion_point(field_set:google.protobuf.SourceCodeInfo.Location.trailing_comments) +} +inline std::string* SourceCodeInfo_Location::mutable_trailing_comments() { + std::string* _s = _internal_mutable_trailing_comments(); + // @@protoc_insertion_point(field_mutable:google.protobuf.SourceCodeInfo.Location.trailing_comments) + return _s; +} +inline const std::string& SourceCodeInfo_Location::_internal_trailing_comments() const { + return _impl_.trailing_comments_.Get(); +} +inline void SourceCodeInfo_Location::_internal_set_trailing_comments(const std::string& value) { + _impl_._has_bits_[0] |= 0x00000002u; + _impl_.trailing_comments_.Set(value, GetArenaForAllocation()); +} +inline std::string* SourceCodeInfo_Location::_internal_mutable_trailing_comments() { + _impl_._has_bits_[0] |= 0x00000002u; + return _impl_.trailing_comments_.Mutable(GetArenaForAllocation()); +} +inline std::string* SourceCodeInfo_Location::release_trailing_comments() { + // @@protoc_insertion_point(field_release:google.protobuf.SourceCodeInfo.Location.trailing_comments) + if (!_internal_has_trailing_comments()) { + return nullptr; + } + _impl_._has_bits_[0] &= ~0x00000002u; + auto* p = _impl_.trailing_comments_.Release(); +#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (_impl_.trailing_comments_.IsDefault()) { + _impl_.trailing_comments_.Set("", GetArenaForAllocation()); + } +#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + return p; +} +inline void SourceCodeInfo_Location::set_allocated_trailing_comments(std::string* trailing_comments) { + if (trailing_comments != nullptr) { + _impl_._has_bits_[0] |= 0x00000002u; + } else { + _impl_._has_bits_[0] &= ~0x00000002u; + } + _impl_.trailing_comments_.SetAllocated(trailing_comments, GetArenaForAllocation()); +#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (_impl_.trailing_comments_.IsDefault()) { + _impl_.trailing_comments_.Set("", GetArenaForAllocation()); + } +#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + // @@protoc_insertion_point(field_set_allocated:google.protobuf.SourceCodeInfo.Location.trailing_comments) +} + +// repeated string leading_detached_comments = 6; +inline int SourceCodeInfo_Location::_internal_leading_detached_comments_size() const { + return _impl_.leading_detached_comments_.size(); +} +inline int SourceCodeInfo_Location::leading_detached_comments_size() const { + return _internal_leading_detached_comments_size(); +} +inline void SourceCodeInfo_Location::clear_leading_detached_comments() { + _impl_.leading_detached_comments_.Clear(); +} +inline std::string* SourceCodeInfo_Location::add_leading_detached_comments() { + std::string* _s = _internal_add_leading_detached_comments(); + // @@protoc_insertion_point(field_add_mutable:google.protobuf.SourceCodeInfo.Location.leading_detached_comments) + return _s; +} +inline const std::string& SourceCodeInfo_Location::_internal_leading_detached_comments(int index) const { + return _impl_.leading_detached_comments_.Get(index); +} +inline const std::string& SourceCodeInfo_Location::leading_detached_comments(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.SourceCodeInfo.Location.leading_detached_comments) + return _internal_leading_detached_comments(index); +} +inline std::string* SourceCodeInfo_Location::mutable_leading_detached_comments(int index) { + // @@protoc_insertion_point(field_mutable:google.protobuf.SourceCodeInfo.Location.leading_detached_comments) + return _impl_.leading_detached_comments_.Mutable(index); +} +inline void SourceCodeInfo_Location::set_leading_detached_comments(int index, const std::string& value) { + _impl_.leading_detached_comments_.Mutable(index)->assign(value); + // @@protoc_insertion_point(field_set:google.protobuf.SourceCodeInfo.Location.leading_detached_comments) +} +inline void SourceCodeInfo_Location::set_leading_detached_comments(int index, std::string&& value) { + _impl_.leading_detached_comments_.Mutable(index)->assign(std::move(value)); + // @@protoc_insertion_point(field_set:google.protobuf.SourceCodeInfo.Location.leading_detached_comments) +} +inline void SourceCodeInfo_Location::set_leading_detached_comments(int index, const char* value) { + GOOGLE_DCHECK(value != nullptr); + _impl_.leading_detached_comments_.Mutable(index)->assign(value); + // @@protoc_insertion_point(field_set_char:google.protobuf.SourceCodeInfo.Location.leading_detached_comments) +} +inline void SourceCodeInfo_Location::set_leading_detached_comments(int index, const char* value, size_t size) { + _impl_.leading_detached_comments_.Mutable(index)->assign( + reinterpret_cast<const char*>(value), size); + // @@protoc_insertion_point(field_set_pointer:google.protobuf.SourceCodeInfo.Location.leading_detached_comments) +} +inline std::string* SourceCodeInfo_Location::_internal_add_leading_detached_comments() { + return _impl_.leading_detached_comments_.Add(); +} +inline void SourceCodeInfo_Location::add_leading_detached_comments(const std::string& value) { + _impl_.leading_detached_comments_.Add()->assign(value); + // @@protoc_insertion_point(field_add:google.protobuf.SourceCodeInfo.Location.leading_detached_comments) +} +inline void SourceCodeInfo_Location::add_leading_detached_comments(std::string&& value) { + _impl_.leading_detached_comments_.Add(std::move(value)); + // @@protoc_insertion_point(field_add:google.protobuf.SourceCodeInfo.Location.leading_detached_comments) +} +inline void SourceCodeInfo_Location::add_leading_detached_comments(const char* value) { + GOOGLE_DCHECK(value != nullptr); + _impl_.leading_detached_comments_.Add()->assign(value); + // @@protoc_insertion_point(field_add_char:google.protobuf.SourceCodeInfo.Location.leading_detached_comments) +} +inline void SourceCodeInfo_Location::add_leading_detached_comments(const char* value, size_t size) { + _impl_.leading_detached_comments_.Add()->assign(reinterpret_cast<const char*>(value), size); + // @@protoc_insertion_point(field_add_pointer:google.protobuf.SourceCodeInfo.Location.leading_detached_comments) +} +inline const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField<std::string>& +SourceCodeInfo_Location::leading_detached_comments() const { + // @@protoc_insertion_point(field_list:google.protobuf.SourceCodeInfo.Location.leading_detached_comments) + return _impl_.leading_detached_comments_; +} +inline ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField<std::string>* +SourceCodeInfo_Location::mutable_leading_detached_comments() { + // @@protoc_insertion_point(field_mutable_list:google.protobuf.SourceCodeInfo.Location.leading_detached_comments) + return &_impl_.leading_detached_comments_; +} + +// ------------------------------------------------------------------- + +// SourceCodeInfo + +// repeated .google.protobuf.SourceCodeInfo.Location location = 1; +inline int SourceCodeInfo::_internal_location_size() const { + return _impl_.location_.size(); +} +inline int SourceCodeInfo::location_size() const { + return _internal_location_size(); +} +inline void SourceCodeInfo::clear_location() { + _impl_.location_.Clear(); +} +inline ::PROTOBUF_NAMESPACE_ID::SourceCodeInfo_Location* SourceCodeInfo::mutable_location(int index) { + // @@protoc_insertion_point(field_mutable:google.protobuf.SourceCodeInfo.location) + return _impl_.location_.Mutable(index); +} +inline ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::SourceCodeInfo_Location >* +SourceCodeInfo::mutable_location() { + // @@protoc_insertion_point(field_mutable_list:google.protobuf.SourceCodeInfo.location) + return &_impl_.location_; +} +inline const ::PROTOBUF_NAMESPACE_ID::SourceCodeInfo_Location& SourceCodeInfo::_internal_location(int index) const { + return _impl_.location_.Get(index); +} +inline const ::PROTOBUF_NAMESPACE_ID::SourceCodeInfo_Location& SourceCodeInfo::location(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.SourceCodeInfo.location) + return _internal_location(index); +} +inline ::PROTOBUF_NAMESPACE_ID::SourceCodeInfo_Location* SourceCodeInfo::_internal_add_location() { + return _impl_.location_.Add(); +} +inline ::PROTOBUF_NAMESPACE_ID::SourceCodeInfo_Location* SourceCodeInfo::add_location() { + ::PROTOBUF_NAMESPACE_ID::SourceCodeInfo_Location* _add = _internal_add_location(); + // @@protoc_insertion_point(field_add:google.protobuf.SourceCodeInfo.location) + return _add; +} +inline const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::SourceCodeInfo_Location >& +SourceCodeInfo::location() const { + // @@protoc_insertion_point(field_list:google.protobuf.SourceCodeInfo.location) + return _impl_.location_; +} + +// ------------------------------------------------------------------- + +// GeneratedCodeInfo_Annotation + +// repeated int32 path = 1 [packed = true]; +inline int GeneratedCodeInfo_Annotation::_internal_path_size() const { + return _impl_.path_.size(); +} +inline int GeneratedCodeInfo_Annotation::path_size() const { + return _internal_path_size(); +} +inline void GeneratedCodeInfo_Annotation::clear_path() { + _impl_.path_.Clear(); +} +inline int32_t GeneratedCodeInfo_Annotation::_internal_path(int index) const { + return _impl_.path_.Get(index); +} +inline int32_t GeneratedCodeInfo_Annotation::path(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.GeneratedCodeInfo.Annotation.path) + return _internal_path(index); +} +inline void GeneratedCodeInfo_Annotation::set_path(int index, int32_t value) { + _impl_.path_.Set(index, value); + // @@protoc_insertion_point(field_set:google.protobuf.GeneratedCodeInfo.Annotation.path) +} +inline void GeneratedCodeInfo_Annotation::_internal_add_path(int32_t value) { + _impl_.path_.Add(value); +} +inline void GeneratedCodeInfo_Annotation::add_path(int32_t value) { + _internal_add_path(value); + // @@protoc_insertion_point(field_add:google.protobuf.GeneratedCodeInfo.Annotation.path) +} +inline const ::PROTOBUF_NAMESPACE_ID::RepeatedField< int32_t >& +GeneratedCodeInfo_Annotation::_internal_path() const { + return _impl_.path_; +} +inline const ::PROTOBUF_NAMESPACE_ID::RepeatedField< int32_t >& +GeneratedCodeInfo_Annotation::path() const { + // @@protoc_insertion_point(field_list:google.protobuf.GeneratedCodeInfo.Annotation.path) + return _internal_path(); +} +inline ::PROTOBUF_NAMESPACE_ID::RepeatedField< int32_t >* +GeneratedCodeInfo_Annotation::_internal_mutable_path() { + return &_impl_.path_; +} +inline ::PROTOBUF_NAMESPACE_ID::RepeatedField< int32_t >* +GeneratedCodeInfo_Annotation::mutable_path() { + // @@protoc_insertion_point(field_mutable_list:google.protobuf.GeneratedCodeInfo.Annotation.path) + return _internal_mutable_path(); +} + +// optional string source_file = 2; +inline bool GeneratedCodeInfo_Annotation::_internal_has_source_file() const { + bool value = (_impl_._has_bits_[0] & 0x00000001u) != 0; + return value; +} +inline bool GeneratedCodeInfo_Annotation::has_source_file() const { + return _internal_has_source_file(); +} +inline void GeneratedCodeInfo_Annotation::clear_source_file() { + _impl_.source_file_.ClearToEmpty(); + _impl_._has_bits_[0] &= ~0x00000001u; +} +inline const std::string& GeneratedCodeInfo_Annotation::source_file() const { + // @@protoc_insertion_point(field_get:google.protobuf.GeneratedCodeInfo.Annotation.source_file) + return _internal_source_file(); +} +template <typename ArgT0, typename... ArgT> +inline PROTOBUF_ALWAYS_INLINE +void GeneratedCodeInfo_Annotation::set_source_file(ArgT0&& arg0, ArgT... args) { + _impl_._has_bits_[0] |= 0x00000001u; + _impl_.source_file_.Set(static_cast<ArgT0 &&>(arg0), args..., GetArenaForAllocation()); + // @@protoc_insertion_point(field_set:google.protobuf.GeneratedCodeInfo.Annotation.source_file) +} +inline std::string* GeneratedCodeInfo_Annotation::mutable_source_file() { + std::string* _s = _internal_mutable_source_file(); + // @@protoc_insertion_point(field_mutable:google.protobuf.GeneratedCodeInfo.Annotation.source_file) + return _s; +} +inline const std::string& GeneratedCodeInfo_Annotation::_internal_source_file() const { + return _impl_.source_file_.Get(); +} +inline void GeneratedCodeInfo_Annotation::_internal_set_source_file(const std::string& value) { + _impl_._has_bits_[0] |= 0x00000001u; + _impl_.source_file_.Set(value, GetArenaForAllocation()); +} +inline std::string* GeneratedCodeInfo_Annotation::_internal_mutable_source_file() { + _impl_._has_bits_[0] |= 0x00000001u; + return _impl_.source_file_.Mutable(GetArenaForAllocation()); +} +inline std::string* GeneratedCodeInfo_Annotation::release_source_file() { + // @@protoc_insertion_point(field_release:google.protobuf.GeneratedCodeInfo.Annotation.source_file) + if (!_internal_has_source_file()) { + return nullptr; + } + _impl_._has_bits_[0] &= ~0x00000001u; + auto* p = _impl_.source_file_.Release(); +#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (_impl_.source_file_.IsDefault()) { + _impl_.source_file_.Set("", GetArenaForAllocation()); + } +#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + return p; +} +inline void GeneratedCodeInfo_Annotation::set_allocated_source_file(std::string* source_file) { + if (source_file != nullptr) { + _impl_._has_bits_[0] |= 0x00000001u; + } else { + _impl_._has_bits_[0] &= ~0x00000001u; + } + _impl_.source_file_.SetAllocated(source_file, GetArenaForAllocation()); +#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (_impl_.source_file_.IsDefault()) { + _impl_.source_file_.Set("", GetArenaForAllocation()); + } +#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + // @@protoc_insertion_point(field_set_allocated:google.protobuf.GeneratedCodeInfo.Annotation.source_file) +} + +// optional int32 begin = 3; +inline bool GeneratedCodeInfo_Annotation::_internal_has_begin() const { + bool value = (_impl_._has_bits_[0] & 0x00000002u) != 0; + return value; +} +inline bool GeneratedCodeInfo_Annotation::has_begin() const { + return _internal_has_begin(); +} +inline void GeneratedCodeInfo_Annotation::clear_begin() { + _impl_.begin_ = 0; + _impl_._has_bits_[0] &= ~0x00000002u; +} +inline int32_t GeneratedCodeInfo_Annotation::_internal_begin() const { + return _impl_.begin_; +} +inline int32_t GeneratedCodeInfo_Annotation::begin() const { + // @@protoc_insertion_point(field_get:google.protobuf.GeneratedCodeInfo.Annotation.begin) + return _internal_begin(); +} +inline void GeneratedCodeInfo_Annotation::_internal_set_begin(int32_t value) { + _impl_._has_bits_[0] |= 0x00000002u; + _impl_.begin_ = value; +} +inline void GeneratedCodeInfo_Annotation::set_begin(int32_t value) { + _internal_set_begin(value); + // @@protoc_insertion_point(field_set:google.protobuf.GeneratedCodeInfo.Annotation.begin) +} + +// optional int32 end = 4; +inline bool GeneratedCodeInfo_Annotation::_internal_has_end() const { + bool value = (_impl_._has_bits_[0] & 0x00000004u) != 0; + return value; +} +inline bool GeneratedCodeInfo_Annotation::has_end() const { + return _internal_has_end(); +} +inline void GeneratedCodeInfo_Annotation::clear_end() { + _impl_.end_ = 0; + _impl_._has_bits_[0] &= ~0x00000004u; +} +inline int32_t GeneratedCodeInfo_Annotation::_internal_end() const { + return _impl_.end_; +} +inline int32_t GeneratedCodeInfo_Annotation::end() const { + // @@protoc_insertion_point(field_get:google.protobuf.GeneratedCodeInfo.Annotation.end) + return _internal_end(); +} +inline void GeneratedCodeInfo_Annotation::_internal_set_end(int32_t value) { + _impl_._has_bits_[0] |= 0x00000004u; + _impl_.end_ = value; +} +inline void GeneratedCodeInfo_Annotation::set_end(int32_t value) { + _internal_set_end(value); + // @@protoc_insertion_point(field_set:google.protobuf.GeneratedCodeInfo.Annotation.end) +} + +// ------------------------------------------------------------------- + +// GeneratedCodeInfo + +// repeated .google.protobuf.GeneratedCodeInfo.Annotation annotation = 1; +inline int GeneratedCodeInfo::_internal_annotation_size() const { + return _impl_.annotation_.size(); +} +inline int GeneratedCodeInfo::annotation_size() const { + return _internal_annotation_size(); +} +inline void GeneratedCodeInfo::clear_annotation() { + _impl_.annotation_.Clear(); +} +inline ::PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo_Annotation* GeneratedCodeInfo::mutable_annotation(int index) { + // @@protoc_insertion_point(field_mutable:google.protobuf.GeneratedCodeInfo.annotation) + return _impl_.annotation_.Mutable(index); +} +inline ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo_Annotation >* +GeneratedCodeInfo::mutable_annotation() { + // @@protoc_insertion_point(field_mutable_list:google.protobuf.GeneratedCodeInfo.annotation) + return &_impl_.annotation_; +} +inline const ::PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo_Annotation& GeneratedCodeInfo::_internal_annotation(int index) const { + return _impl_.annotation_.Get(index); +} +inline const ::PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo_Annotation& GeneratedCodeInfo::annotation(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.GeneratedCodeInfo.annotation) + return _internal_annotation(index); +} +inline ::PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo_Annotation* GeneratedCodeInfo::_internal_add_annotation() { + return _impl_.annotation_.Add(); +} +inline ::PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo_Annotation* GeneratedCodeInfo::add_annotation() { + ::PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo_Annotation* _add = _internal_add_annotation(); + // @@protoc_insertion_point(field_add:google.protobuf.GeneratedCodeInfo.annotation) + return _add; +} +inline const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo_Annotation >& +GeneratedCodeInfo::annotation() const { + // @@protoc_insertion_point(field_list:google.protobuf.GeneratedCodeInfo.annotation) + return _impl_.annotation_; +} + +#ifdef __GNUC__ + #pragma GCC diagnostic pop +#endif // __GNUC__ +// ------------------------------------------------------------------- + +// ------------------------------------------------------------------- + +// ------------------------------------------------------------------- + +// ------------------------------------------------------------------- + +// ------------------------------------------------------------------- + +// ------------------------------------------------------------------- + +// ------------------------------------------------------------------- + +// ------------------------------------------------------------------- + +// ------------------------------------------------------------------- + +// ------------------------------------------------------------------- + +// ------------------------------------------------------------------- + +// ------------------------------------------------------------------- + +// ------------------------------------------------------------------- + +// ------------------------------------------------------------------- + +// ------------------------------------------------------------------- + +// ------------------------------------------------------------------- + +// ------------------------------------------------------------------- + +// ------------------------------------------------------------------- + +// ------------------------------------------------------------------- + +// ------------------------------------------------------------------- + +// ------------------------------------------------------------------- + +// ------------------------------------------------------------------- + +// ------------------------------------------------------------------- + +// ------------------------------------------------------------------- + +// ------------------------------------------------------------------- + +// ------------------------------------------------------------------- + + +// @@protoc_insertion_point(namespace_scope) + +PROTOBUF_NAMESPACE_CLOSE + +PROTOBUF_NAMESPACE_OPEN + +template <> struct is_proto_enum< ::PROTOBUF_NAMESPACE_ID::FieldDescriptorProto_Type> : ::std::true_type {}; +template <> +inline const EnumDescriptor* GetEnumDescriptor< ::PROTOBUF_NAMESPACE_ID::FieldDescriptorProto_Type>() { + return ::PROTOBUF_NAMESPACE_ID::FieldDescriptorProto_Type_descriptor(); +} +template <> struct is_proto_enum< ::PROTOBUF_NAMESPACE_ID::FieldDescriptorProto_Label> : ::std::true_type {}; +template <> +inline const EnumDescriptor* GetEnumDescriptor< ::PROTOBUF_NAMESPACE_ID::FieldDescriptorProto_Label>() { + return ::PROTOBUF_NAMESPACE_ID::FieldDescriptorProto_Label_descriptor(); +} +template <> struct is_proto_enum< ::PROTOBUF_NAMESPACE_ID::FileOptions_OptimizeMode> : ::std::true_type {}; +template <> +inline const EnumDescriptor* GetEnumDescriptor< ::PROTOBUF_NAMESPACE_ID::FileOptions_OptimizeMode>() { + return ::PROTOBUF_NAMESPACE_ID::FileOptions_OptimizeMode_descriptor(); +} +template <> struct is_proto_enum< ::PROTOBUF_NAMESPACE_ID::FieldOptions_CType> : ::std::true_type {}; +template <> +inline const EnumDescriptor* GetEnumDescriptor< ::PROTOBUF_NAMESPACE_ID::FieldOptions_CType>() { + return ::PROTOBUF_NAMESPACE_ID::FieldOptions_CType_descriptor(); +} +template <> struct is_proto_enum< ::PROTOBUF_NAMESPACE_ID::FieldOptions_JSType> : ::std::true_type {}; +template <> +inline const EnumDescriptor* GetEnumDescriptor< ::PROTOBUF_NAMESPACE_ID::FieldOptions_JSType>() { + return ::PROTOBUF_NAMESPACE_ID::FieldOptions_JSType_descriptor(); +} +template <> struct is_proto_enum< ::PROTOBUF_NAMESPACE_ID::MethodOptions_IdempotencyLevel> : ::std::true_type {}; +template <> +inline const EnumDescriptor* GetEnumDescriptor< ::PROTOBUF_NAMESPACE_ID::MethodOptions_IdempotencyLevel>() { + return ::PROTOBUF_NAMESPACE_ID::MethodOptions_IdempotencyLevel_descriptor(); +} + +PROTOBUF_NAMESPACE_CLOSE + +// @@protoc_insertion_point(global_scope) + +#include <google/protobuf/port_undef.inc> +#endif // GOOGLE_PROTOBUF_INCLUDED_GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2fdescriptor_2eproto diff --git a/toolkit/components/protobuf/src/google/protobuf/descriptor.proto b/toolkit/components/protobuf/src/google/protobuf/descriptor.proto new file mode 100644 index 0000000000..f8eb216cdc --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/descriptor.proto @@ -0,0 +1,921 @@ +// 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. + +// Author: kenton@google.com (Kenton Varda) +// Based on original Protocol Buffers design by +// Sanjay Ghemawat, Jeff Dean, and others. +// +// The messages in this file describe the definitions found in .proto files. +// A valid .proto file can be translated directly to a FileDescriptorProto +// without any other information (e.g. without reading its imports). + + +syntax = "proto2"; + +package google.protobuf; + +option go_package = "google.golang.org/protobuf/types/descriptorpb"; +option java_package = "com.google.protobuf"; +option java_outer_classname = "DescriptorProtos"; +option csharp_namespace = "Google.Protobuf.Reflection"; +option objc_class_prefix = "GPB"; +option cc_enable_arenas = true; + +// descriptor.proto must be optimized for speed because reflection-based +// algorithms don't work during bootstrapping. +option optimize_for = SPEED; + +// The protocol compiler can output a FileDescriptorSet containing the .proto +// files it parses. +message FileDescriptorSet { + repeated FileDescriptorProto file = 1; +} + +// Describes a complete .proto file. +message FileDescriptorProto { + optional string name = 1; // file name, relative to root of source tree + optional string package = 2; // e.g. "foo", "foo.bar", etc. + + // Names of files imported by this file. + repeated string dependency = 3; + // Indexes of the public imported files in the dependency list above. + repeated int32 public_dependency = 10; + // Indexes of the weak imported files in the dependency list. + // For Google-internal migration only. Do not use. + repeated int32 weak_dependency = 11; + + // All top-level definitions in this file. + repeated DescriptorProto message_type = 4; + repeated EnumDescriptorProto enum_type = 5; + repeated ServiceDescriptorProto service = 6; + repeated FieldDescriptorProto extension = 7; + + optional FileOptions options = 8; + + // This field contains optional information about the original source code. + // You may safely remove this entire field without harming runtime + // functionality of the descriptors -- the information is needed only by + // development tools. + optional SourceCodeInfo source_code_info = 9; + + // The syntax of the proto file. + // The supported values are "proto2" and "proto3". + optional string syntax = 12; +} + +// Describes a message type. +message DescriptorProto { + optional string name = 1; + + repeated FieldDescriptorProto field = 2; + repeated FieldDescriptorProto extension = 6; + + repeated DescriptorProto nested_type = 3; + repeated EnumDescriptorProto enum_type = 4; + + message ExtensionRange { + optional int32 start = 1; // Inclusive. + optional int32 end = 2; // Exclusive. + + optional ExtensionRangeOptions options = 3; + } + repeated ExtensionRange extension_range = 5; + + repeated OneofDescriptorProto oneof_decl = 8; + + optional MessageOptions options = 7; + + // Range of reserved tag numbers. Reserved tag numbers may not be used by + // fields or extension ranges in the same message. Reserved ranges may + // not overlap. + message ReservedRange { + optional int32 start = 1; // Inclusive. + optional int32 end = 2; // Exclusive. + } + repeated ReservedRange reserved_range = 9; + // Reserved field names, which may not be used by fields in the same message. + // A given name may only be reserved once. + repeated string reserved_name = 10; +} + +message ExtensionRangeOptions { + // The parser stores options it doesn't recognize here. See above. + repeated UninterpretedOption uninterpreted_option = 999; + + + // Clients can define custom options in extensions of this message. See above. + extensions 1000 to max; +} + +// Describes a field within a message. +message FieldDescriptorProto { + enum Type { + // 0 is reserved for errors. + // Order is weird for historical reasons. + TYPE_DOUBLE = 1; + TYPE_FLOAT = 2; + // Not ZigZag encoded. Negative numbers take 10 bytes. Use TYPE_SINT64 if + // negative values are likely. + TYPE_INT64 = 3; + TYPE_UINT64 = 4; + // Not ZigZag encoded. Negative numbers take 10 bytes. Use TYPE_SINT32 if + // negative values are likely. + TYPE_INT32 = 5; + TYPE_FIXED64 = 6; + TYPE_FIXED32 = 7; + TYPE_BOOL = 8; + TYPE_STRING = 9; + // Tag-delimited aggregate. + // Group type is deprecated and not supported in proto3. However, Proto3 + // implementations should still be able to parse the group wire format and + // treat group fields as unknown fields. + TYPE_GROUP = 10; + TYPE_MESSAGE = 11; // Length-delimited aggregate. + + // New in version 2. + TYPE_BYTES = 12; + TYPE_UINT32 = 13; + TYPE_ENUM = 14; + TYPE_SFIXED32 = 15; + TYPE_SFIXED64 = 16; + TYPE_SINT32 = 17; // Uses ZigZag encoding. + TYPE_SINT64 = 18; // Uses ZigZag encoding. + } + + enum Label { + // 0 is reserved for errors + LABEL_OPTIONAL = 1; + LABEL_REQUIRED = 2; + LABEL_REPEATED = 3; + } + + optional string name = 1; + optional int32 number = 3; + optional Label label = 4; + + // If type_name is set, this need not be set. If both this and type_name + // are set, this must be one of TYPE_ENUM, TYPE_MESSAGE or TYPE_GROUP. + optional Type type = 5; + + // For message and enum types, this is the name of the type. If the name + // starts with a '.', it is fully-qualified. Otherwise, C++-like scoping + // rules are used to find the type (i.e. first the nested types within this + // message are searched, then within the parent, on up to the root + // namespace). + optional string type_name = 6; + + // For extensions, this is the name of the type being extended. It is + // resolved in the same manner as type_name. + optional string extendee = 2; + + // For numeric types, contains the original text representation of the value. + // For booleans, "true" or "false". + // For strings, contains the default text contents (not escaped in any way). + // For bytes, contains the C escaped value. All bytes >= 128 are escaped. + optional string default_value = 7; + + // If set, gives the index of a oneof in the containing type's oneof_decl + // list. This field is a member of that oneof. + optional int32 oneof_index = 9; + + // JSON name of this field. The value is set by protocol compiler. If the + // user has set a "json_name" option on this field, that option's value + // will be used. Otherwise, it's deduced from the field's name by converting + // it to camelCase. + optional string json_name = 10; + + optional FieldOptions options = 8; + + // If true, this is a proto3 "optional". When a proto3 field is optional, it + // tracks presence regardless of field type. + // + // When proto3_optional is true, this field must be belong to a oneof to + // signal to old proto3 clients that presence is tracked for this field. This + // oneof is known as a "synthetic" oneof, and this field must be its sole + // member (each proto3 optional field gets its own synthetic oneof). Synthetic + // oneofs exist in the descriptor only, and do not generate any API. Synthetic + // oneofs must be ordered after all "real" oneofs. + // + // For message fields, proto3_optional doesn't create any semantic change, + // since non-repeated message fields always track presence. However it still + // indicates the semantic detail of whether the user wrote "optional" or not. + // This can be useful for round-tripping the .proto file. For consistency we + // give message fields a synthetic oneof also, even though it is not required + // to track presence. This is especially important because the parser can't + // tell if a field is a message or an enum, so it must always create a + // synthetic oneof. + // + // Proto2 optional fields do not set this flag, because they already indicate + // optional with `LABEL_OPTIONAL`. + optional bool proto3_optional = 17; +} + +// Describes a oneof. +message OneofDescriptorProto { + optional string name = 1; + optional OneofOptions options = 2; +} + +// Describes an enum type. +message EnumDescriptorProto { + optional string name = 1; + + repeated EnumValueDescriptorProto value = 2; + + optional EnumOptions options = 3; + + // Range of reserved numeric values. Reserved values may not be used by + // entries in the same enum. Reserved ranges may not overlap. + // + // Note that this is distinct from DescriptorProto.ReservedRange in that it + // is inclusive such that it can appropriately represent the entire int32 + // domain. + message EnumReservedRange { + optional int32 start = 1; // Inclusive. + optional int32 end = 2; // Inclusive. + } + + // Range of reserved numeric values. Reserved numeric values may not be used + // by enum values in the same enum declaration. Reserved ranges may not + // overlap. + repeated EnumReservedRange reserved_range = 4; + + // Reserved enum value names, which may not be reused. A given name may only + // be reserved once. + repeated string reserved_name = 5; +} + +// Describes a value within an enum. +message EnumValueDescriptorProto { + optional string name = 1; + optional int32 number = 2; + + optional EnumValueOptions options = 3; +} + +// Describes a service. +message ServiceDescriptorProto { + optional string name = 1; + repeated MethodDescriptorProto method = 2; + + optional ServiceOptions options = 3; +} + +// Describes a method of a service. +message MethodDescriptorProto { + optional string name = 1; + + // Input and output type names. These are resolved in the same way as + // FieldDescriptorProto.type_name, but must refer to a message type. + optional string input_type = 2; + optional string output_type = 3; + + optional MethodOptions options = 4; + + // Identifies if client streams multiple client messages + optional bool client_streaming = 5 [default = false]; + // Identifies if server streams multiple server messages + optional bool server_streaming = 6 [default = false]; +} + + +// =================================================================== +// Options + +// Each of the definitions above may have "options" attached. These are +// just annotations which may cause code to be generated slightly differently +// or may contain hints for code that manipulates protocol messages. +// +// Clients may define custom options as extensions of the *Options messages. +// These extensions may not yet be known at parsing time, so the parser cannot +// store the values in them. Instead it stores them in a field in the *Options +// message called uninterpreted_option. This field must have the same name +// across all *Options messages. We then use this field to populate the +// extensions when we build a descriptor, at which point all protos have been +// parsed and so all extensions are known. +// +// Extension numbers for custom options may be chosen as follows: +// * For options which will only be used within a single application or +// organization, or for experimental options, use field numbers 50000 +// through 99999. It is up to you to ensure that you do not use the +// same number for multiple options. +// * For options which will be published and used publicly by multiple +// independent entities, e-mail protobuf-global-extension-registry@google.com +// to reserve extension numbers. Simply provide your project name (e.g. +// Objective-C plugin) and your project website (if available) -- there's no +// need to explain how you intend to use them. Usually you only need one +// extension number. You can declare multiple options with only one extension +// number by putting them in a sub-message. See the Custom Options section of +// the docs for examples: +// https://developers.google.com/protocol-buffers/docs/proto#options +// If this turns out to be popular, a web service will be set up +// to automatically assign option numbers. + +message FileOptions { + + // Sets the Java package where classes generated from this .proto will be + // placed. By default, the proto package is used, but this is often + // inappropriate because proto packages do not normally start with backwards + // domain names. + optional string java_package = 1; + + + // Controls the name of the wrapper Java class generated for the .proto file. + // That class will always contain the .proto file's getDescriptor() method as + // well as any top-level extensions defined in the .proto file. + // If java_multiple_files is disabled, then all the other classes from the + // .proto file will be nested inside the single wrapper outer class. + optional string java_outer_classname = 8; + + // If enabled, then the Java code generator will generate a separate .java + // file for each top-level message, enum, and service defined in the .proto + // file. Thus, these types will *not* be nested inside the wrapper class + // named by java_outer_classname. However, the wrapper class will still be + // generated to contain the file's getDescriptor() method as well as any + // top-level extensions defined in the file. + optional bool java_multiple_files = 10 [default = false]; + + // This option does nothing. + optional bool java_generate_equals_and_hash = 20 [deprecated=true]; + + // If set true, then the Java2 code generator will generate code that + // throws an exception whenever an attempt is made to assign a non-UTF-8 + // byte sequence to a string field. + // Message reflection will do the same. + // However, an extension field still accepts non-UTF-8 byte sequences. + // This option has no effect on when used with the lite runtime. + optional bool java_string_check_utf8 = 27 [default = false]; + + + // Generated classes can be optimized for speed or code size. + enum OptimizeMode { + SPEED = 1; // Generate complete code for parsing, serialization, + // etc. + CODE_SIZE = 2; // Use ReflectionOps to implement these methods. + LITE_RUNTIME = 3; // Generate code using MessageLite and the lite runtime. + } + optional OptimizeMode optimize_for = 9 [default = SPEED]; + + // Sets the Go package where structs generated from this .proto will be + // placed. If omitted, the Go package will be derived from the following: + // - The basename of the package import path, if provided. + // - Otherwise, the package statement in the .proto file, if present. + // - Otherwise, the basename of the .proto file, without extension. + optional string go_package = 11; + + + + + // Should generic services be generated in each language? "Generic" services + // are not specific to any particular RPC system. They are generated by the + // main code generators in each language (without additional plugins). + // Generic services were the only kind of service generation supported by + // early versions of google.protobuf. + // + // Generic services are now considered deprecated in favor of using plugins + // that generate code specific to your particular RPC system. Therefore, + // these default to false. Old code which depends on generic services should + // explicitly set them to true. + optional bool cc_generic_services = 16 [default = false]; + optional bool java_generic_services = 17 [default = false]; + optional bool py_generic_services = 18 [default = false]; + optional bool php_generic_services = 42 [default = false]; + + // Is this file deprecated? + // Depending on the target platform, this can emit Deprecated annotations + // for everything in the file, or it will be completely ignored; in the very + // least, this is a formalization for deprecating files. + optional bool deprecated = 23 [default = false]; + + // Enables the use of arenas for the proto messages in this file. This applies + // only to generated classes for C++. + optional bool cc_enable_arenas = 31 [default = true]; + + + // Sets the objective c class prefix which is prepended to all objective c + // generated classes from this .proto. There is no default. + optional string objc_class_prefix = 36; + + // Namespace for generated classes; defaults to the package. + optional string csharp_namespace = 37; + + // By default Swift generators will take the proto package and CamelCase it + // replacing '.' with underscore and use that to prefix the types/symbols + // defined. When this options is provided, they will use this value instead + // to prefix the types/symbols defined. + optional string swift_prefix = 39; + + // Sets the php class prefix which is prepended to all php generated classes + // from this .proto. Default is empty. + optional string php_class_prefix = 40; + + // Use this option to change the namespace of php generated classes. Default + // is empty. When this option is empty, the package name will be used for + // determining the namespace. + optional string php_namespace = 41; + + // Use this option to change the namespace of php generated metadata classes. + // Default is empty. When this option is empty, the proto file name will be + // used for determining the namespace. + optional string php_metadata_namespace = 44; + + // Use this option to change the package of ruby generated classes. Default + // is empty. When this option is not set, the package name will be used for + // determining the ruby package. + optional string ruby_package = 45; + + + // The parser stores options it doesn't recognize here. + // See the documentation for the "Options" section above. + repeated UninterpretedOption uninterpreted_option = 999; + + // Clients can define custom options in extensions of this message. + // See the documentation for the "Options" section above. + extensions 1000 to max; + + reserved 38; +} + +message MessageOptions { + // Set true to use the old proto1 MessageSet wire format for extensions. + // This is provided for backwards-compatibility with the MessageSet wire + // format. You should not use this for any other reason: It's less + // efficient, has fewer features, and is more complicated. + // + // The message must be defined exactly as follows: + // message Foo { + // option message_set_wire_format = true; + // extensions 4 to max; + // } + // Note that the message cannot have any defined fields; MessageSets only + // have extensions. + // + // All extensions of your type must be singular messages; e.g. they cannot + // be int32s, enums, or repeated messages. + // + // Because this is an option, the above two restrictions are not enforced by + // the protocol compiler. + optional bool message_set_wire_format = 1 [default = false]; + + // Disables the generation of the standard "descriptor()" accessor, which can + // conflict with a field of the same name. This is meant to make migration + // from proto1 easier; new code should avoid fields named "descriptor". + optional bool no_standard_descriptor_accessor = 2 [default = false]; + + // Is this message deprecated? + // Depending on the target platform, this can emit Deprecated annotations + // for the message, or it will be completely ignored; in the very least, + // this is a formalization for deprecating messages. + optional bool deprecated = 3 [default = false]; + + reserved 4, 5, 6; + + // Whether the message is an automatically generated map entry type for the + // maps field. + // + // For maps fields: + // map<KeyType, ValueType> map_field = 1; + // The parsed descriptor looks like: + // message MapFieldEntry { + // option map_entry = true; + // optional KeyType key = 1; + // optional ValueType value = 2; + // } + // repeated MapFieldEntry map_field = 1; + // + // Implementations may choose not to generate the map_entry=true message, but + // use a native map in the target language to hold the keys and values. + // The reflection APIs in such implementations still need to work as + // if the field is a repeated message field. + // + // NOTE: Do not set the option in .proto files. Always use the maps syntax + // instead. The option should only be implicitly set by the proto compiler + // parser. + optional bool map_entry = 7; + + reserved 8; // javalite_serializable + reserved 9; // javanano_as_lite + + + // The parser stores options it doesn't recognize here. See above. + repeated UninterpretedOption uninterpreted_option = 999; + + // Clients can define custom options in extensions of this message. See above. + extensions 1000 to max; +} + +message FieldOptions { + // The ctype option instructs the C++ code generator to use a different + // representation of the field than it normally would. See the specific + // options below. This option is not yet implemented in the open source + // release -- sorry, we'll try to include it in a future version! + optional CType ctype = 1 [default = STRING]; + enum CType { + // Default mode. + STRING = 0; + + CORD = 1; + + STRING_PIECE = 2; + } + // The packed option can be enabled for repeated primitive fields to enable + // a more efficient representation on the wire. Rather than repeatedly + // writing the tag and type for each element, the entire array is encoded as + // a single length-delimited blob. In proto3, only explicit setting it to + // false will avoid using packed encoding. + optional bool packed = 2; + + // The jstype option determines the JavaScript type used for values of the + // field. The option is permitted only for 64 bit integral and fixed types + // (int64, uint64, sint64, fixed64, sfixed64). A field with jstype JS_STRING + // is represented as JavaScript string, which avoids loss of precision that + // can happen when a large value is converted to a floating point JavaScript. + // Specifying JS_NUMBER for the jstype causes the generated JavaScript code to + // use the JavaScript "number" type. The behavior of the default option + // JS_NORMAL is implementation dependent. + // + // This option is an enum to permit additional types to be added, e.g. + // goog.math.Integer. + optional JSType jstype = 6 [default = JS_NORMAL]; + enum JSType { + // Use the default type. + JS_NORMAL = 0; + + // Use JavaScript strings. + JS_STRING = 1; + + // Use JavaScript numbers. + JS_NUMBER = 2; + } + + // Should this field be parsed lazily? Lazy applies only to message-type + // fields. It means that when the outer message is initially parsed, the + // inner message's contents will not be parsed but instead stored in encoded + // form. The inner message will actually be parsed when it is first accessed. + // + // This is only a hint. Implementations are free to choose whether to use + // eager or lazy parsing regardless of the value of this option. However, + // setting this option true suggests that the protocol author believes that + // using lazy parsing on this field is worth the additional bookkeeping + // overhead typically needed to implement it. + // + // This option does not affect the public interface of any generated code; + // all method signatures remain the same. Furthermore, thread-safety of the + // interface is not affected by this option; const methods remain safe to + // call from multiple threads concurrently, while non-const methods continue + // to require exclusive access. + // + // + // Note that implementations may choose not to check required fields within + // a lazy sub-message. That is, calling IsInitialized() on the outer message + // may return true even if the inner message has missing required fields. + // This is necessary because otherwise the inner message would have to be + // parsed in order to perform the check, defeating the purpose of lazy + // parsing. An implementation which chooses not to check required fields + // must be consistent about it. That is, for any particular sub-message, the + // implementation must either *always* check its required fields, or *never* + // check its required fields, regardless of whether or not the message has + // been parsed. + // + // As of 2021, lazy does no correctness checks on the byte stream during + // parsing. This may lead to crashes if and when an invalid byte stream is + // finally parsed upon access. + // + // TODO(b/211906113): Enable validation on lazy fields. + optional bool lazy = 5 [default = false]; + + // unverified_lazy does no correctness checks on the byte stream. This should + // only be used where lazy with verification is prohibitive for performance + // reasons. + optional bool unverified_lazy = 15 [default = false]; + + // Is this field deprecated? + // Depending on the target platform, this can emit Deprecated annotations + // for accessors, or it will be completely ignored; in the very least, this + // is a formalization for deprecating fields. + optional bool deprecated = 3 [default = false]; + + // For Google-internal migration only. Do not use. + optional bool weak = 10 [default = false]; + + + // The parser stores options it doesn't recognize here. See above. + repeated UninterpretedOption uninterpreted_option = 999; + + // Clients can define custom options in extensions of this message. See above. + extensions 1000 to max; + + reserved 4; // removed jtype +} + +message OneofOptions { + // The parser stores options it doesn't recognize here. See above. + repeated UninterpretedOption uninterpreted_option = 999; + + // Clients can define custom options in extensions of this message. See above. + extensions 1000 to max; +} + +message EnumOptions { + + // Set this option to true to allow mapping different tag names to the same + // value. + optional bool allow_alias = 2; + + // Is this enum deprecated? + // Depending on the target platform, this can emit Deprecated annotations + // for the enum, or it will be completely ignored; in the very least, this + // is a formalization for deprecating enums. + optional bool deprecated = 3 [default = false]; + + reserved 5; // javanano_as_lite + + // The parser stores options it doesn't recognize here. See above. + repeated UninterpretedOption uninterpreted_option = 999; + + // Clients can define custom options in extensions of this message. See above. + extensions 1000 to max; +} + +message EnumValueOptions { + // Is this enum value deprecated? + // Depending on the target platform, this can emit Deprecated annotations + // for the enum value, or it will be completely ignored; in the very least, + // this is a formalization for deprecating enum values. + optional bool deprecated = 1 [default = false]; + + // The parser stores options it doesn't recognize here. See above. + repeated UninterpretedOption uninterpreted_option = 999; + + // Clients can define custom options in extensions of this message. See above. + extensions 1000 to max; +} + +message ServiceOptions { + + // Note: Field numbers 1 through 32 are reserved for Google's internal RPC + // framework. We apologize for hoarding these numbers to ourselves, but + // we were already using them long before we decided to release Protocol + // Buffers. + + // Is this service deprecated? + // Depending on the target platform, this can emit Deprecated annotations + // for the service, or it will be completely ignored; in the very least, + // this is a formalization for deprecating services. + optional bool deprecated = 33 [default = false]; + + // The parser stores options it doesn't recognize here. See above. + repeated UninterpretedOption uninterpreted_option = 999; + + // Clients can define custom options in extensions of this message. See above. + extensions 1000 to max; +} + +message MethodOptions { + + // Note: Field numbers 1 through 32 are reserved for Google's internal RPC + // framework. We apologize for hoarding these numbers to ourselves, but + // we were already using them long before we decided to release Protocol + // Buffers. + + // Is this method deprecated? + // Depending on the target platform, this can emit Deprecated annotations + // for the method, or it will be completely ignored; in the very least, + // this is a formalization for deprecating methods. + optional bool deprecated = 33 [default = false]; + + // Is this method side-effect-free (or safe in HTTP parlance), or idempotent, + // or neither? HTTP based RPC implementation may choose GET verb for safe + // methods, and PUT verb for idempotent methods instead of the default POST. + enum IdempotencyLevel { + IDEMPOTENCY_UNKNOWN = 0; + NO_SIDE_EFFECTS = 1; // implies idempotent + IDEMPOTENT = 2; // idempotent, but may have side effects + } + optional IdempotencyLevel idempotency_level = 34 + [default = IDEMPOTENCY_UNKNOWN]; + + // The parser stores options it doesn't recognize here. See above. + repeated UninterpretedOption uninterpreted_option = 999; + + // Clients can define custom options in extensions of this message. See above. + extensions 1000 to max; +} + + +// A message representing a option the parser does not recognize. This only +// appears in options protos created by the compiler::Parser class. +// DescriptorPool resolves these when building Descriptor objects. Therefore, +// options protos in descriptor objects (e.g. returned by Descriptor::options(), +// or produced by Descriptor::CopyTo()) will never have UninterpretedOptions +// in them. +message UninterpretedOption { + // The name of the uninterpreted option. Each string represents a segment in + // a dot-separated name. is_extension is true iff a segment represents an + // extension (denoted with parentheses in options specs in .proto files). + // E.g.,{ ["foo", false], ["bar.baz", true], ["moo", false] } represents + // "foo.(bar.baz).moo". + message NamePart { + required string name_part = 1; + required bool is_extension = 2; + } + repeated NamePart name = 2; + + // The value of the uninterpreted option, in whatever type the tokenizer + // identified it as during parsing. Exactly one of these should be set. + optional string identifier_value = 3; + optional uint64 positive_int_value = 4; + optional int64 negative_int_value = 5; + optional double double_value = 6; + optional bytes string_value = 7; + optional string aggregate_value = 8; +} + +// =================================================================== +// Optional source code info + +// Encapsulates information about the original source file from which a +// FileDescriptorProto was generated. +message SourceCodeInfo { + // A Location identifies a piece of source code in a .proto file which + // corresponds to a particular definition. This information is intended + // to be useful to IDEs, code indexers, documentation generators, and similar + // tools. + // + // For example, say we have a file like: + // message Foo { + // optional string foo = 1; + // } + // Let's look at just the field definition: + // optional string foo = 1; + // ^ ^^ ^^ ^ ^^^ + // a bc de f ghi + // We have the following locations: + // span path represents + // [a,i) [ 4, 0, 2, 0 ] The whole field definition. + // [a,b) [ 4, 0, 2, 0, 4 ] The label (optional). + // [c,d) [ 4, 0, 2, 0, 5 ] The type (string). + // [e,f) [ 4, 0, 2, 0, 1 ] The name (foo). + // [g,h) [ 4, 0, 2, 0, 3 ] The number (1). + // + // Notes: + // - A location may refer to a repeated field itself (i.e. not to any + // particular index within it). This is used whenever a set of elements are + // logically enclosed in a single code segment. For example, an entire + // extend block (possibly containing multiple extension definitions) will + // have an outer location whose path refers to the "extensions" repeated + // field without an index. + // - Multiple locations may have the same path. This happens when a single + // logical declaration is spread out across multiple places. The most + // obvious example is the "extend" block again -- there may be multiple + // extend blocks in the same scope, each of which will have the same path. + // - A location's span is not always a subset of its parent's span. For + // example, the "extendee" of an extension declaration appears at the + // beginning of the "extend" block and is shared by all extensions within + // the block. + // - Just because a location's span is a subset of some other location's span + // does not mean that it is a descendant. For example, a "group" defines + // both a type and a field in a single declaration. Thus, the locations + // corresponding to the type and field and their components will overlap. + // - Code which tries to interpret locations should probably be designed to + // ignore those that it doesn't understand, as more types of locations could + // be recorded in the future. + repeated Location location = 1; + message Location { + // Identifies which part of the FileDescriptorProto was defined at this + // location. + // + // Each element is a field number or an index. They form a path from + // the root FileDescriptorProto to the place where the definition occurs. + // For example, this path: + // [ 4, 3, 2, 7, 1 ] + // refers to: + // file.message_type(3) // 4, 3 + // .field(7) // 2, 7 + // .name() // 1 + // This is because FileDescriptorProto.message_type has field number 4: + // repeated DescriptorProto message_type = 4; + // and DescriptorProto.field has field number 2: + // repeated FieldDescriptorProto field = 2; + // and FieldDescriptorProto.name has field number 1: + // optional string name = 1; + // + // Thus, the above path gives the location of a field name. If we removed + // the last element: + // [ 4, 3, 2, 7 ] + // this path refers to the whole field declaration (from the beginning + // of the label to the terminating semicolon). + repeated int32 path = 1 [packed = true]; + + // Always has exactly three or four elements: start line, start column, + // end line (optional, otherwise assumed same as start line), end column. + // These are packed into a single field for efficiency. Note that line + // and column numbers are zero-based -- typically you will want to add + // 1 to each before displaying to a user. + repeated int32 span = 2 [packed = true]; + + // If this SourceCodeInfo represents a complete declaration, these are any + // comments appearing before and after the declaration which appear to be + // attached to the declaration. + // + // A series of line comments appearing on consecutive lines, with no other + // tokens appearing on those lines, will be treated as a single comment. + // + // leading_detached_comments will keep paragraphs of comments that appear + // before (but not connected to) the current element. Each paragraph, + // separated by empty lines, will be one comment element in the repeated + // field. + // + // Only the comment content is provided; comment markers (e.g. //) are + // stripped out. For block comments, leading whitespace and an asterisk + // will be stripped from the beginning of each line other than the first. + // Newlines are included in the output. + // + // Examples: + // + // optional int32 foo = 1; // Comment attached to foo. + // // Comment attached to bar. + // optional int32 bar = 2; + // + // optional string baz = 3; + // // Comment attached to baz. + // // Another line attached to baz. + // + // // Comment attached to moo. + // // + // // Another line attached to moo. + // optional double moo = 4; + // + // // Detached comment for corge. This is not leading or trailing comments + // // to moo or corge because there are blank lines separating it from + // // both. + // + // // Detached comment for corge paragraph 2. + // + // optional string corge = 5; + // /* Block comment attached + // * to corge. Leading asterisks + // * will be removed. */ + // /* Block comment attached to + // * grault. */ + // optional int32 grault = 6; + // + // // ignored detached comments. + optional string leading_comments = 3; + optional string trailing_comments = 4; + repeated string leading_detached_comments = 6; + } +} + +// Describes the relationship between generated code and its original source +// file. A GeneratedCodeInfo message is associated with only one generated +// source file, but may contain references to different source .proto files. +message GeneratedCodeInfo { + // An Annotation connects some span of text in generated code to an element + // of its generating .proto file. + repeated Annotation annotation = 1; + message Annotation { + // Identifies the element in the original source .proto file. This field + // is formatted the same as SourceCodeInfo.Location.path. + repeated int32 path = 1 [packed = true]; + + // Identifies the filesystem path to the original source .proto. + optional string source_file = 2; + + // Identifies the starting offset in bytes in the generated code + // that relates to the identified object. + optional int32 begin = 3; + + // Identifies the ending offset in bytes in the generated code that + // relates to the identified offset. The end offset should be one past + // the last relevant byte (so the length of the text = end - begin). + optional int32 end = 4; + } +} diff --git a/toolkit/components/protobuf/src/google/protobuf/descriptor_database.cc b/toolkit/components/protobuf/src/google/protobuf/descriptor_database.cc new file mode 100644 index 0000000000..203000d67d --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/descriptor_database.cc @@ -0,0 +1,1048 @@ +// 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. + +// Author: kenton@google.com (Kenton Varda) +// Based on original Protocol Buffers design by +// Sanjay Ghemawat, Jeff Dean, and others. + +#include <google/protobuf/descriptor_database.h> + +#include <algorithm> +#include <set> + +#include <google/protobuf/descriptor.pb.h> +#include <google/protobuf/stubs/map_util.h> +#include <google/protobuf/stubs/stl_util.h> + + +namespace google { +namespace protobuf { + +namespace { +void RecordMessageNames(const DescriptorProto& desc_proto, + const std::string& prefix, + std::set<std::string>* output) { + GOOGLE_CHECK(desc_proto.has_name()); + std::string full_name = prefix.empty() + ? desc_proto.name() + : StrCat(prefix, ".", desc_proto.name()); + output->insert(full_name); + + for (const auto& d : desc_proto.nested_type()) { + RecordMessageNames(d, full_name, output); + } +} + +void RecordMessageNames(const FileDescriptorProto& file_proto, + std::set<std::string>* output) { + for (const auto& d : file_proto.message_type()) { + RecordMessageNames(d, file_proto.package(), output); + } +} + +template <typename Fn> +bool ForAllFileProtos(DescriptorDatabase* db, Fn callback, + std::vector<std::string>* output) { + std::vector<std::string> file_names; + if (!db->FindAllFileNames(&file_names)) { + return false; + } + std::set<std::string> set; + FileDescriptorProto file_proto; + for (const auto& f : file_names) { + file_proto.Clear(); + if (!db->FindFileByName(f, &file_proto)) { + GOOGLE_LOG(ERROR) << "File not found in database (unexpected): " << f; + return false; + } + callback(file_proto, &set); + } + output->insert(output->end(), set.begin(), set.end()); + return true; +} +} // namespace + +DescriptorDatabase::~DescriptorDatabase() {} + +bool DescriptorDatabase::FindAllPackageNames(std::vector<std::string>* output) { + return ForAllFileProtos( + this, + [](const FileDescriptorProto& file_proto, std::set<std::string>* set) { + set->insert(file_proto.package()); + }, + output); +} + +bool DescriptorDatabase::FindAllMessageNames(std::vector<std::string>* output) { + return ForAllFileProtos( + this, + [](const FileDescriptorProto& file_proto, std::set<std::string>* set) { + RecordMessageNames(file_proto, set); + }, + output); +} + +// =================================================================== + +SimpleDescriptorDatabase::SimpleDescriptorDatabase() {} +SimpleDescriptorDatabase::~SimpleDescriptorDatabase() {} + +template <typename Value> +bool SimpleDescriptorDatabase::DescriptorIndex<Value>::AddFile( + const FileDescriptorProto& file, Value value) { + if (!InsertIfNotPresent(&by_name_, file.name(), value)) { + GOOGLE_LOG(ERROR) << "File already exists in database: " << file.name(); + return false; + } + + // We must be careful here -- calling file.package() if file.has_package() is + // false could access an uninitialized static-storage variable if we are being + // run at startup time. + std::string path = file.has_package() ? file.package() : std::string(); + if (!path.empty()) path += '.'; + + for (int i = 0; i < file.message_type_size(); i++) { + if (!AddSymbol(path + file.message_type(i).name(), value)) return false; + if (!AddNestedExtensions(file.name(), file.message_type(i), value)) + return false; + } + for (int i = 0; i < file.enum_type_size(); i++) { + if (!AddSymbol(path + file.enum_type(i).name(), value)) return false; + } + for (int i = 0; i < file.extension_size(); i++) { + if (!AddSymbol(path + file.extension(i).name(), value)) return false; + if (!AddExtension(file.name(), file.extension(i), value)) return false; + } + for (int i = 0; i < file.service_size(); i++) { + if (!AddSymbol(path + file.service(i).name(), value)) return false; + } + + return true; +} + +namespace { + +// Returns true if and only if all characters in the name are alphanumerics, +// underscores, or periods. +bool ValidateSymbolName(StringPiece name) { + for (char c : name) { + // I don't trust ctype.h due to locales. :( + if (c != '.' && c != '_' && (c < '0' || c > '9') && (c < 'A' || c > 'Z') && + (c < 'a' || c > 'z')) { + return false; + } + } + return true; +} + +// Find the last key in the container which sorts less than or equal to the +// symbol name. Since upper_bound() returns the *first* key that sorts +// *greater* than the input, we want the element immediately before that. +template <typename Container, typename Key> +typename Container::const_iterator FindLastLessOrEqual( + const Container* container, const Key& key) { + auto iter = container->upper_bound(key); + if (iter != container->begin()) --iter; + return iter; +} + +// As above, but using std::upper_bound instead. +template <typename Container, typename Key, typename Cmp> +typename Container::const_iterator FindLastLessOrEqual( + const Container* container, const Key& key, const Cmp& cmp) { + auto iter = std::upper_bound(container->begin(), container->end(), key, cmp); + if (iter != container->begin()) --iter; + return iter; +} + +// True if either the arguments are equal or super_symbol identifies a +// parent symbol of sub_symbol (e.g. "foo.bar" is a parent of +// "foo.bar.baz", but not a parent of "foo.barbaz"). +bool IsSubSymbol(StringPiece sub_symbol, StringPiece super_symbol) { + return sub_symbol == super_symbol || + (HasPrefixString(super_symbol, sub_symbol) && + super_symbol[sub_symbol.size()] == '.'); +} + +} // namespace + +template <typename Value> +bool SimpleDescriptorDatabase::DescriptorIndex<Value>::AddSymbol( + const std::string& name, Value value) { + // We need to make sure not to violate our map invariant. + + // If the symbol name is invalid it could break our lookup algorithm (which + // relies on the fact that '.' sorts before all other characters that are + // valid in symbol names). + if (!ValidateSymbolName(name)) { + GOOGLE_LOG(ERROR) << "Invalid symbol name: " << name; + return false; + } + + // Try to look up the symbol to make sure a super-symbol doesn't already + // exist. + auto iter = FindLastLessOrEqual(&by_symbol_, name); + + if (iter == by_symbol_.end()) { + // Apparently the map is currently empty. Just insert and be done with it. + by_symbol_.insert( + typename std::map<std::string, Value>::value_type(name, value)); + return true; + } + + if (IsSubSymbol(iter->first, name)) { + GOOGLE_LOG(ERROR) << "Symbol name \"" << name + << "\" conflicts with the existing " + "symbol \"" + << iter->first << "\"."; + return false; + } + + // OK, that worked. Now we have to make sure that no symbol in the map is + // a sub-symbol of the one we are inserting. The only symbol which could + // be so is the first symbol that is greater than the new symbol. Since + // |iter| points at the last symbol that is less than or equal, we just have + // to increment it. + ++iter; + + if (iter != by_symbol_.end() && IsSubSymbol(name, iter->first)) { + GOOGLE_LOG(ERROR) << "Symbol name \"" << name + << "\" conflicts with the existing " + "symbol \"" + << iter->first << "\"."; + return false; + } + + // OK, no conflicts. + + // Insert the new symbol using the iterator as a hint, the new entry will + // appear immediately before the one the iterator is pointing at. + by_symbol_.insert( + iter, typename std::map<std::string, Value>::value_type(name, value)); + + return true; +} + +template <typename Value> +bool SimpleDescriptorDatabase::DescriptorIndex<Value>::AddNestedExtensions( + const std::string& filename, const DescriptorProto& message_type, + Value value) { + for (int i = 0; i < message_type.nested_type_size(); i++) { + if (!AddNestedExtensions(filename, message_type.nested_type(i), value)) + return false; + } + for (int i = 0; i < message_type.extension_size(); i++) { + if (!AddExtension(filename, message_type.extension(i), value)) return false; + } + return true; +} + +template <typename Value> +bool SimpleDescriptorDatabase::DescriptorIndex<Value>::AddExtension( + const std::string& filename, const FieldDescriptorProto& field, + Value value) { + if (!field.extendee().empty() && field.extendee()[0] == '.') { + // The extension is fully-qualified. We can use it as a lookup key in + // the by_symbol_ table. + if (!InsertIfNotPresent( + &by_extension_, + std::make_pair(field.extendee().substr(1), field.number()), + value)) { + GOOGLE_LOG(ERROR) << "Extension conflicts with extension already in database: " + "extend " + << field.extendee() << " { " << field.name() << " = " + << field.number() << " } from:" << filename; + return false; + } + } else { + // Not fully-qualified. We can't really do anything here, unfortunately. + // We don't consider this an error, though, because the descriptor is + // valid. + } + return true; +} + +template <typename Value> +Value SimpleDescriptorDatabase::DescriptorIndex<Value>::FindFile( + const std::string& filename) { + return FindWithDefault(by_name_, filename, Value()); +} + +template <typename Value> +Value SimpleDescriptorDatabase::DescriptorIndex<Value>::FindSymbol( + const std::string& name) { + auto iter = FindLastLessOrEqual(&by_symbol_, name); + + return (iter != by_symbol_.end() && IsSubSymbol(iter->first, name)) + ? iter->second + : Value(); +} + +template <typename Value> +Value SimpleDescriptorDatabase::DescriptorIndex<Value>::FindExtension( + const std::string& containing_type, int field_number) { + return FindWithDefault( + by_extension_, std::make_pair(containing_type, field_number), Value()); +} + +template <typename Value> +bool SimpleDescriptorDatabase::DescriptorIndex<Value>::FindAllExtensionNumbers( + const std::string& containing_type, std::vector<int>* output) { + typename std::map<std::pair<std::string, int>, Value>::const_iterator it = + by_extension_.lower_bound(std::make_pair(containing_type, 0)); + bool success = false; + + for (; it != by_extension_.end() && it->first.first == containing_type; + ++it) { + output->push_back(it->first.second); + success = true; + } + + return success; +} + +template <typename Value> +void SimpleDescriptorDatabase::DescriptorIndex<Value>::FindAllFileNames( + std::vector<std::string>* output) { + output->resize(by_name_.size()); + int i = 0; + for (const auto& kv : by_name_) { + (*output)[i] = kv.first; + i++; + } +} + +// ------------------------------------------------------------------- + +bool SimpleDescriptorDatabase::Add(const FileDescriptorProto& file) { + FileDescriptorProto* new_file = new FileDescriptorProto; + new_file->CopyFrom(file); + return AddAndOwn(new_file); +} + +bool SimpleDescriptorDatabase::AddAndOwn(const FileDescriptorProto* file) { + files_to_delete_.emplace_back(file); + return index_.AddFile(*file, file); +} + +bool SimpleDescriptorDatabase::FindFileByName(const std::string& filename, + FileDescriptorProto* output) { + return MaybeCopy(index_.FindFile(filename), output); +} + +bool SimpleDescriptorDatabase::FindFileContainingSymbol( + const std::string& symbol_name, FileDescriptorProto* output) { + return MaybeCopy(index_.FindSymbol(symbol_name), output); +} + +bool SimpleDescriptorDatabase::FindFileContainingExtension( + const std::string& containing_type, int field_number, + FileDescriptorProto* output) { + return MaybeCopy(index_.FindExtension(containing_type, field_number), output); +} + +bool SimpleDescriptorDatabase::FindAllExtensionNumbers( + const std::string& extendee_type, std::vector<int>* output) { + return index_.FindAllExtensionNumbers(extendee_type, output); +} + + +bool SimpleDescriptorDatabase::FindAllFileNames( + std::vector<std::string>* output) { + index_.FindAllFileNames(output); + return true; +} + +bool SimpleDescriptorDatabase::MaybeCopy(const FileDescriptorProto* file, + FileDescriptorProto* output) { + if (file == nullptr) return false; + output->CopyFrom(*file); + return true; +} + +// ------------------------------------------------------------------- + +class EncodedDescriptorDatabase::DescriptorIndex { + public: + using Value = std::pair<const void*, int>; + // Helpers to recursively add particular descriptors and all their contents + // to the index. + template <typename FileProto> + bool AddFile(const FileProto& file, Value value); + + Value FindFile(StringPiece filename); + Value FindSymbol(StringPiece name); + Value FindSymbolOnlyFlat(StringPiece name) const; + Value FindExtension(StringPiece containing_type, int field_number); + bool FindAllExtensionNumbers(StringPiece containing_type, + std::vector<int>* output); + void FindAllFileNames(std::vector<std::string>* output) const; + + private: + friend class EncodedDescriptorDatabase; + + bool AddSymbol(StringPiece symbol); + + template <typename DescProto> + bool AddNestedExtensions(StringPiece filename, + const DescProto& message_type); + template <typename FieldProto> + bool AddExtension(StringPiece filename, const FieldProto& field); + + // All the maps below have two representations: + // - a std::set<> where we insert initially. + // - a std::vector<> where we flatten the structure on demand. + // The initial tree helps avoid O(N) behavior of inserting into a sorted + // vector, while the vector reduces the heap requirements of the data + // structure. + + void EnsureFlat(); + + using String = std::string; + + String EncodeString(StringPiece str) const { return String(str); } + StringPiece DecodeString(const String& str, int) const { return str; } + + struct EncodedEntry { + // Do not use `Value` here to avoid the padding of that object. + const void* data; + int size; + // Keep the package here instead of each SymbolEntry to save space. + String encoded_package; + + Value value() const { return {data, size}; } + }; + std::vector<EncodedEntry> all_values_; + + struct FileEntry { + int data_offset; + String encoded_name; + + StringPiece name(const DescriptorIndex& index) const { + return index.DecodeString(encoded_name, data_offset); + } + }; + struct FileCompare { + const DescriptorIndex& index; + + bool operator()(const FileEntry& a, const FileEntry& b) const { + return a.name(index) < b.name(index); + } + bool operator()(const FileEntry& a, StringPiece b) const { + return a.name(index) < b; + } + bool operator()(StringPiece a, const FileEntry& b) const { + return a < b.name(index); + } + }; + std::set<FileEntry, FileCompare> by_name_{FileCompare{*this}}; + std::vector<FileEntry> by_name_flat_; + + struct SymbolEntry { + int data_offset; + String encoded_symbol; + + StringPiece package(const DescriptorIndex& index) const { + return index.DecodeString(index.all_values_[data_offset].encoded_package, + data_offset); + } + StringPiece symbol(const DescriptorIndex& index) const { + return index.DecodeString(encoded_symbol, data_offset); + } + + std::string AsString(const DescriptorIndex& index) const { + auto p = package(index); + return StrCat(p, p.empty() ? "" : ".", symbol(index)); + } + }; + + struct SymbolCompare { + const DescriptorIndex& index; + + std::string AsString(const SymbolEntry& entry) const { + return entry.AsString(index); + } + static StringPiece AsString(StringPiece str) { return str; } + + std::pair<StringPiece, StringPiece> GetParts( + const SymbolEntry& entry) const { + auto package = entry.package(index); + if (package.empty()) return {entry.symbol(index), StringPiece{}}; + return {package, entry.symbol(index)}; + } + std::pair<StringPiece, StringPiece> GetParts( + StringPiece str) const { + return {str, {}}; + } + + template <typename T, typename U> + bool operator()(const T& lhs, const U& rhs) const { + auto lhs_parts = GetParts(lhs); + auto rhs_parts = GetParts(rhs); + + // Fast path to avoid making the whole string for common cases. + if (int res = + lhs_parts.first.substr(0, rhs_parts.first.size()) + .compare(rhs_parts.first.substr(0, lhs_parts.first.size()))) { + // If the packages already differ, exit early. + return res < 0; + } else if (lhs_parts.first.size() == rhs_parts.first.size()) { + return lhs_parts.second < rhs_parts.second; + } + return AsString(lhs) < AsString(rhs); + } + }; + std::set<SymbolEntry, SymbolCompare> by_symbol_{SymbolCompare{*this}}; + std::vector<SymbolEntry> by_symbol_flat_; + + struct ExtensionEntry { + int data_offset; + String encoded_extendee; + StringPiece extendee(const DescriptorIndex& index) const { + return index.DecodeString(encoded_extendee, data_offset).substr(1); + } + int extension_number; + }; + struct ExtensionCompare { + const DescriptorIndex& index; + + bool operator()(const ExtensionEntry& a, const ExtensionEntry& b) const { + return std::make_tuple(a.extendee(index), a.extension_number) < + std::make_tuple(b.extendee(index), b.extension_number); + } + bool operator()(const ExtensionEntry& a, + std::tuple<StringPiece, int> b) const { + return std::make_tuple(a.extendee(index), a.extension_number) < b; + } + bool operator()(std::tuple<StringPiece, int> a, + const ExtensionEntry& b) const { + return a < std::make_tuple(b.extendee(index), b.extension_number); + } + }; + std::set<ExtensionEntry, ExtensionCompare> by_extension_{ + ExtensionCompare{*this}}; + std::vector<ExtensionEntry> by_extension_flat_; +}; + +bool EncodedDescriptorDatabase::Add(const void* encoded_file_descriptor, + int size) { + FileDescriptorProto file; + if (file.ParseFromArray(encoded_file_descriptor, size)) { + return index_->AddFile(file, std::make_pair(encoded_file_descriptor, size)); + } else { + GOOGLE_LOG(ERROR) << "Invalid file descriptor data passed to " + "EncodedDescriptorDatabase::Add()."; + return false; + } +} + +bool EncodedDescriptorDatabase::AddCopy(const void* encoded_file_descriptor, + int size) { + void* copy = operator new(size); + memcpy(copy, encoded_file_descriptor, size); + files_to_delete_.push_back(copy); + return Add(copy, size); +} + +bool EncodedDescriptorDatabase::FindFileByName(const std::string& filename, + FileDescriptorProto* output) { + return MaybeParse(index_->FindFile(filename), output); +} + +bool EncodedDescriptorDatabase::FindFileContainingSymbol( + const std::string& symbol_name, FileDescriptorProto* output) { + return MaybeParse(index_->FindSymbol(symbol_name), output); +} + +bool EncodedDescriptorDatabase::FindNameOfFileContainingSymbol( + const std::string& symbol_name, std::string* output) { + auto encoded_file = index_->FindSymbol(symbol_name); + if (encoded_file.first == nullptr) return false; + + // Optimization: The name should be the first field in the encoded message. + // Try to just read it directly. + io::CodedInputStream input(static_cast<const uint8_t*>(encoded_file.first), + encoded_file.second); + + const uint32_t kNameTag = internal::WireFormatLite::MakeTag( + FileDescriptorProto::kNameFieldNumber, + internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED); + + if (input.ReadTagNoLastTag() == kNameTag) { + // Success! + return internal::WireFormatLite::ReadString(&input, output); + } else { + // Slow path. Parse whole message. + FileDescriptorProto file_proto; + if (!file_proto.ParseFromArray(encoded_file.first, encoded_file.second)) { + return false; + } + *output = file_proto.name(); + return true; + } +} + +bool EncodedDescriptorDatabase::FindFileContainingExtension( + const std::string& containing_type, int field_number, + FileDescriptorProto* output) { + return MaybeParse(index_->FindExtension(containing_type, field_number), + output); +} + +bool EncodedDescriptorDatabase::FindAllExtensionNumbers( + const std::string& extendee_type, std::vector<int>* output) { + return index_->FindAllExtensionNumbers(extendee_type, output); +} + +template <typename FileProto> +bool EncodedDescriptorDatabase::DescriptorIndex::AddFile(const FileProto& file, + Value value) { + // We push `value` into the array first. This is important because the AddXXX + // functions below will expect it to be there. + all_values_.push_back({value.first, value.second, {}}); + + if (!ValidateSymbolName(file.package())) { + GOOGLE_LOG(ERROR) << "Invalid package name: " << file.package(); + return false; + } + all_values_.back().encoded_package = EncodeString(file.package()); + + if (!InsertIfNotPresent( + &by_name_, FileEntry{static_cast<int>(all_values_.size() - 1), + EncodeString(file.name())}) || + std::binary_search(by_name_flat_.begin(), by_name_flat_.end(), + file.name(), by_name_.key_comp())) { + GOOGLE_LOG(ERROR) << "File already exists in database: " << file.name(); + return false; + } + + for (const auto& message_type : file.message_type()) { + if (!AddSymbol(message_type.name())) return false; + if (!AddNestedExtensions(file.name(), message_type)) return false; + } + for (const auto& enum_type : file.enum_type()) { + if (!AddSymbol(enum_type.name())) return false; + } + for (const auto& extension : file.extension()) { + if (!AddSymbol(extension.name())) return false; + if (!AddExtension(file.name(), extension)) return false; + } + for (const auto& service : file.service()) { + if (!AddSymbol(service.name())) return false; + } + + return true; +} + +template <typename Iter, typename Iter2, typename Index> +static bool CheckForMutualSubsymbols(StringPiece symbol_name, Iter* iter, + Iter2 end, const Index& index) { + if (*iter != end) { + if (IsSubSymbol((*iter)->AsString(index), symbol_name)) { + GOOGLE_LOG(ERROR) << "Symbol name \"" << symbol_name + << "\" conflicts with the existing symbol \"" + << (*iter)->AsString(index) << "\"."; + return false; + } + + // OK, that worked. Now we have to make sure that no symbol in the map is + // a sub-symbol of the one we are inserting. The only symbol which could + // be so is the first symbol that is greater than the new symbol. Since + // |iter| points at the last symbol that is less than or equal, we just have + // to increment it. + ++*iter; + + if (*iter != end && IsSubSymbol(symbol_name, (*iter)->AsString(index))) { + GOOGLE_LOG(ERROR) << "Symbol name \"" << symbol_name + << "\" conflicts with the existing symbol \"" + << (*iter)->AsString(index) << "\"."; + return false; + } + } + return true; +} + +bool EncodedDescriptorDatabase::DescriptorIndex::AddSymbol( + StringPiece symbol) { + SymbolEntry entry = {static_cast<int>(all_values_.size() - 1), + EncodeString(symbol)}; + std::string entry_as_string = entry.AsString(*this); + + // We need to make sure not to violate our map invariant. + + // If the symbol name is invalid it could break our lookup algorithm (which + // relies on the fact that '.' sorts before all other characters that are + // valid in symbol names). + if (!ValidateSymbolName(symbol)) { + GOOGLE_LOG(ERROR) << "Invalid symbol name: " << entry_as_string; + return false; + } + + auto iter = FindLastLessOrEqual(&by_symbol_, entry); + if (!CheckForMutualSubsymbols(entry_as_string, &iter, by_symbol_.end(), + *this)) { + return false; + } + + // Same, but on by_symbol_flat_ + auto flat_iter = + FindLastLessOrEqual(&by_symbol_flat_, entry, by_symbol_.key_comp()); + if (!CheckForMutualSubsymbols(entry_as_string, &flat_iter, + by_symbol_flat_.end(), *this)) { + return false; + } + + // OK, no conflicts. + + // Insert the new symbol using the iterator as a hint, the new entry will + // appear immediately before the one the iterator is pointing at. + by_symbol_.insert(iter, entry); + + return true; +} + +template <typename DescProto> +bool EncodedDescriptorDatabase::DescriptorIndex::AddNestedExtensions( + StringPiece filename, const DescProto& message_type) { + for (const auto& nested_type : message_type.nested_type()) { + if (!AddNestedExtensions(filename, nested_type)) return false; + } + for (const auto& extension : message_type.extension()) { + if (!AddExtension(filename, extension)) return false; + } + return true; +} + +template <typename FieldProto> +bool EncodedDescriptorDatabase::DescriptorIndex::AddExtension( + StringPiece filename, const FieldProto& field) { + if (!field.extendee().empty() && field.extendee()[0] == '.') { + // The extension is fully-qualified. We can use it as a lookup key in + // the by_symbol_ table. + if (!InsertIfNotPresent( + &by_extension_, + ExtensionEntry{static_cast<int>(all_values_.size() - 1), + EncodeString(field.extendee()), field.number()}) || + std::binary_search( + by_extension_flat_.begin(), by_extension_flat_.end(), + std::make_pair(field.extendee().substr(1), field.number()), + by_extension_.key_comp())) { + GOOGLE_LOG(ERROR) << "Extension conflicts with extension already in database: " + "extend " + << field.extendee() << " { " << field.name() << " = " + << field.number() << " } from:" << filename; + return false; + } + } else { + // Not fully-qualified. We can't really do anything here, unfortunately. + // We don't consider this an error, though, because the descriptor is + // valid. + } + return true; +} + +std::pair<const void*, int> +EncodedDescriptorDatabase::DescriptorIndex::FindSymbol(StringPiece name) { + EnsureFlat(); + return FindSymbolOnlyFlat(name); +} + +std::pair<const void*, int> +EncodedDescriptorDatabase::DescriptorIndex::FindSymbolOnlyFlat( + StringPiece name) const { + auto iter = + FindLastLessOrEqual(&by_symbol_flat_, name, by_symbol_.key_comp()); + + return iter != by_symbol_flat_.end() && + IsSubSymbol(iter->AsString(*this), name) + ? all_values_[iter->data_offset].value() + : Value(); +} + +std::pair<const void*, int> +EncodedDescriptorDatabase::DescriptorIndex::FindExtension( + StringPiece containing_type, int field_number) { + EnsureFlat(); + + auto it = std::lower_bound( + by_extension_flat_.begin(), by_extension_flat_.end(), + std::make_tuple(containing_type, field_number), by_extension_.key_comp()); + return it == by_extension_flat_.end() || + it->extendee(*this) != containing_type || + it->extension_number != field_number + ? std::make_pair(nullptr, 0) + : all_values_[it->data_offset].value(); +} + +template <typename T, typename Less> +static void MergeIntoFlat(std::set<T, Less>* s, std::vector<T>* flat) { + if (s->empty()) return; + std::vector<T> new_flat(s->size() + flat->size()); + std::merge(s->begin(), s->end(), flat->begin(), flat->end(), &new_flat[0], + s->key_comp()); + *flat = std::move(new_flat); + s->clear(); +} + +void EncodedDescriptorDatabase::DescriptorIndex::EnsureFlat() { + all_values_.shrink_to_fit(); + // Merge each of the sets into their flat counterpart. + MergeIntoFlat(&by_name_, &by_name_flat_); + MergeIntoFlat(&by_symbol_, &by_symbol_flat_); + MergeIntoFlat(&by_extension_, &by_extension_flat_); +} + +bool EncodedDescriptorDatabase::DescriptorIndex::FindAllExtensionNumbers( + StringPiece containing_type, std::vector<int>* output) { + EnsureFlat(); + + bool success = false; + auto it = std::lower_bound( + by_extension_flat_.begin(), by_extension_flat_.end(), + std::make_tuple(containing_type, 0), by_extension_.key_comp()); + for (; + it != by_extension_flat_.end() && it->extendee(*this) == containing_type; + ++it) { + output->push_back(it->extension_number); + success = true; + } + + return success; +} + +void EncodedDescriptorDatabase::DescriptorIndex::FindAllFileNames( + std::vector<std::string>* output) const { + output->resize(by_name_.size() + by_name_flat_.size()); + int i = 0; + for (const auto& entry : by_name_) { + (*output)[i] = std::string(entry.name(*this)); + i++; + } + for (const auto& entry : by_name_flat_) { + (*output)[i] = std::string(entry.name(*this)); + i++; + } +} + +std::pair<const void*, int> +EncodedDescriptorDatabase::DescriptorIndex::FindFile( + StringPiece filename) { + EnsureFlat(); + + auto it = std::lower_bound(by_name_flat_.begin(), by_name_flat_.end(), + filename, by_name_.key_comp()); + return it == by_name_flat_.end() || it->name(*this) != filename + ? std::make_pair(nullptr, 0) + : all_values_[it->data_offset].value(); +} + + +bool EncodedDescriptorDatabase::FindAllFileNames( + std::vector<std::string>* output) { + index_->FindAllFileNames(output); + return true; +} + +bool EncodedDescriptorDatabase::MaybeParse( + std::pair<const void*, int> encoded_file, FileDescriptorProto* output) { + if (encoded_file.first == nullptr) return false; + return output->ParseFromArray(encoded_file.first, encoded_file.second); +} + +EncodedDescriptorDatabase::EncodedDescriptorDatabase() + : index_(new DescriptorIndex()) {} + +EncodedDescriptorDatabase::~EncodedDescriptorDatabase() { + for (void* p : files_to_delete_) { + operator delete(p); + } +} + +// =================================================================== + +DescriptorPoolDatabase::DescriptorPoolDatabase(const DescriptorPool& pool) + : pool_(pool) {} +DescriptorPoolDatabase::~DescriptorPoolDatabase() {} + +bool DescriptorPoolDatabase::FindFileByName(const std::string& filename, + FileDescriptorProto* output) { + const FileDescriptor* file = pool_.FindFileByName(filename); + if (file == nullptr) return false; + output->Clear(); + file->CopyTo(output); + return true; +} + +bool DescriptorPoolDatabase::FindFileContainingSymbol( + const std::string& symbol_name, FileDescriptorProto* output) { + const FileDescriptor* file = pool_.FindFileContainingSymbol(symbol_name); + if (file == nullptr) return false; + output->Clear(); + file->CopyTo(output); + return true; +} + +bool DescriptorPoolDatabase::FindFileContainingExtension( + const std::string& containing_type, int field_number, + FileDescriptorProto* output) { + const Descriptor* extendee = pool_.FindMessageTypeByName(containing_type); + if (extendee == nullptr) return false; + + const FieldDescriptor* extension = + pool_.FindExtensionByNumber(extendee, field_number); + if (extension == nullptr) return false; + + output->Clear(); + extension->file()->CopyTo(output); + return true; +} + +bool DescriptorPoolDatabase::FindAllExtensionNumbers( + const std::string& extendee_type, std::vector<int>* output) { + const Descriptor* extendee = pool_.FindMessageTypeByName(extendee_type); + if (extendee == nullptr) return false; + + std::vector<const FieldDescriptor*> extensions; + pool_.FindAllExtensions(extendee, &extensions); + + for (const FieldDescriptor* extension : extensions) { + output->push_back(extension->number()); + } + + return true; +} + +// =================================================================== + +MergedDescriptorDatabase::MergedDescriptorDatabase( + DescriptorDatabase* source1, DescriptorDatabase* source2) { + sources_.push_back(source1); + sources_.push_back(source2); +} +MergedDescriptorDatabase::MergedDescriptorDatabase( + const std::vector<DescriptorDatabase*>& sources) + : sources_(sources) {} +MergedDescriptorDatabase::~MergedDescriptorDatabase() {} + +bool MergedDescriptorDatabase::FindFileByName(const std::string& filename, + FileDescriptorProto* output) { + for (DescriptorDatabase* source : sources_) { + if (source->FindFileByName(filename, output)) { + return true; + } + } + return false; +} + +bool MergedDescriptorDatabase::FindFileContainingSymbol( + const std::string& symbol_name, FileDescriptorProto* output) { + for (size_t i = 0; i < sources_.size(); i++) { + if (sources_[i]->FindFileContainingSymbol(symbol_name, output)) { + // The symbol was found in source i. However, if one of the previous + // sources defines a file with the same name (which presumably doesn't + // contain the symbol, since it wasn't found in that source), then we + // must hide it from the caller. + FileDescriptorProto temp; + for (size_t j = 0; j < i; j++) { + if (sources_[j]->FindFileByName(output->name(), &temp)) { + // Found conflicting file in a previous source. + return false; + } + } + return true; + } + } + return false; +} + +bool MergedDescriptorDatabase::FindFileContainingExtension( + const std::string& containing_type, int field_number, + FileDescriptorProto* output) { + for (size_t i = 0; i < sources_.size(); i++) { + if (sources_[i]->FindFileContainingExtension(containing_type, field_number, + output)) { + // The symbol was found in source i. However, if one of the previous + // sources defines a file with the same name (which presumably doesn't + // contain the symbol, since it wasn't found in that source), then we + // must hide it from the caller. + FileDescriptorProto temp; + for (size_t j = 0; j < i; j++) { + if (sources_[j]->FindFileByName(output->name(), &temp)) { + // Found conflicting file in a previous source. + return false; + } + } + return true; + } + } + return false; +} + +bool MergedDescriptorDatabase::FindAllExtensionNumbers( + const std::string& extendee_type, std::vector<int>* output) { + std::set<int> merged_results; + std::vector<int> results; + bool success = false; + + for (DescriptorDatabase* source : sources_) { + if (source->FindAllExtensionNumbers(extendee_type, &results)) { + std::copy(results.begin(), results.end(), + std::insert_iterator<std::set<int> >(merged_results, + merged_results.begin())); + success = true; + } + results.clear(); + } + + std::copy(merged_results.begin(), merged_results.end(), + std::insert_iterator<std::vector<int> >(*output, output->end())); + + return success; +} + + +bool MergedDescriptorDatabase::FindAllFileNames( + std::vector<std::string>* output) { + bool implemented = false; + for (DescriptorDatabase* source : sources_) { + std::vector<std::string> source_output; + if (source->FindAllFileNames(&source_output)) { + output->reserve(output->size() + source_output.size()); + for (auto& source : source_output) { + output->push_back(std::move(source)); + } + implemented = true; + } + } + return implemented; +} + +} // namespace protobuf +} // namespace google diff --git a/toolkit/components/protobuf/src/google/protobuf/descriptor_database.h b/toolkit/components/protobuf/src/google/protobuf/descriptor_database.h new file mode 100644 index 0000000000..f4f06bbfa6 --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/descriptor_database.h @@ -0,0 +1,398 @@ +// 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. + +// Author: kenton@google.com (Kenton Varda) +// Based on original Protocol Buffers design by +// Sanjay Ghemawat, Jeff Dean, and others. +// +// Interface for manipulating databases of descriptors. + +#ifndef GOOGLE_PROTOBUF_DESCRIPTOR_DATABASE_H__ +#define GOOGLE_PROTOBUF_DESCRIPTOR_DATABASE_H__ + + +#include <map> +#include <string> +#include <utility> +#include <vector> + +#include <google/protobuf/stubs/common.h> +#include <google/protobuf/descriptor.h> + +// Must be included last. +#include <google/protobuf/port_def.inc> + +#ifdef SWIG +#error "You cannot SWIG proto headers" +#endif + +namespace google { +namespace protobuf { + +// Defined in this file. +class DescriptorDatabase; +class SimpleDescriptorDatabase; +class EncodedDescriptorDatabase; +class DescriptorPoolDatabase; +class MergedDescriptorDatabase; + +// Abstract interface for a database of descriptors. +// +// This is useful if you want to create a DescriptorPool which loads +// descriptors on-demand from some sort of large database. If the database +// is large, it may be inefficient to enumerate every .proto file inside it +// calling DescriptorPool::BuildFile() for each one. Instead, a DescriptorPool +// can be created which wraps a DescriptorDatabase and only builds particular +// descriptors when they are needed. +class PROTOBUF_EXPORT DescriptorDatabase { + public: + inline DescriptorDatabase() {} + virtual ~DescriptorDatabase(); + + // Find a file by file name. Fills in in *output and returns true if found. + // Otherwise, returns false, leaving the contents of *output undefined. + virtual bool FindFileByName(const std::string& filename, + FileDescriptorProto* output) = 0; + + // Find the file that declares the given fully-qualified symbol name. + // If found, fills in *output and returns true, otherwise returns false + // and leaves *output undefined. + virtual bool FindFileContainingSymbol(const std::string& symbol_name, + FileDescriptorProto* output) = 0; + + // Find the file which defines an extension extending the given message type + // with the given field number. If found, fills in *output and returns true, + // otherwise returns false and leaves *output undefined. containing_type + // must be a fully-qualified type name. + virtual bool FindFileContainingExtension(const std::string& containing_type, + int field_number, + FileDescriptorProto* output) = 0; + + // Finds the tag numbers used by all known extensions of + // extendee_type, and appends them to output in an undefined + // order. This method is best-effort: it's not guaranteed that the + // database will find all extensions, and it's not guaranteed that + // FindFileContainingExtension will return true on all of the found + // numbers. Returns true if the search was successful, otherwise + // returns false and leaves output unchanged. + // + // This method has a default implementation that always returns + // false. + virtual bool FindAllExtensionNumbers(const std::string& /* extendee_type */, + std::vector<int>* /* output */) { + return false; + } + + + // Finds the file names and appends them to the output in an + // undefined order. This method is best-effort: it's not guaranteed that the + // database will find all files. Returns true if the database supports + // searching all file names, otherwise returns false and leaves output + // unchanged. + // + // This method has a default implementation that always returns + // false. + virtual bool FindAllFileNames(std::vector<std::string>* /*output*/) { + return false; + } + + // Finds the package names and appends them to the output in an + // undefined order. This method is best-effort: it's not guaranteed that the + // database will find all packages. Returns true if the database supports + // searching all package names, otherwise returns false and leaves output + // unchanged. + bool FindAllPackageNames(std::vector<std::string>* output); + + // Finds the message names and appends them to the output in an + // undefined order. This method is best-effort: it's not guaranteed that the + // database will find all messages. Returns true if the database supports + // searching all message names, otherwise returns false and leaves output + // unchanged. + bool FindAllMessageNames(std::vector<std::string>* output); + + private: + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(DescriptorDatabase); +}; + +// A DescriptorDatabase into which you can insert files manually. +// +// FindFileContainingSymbol() is fully-implemented. When you add a file, its +// symbols will be indexed for this purpose. Note that the implementation +// may return false positives, but only if it isn't possible for the symbol +// to be defined in any other file. In particular, if a file defines a symbol +// "Foo", then searching for "Foo.[anything]" will match that file. This way, +// the database does not need to aggressively index all children of a symbol. +// +// FindFileContainingExtension() is mostly-implemented. It works if and only +// if the original FieldDescriptorProto defining the extension has a +// fully-qualified type name in its "extendee" field (i.e. starts with a '.'). +// If the extendee is a relative name, SimpleDescriptorDatabase will not +// attempt to resolve the type, so it will not know what type the extension is +// extending. Therefore, calling FindFileContainingExtension() with the +// extension's containing type will never actually find that extension. Note +// that this is an unlikely problem, as all FileDescriptorProtos created by the +// protocol compiler (as well as ones created by calling +// FileDescriptor::CopyTo()) will always use fully-qualified names for all +// types. You only need to worry if you are constructing FileDescriptorProtos +// yourself, or are calling compiler::Parser directly. +class PROTOBUF_EXPORT SimpleDescriptorDatabase : public DescriptorDatabase { + public: + SimpleDescriptorDatabase(); + ~SimpleDescriptorDatabase() override; + + // Adds the FileDescriptorProto to the database, making a copy. The object + // can be deleted after Add() returns. Returns false if the file conflicted + // with a file already in the database, in which case an error will have + // been written to GOOGLE_LOG(ERROR). + bool Add(const FileDescriptorProto& file); + + // Adds the FileDescriptorProto to the database and takes ownership of it. + bool AddAndOwn(const FileDescriptorProto* file); + + // implements DescriptorDatabase ----------------------------------- + bool FindFileByName(const std::string& filename, + FileDescriptorProto* output) override; + bool FindFileContainingSymbol(const std::string& symbol_name, + FileDescriptorProto* output) override; + bool FindFileContainingExtension(const std::string& containing_type, + int field_number, + FileDescriptorProto* output) override; + bool FindAllExtensionNumbers(const std::string& extendee_type, + std::vector<int>* output) override; + + bool FindAllFileNames(std::vector<std::string>* output) override; + + private: + // An index mapping file names, symbol names, and extension numbers to + // some sort of values. + template <typename Value> + class DescriptorIndex { + public: + // Helpers to recursively add particular descriptors and all their contents + // to the index. + bool AddFile(const FileDescriptorProto& file, Value value); + bool AddSymbol(const std::string& name, Value value); + bool AddNestedExtensions(const std::string& filename, + const DescriptorProto& message_type, Value value); + bool AddExtension(const std::string& filename, + const FieldDescriptorProto& field, Value value); + + Value FindFile(const std::string& filename); + Value FindSymbol(const std::string& name); + Value FindExtension(const std::string& containing_type, int field_number); + bool FindAllExtensionNumbers(const std::string& containing_type, + std::vector<int>* output); + void FindAllFileNames(std::vector<std::string>* output); + + private: + std::map<std::string, Value> by_name_; + std::map<std::string, Value> by_symbol_; + std::map<std::pair<std::string, int>, Value> by_extension_; + + // Invariant: The by_symbol_ map does not contain any symbols which are + // prefixes of other symbols in the map. For example, "foo.bar" is a + // prefix of "foo.bar.baz" (but is not a prefix of "foo.barbaz"). + // + // This invariant is important because it means that given a symbol name, + // we can find a key in the map which is a prefix of the symbol in O(lg n) + // time, and we know that there is at most one such key. + // + // The prefix lookup algorithm works like so: + // 1) Find the last key in the map which is less than or equal to the + // search key. + // 2) If the found key is a prefix of the search key, then return it. + // Otherwise, there is no match. + // + // I am sure this algorithm has been described elsewhere, but since I + // wasn't able to find it quickly I will instead prove that it works + // myself. The key to the algorithm is that if a match exists, step (1) + // will find it. Proof: + // 1) Define the "search key" to be the key we are looking for, the "found + // key" to be the key found in step (1), and the "match key" to be the + // key which actually matches the search key (i.e. the key we're trying + // to find). + // 2) The found key must be less than or equal to the search key by + // definition. + // 3) The match key must also be less than or equal to the search key + // (because it is a prefix). + // 4) The match key cannot be greater than the found key, because if it + // were, then step (1) of the algorithm would have returned the match + // key instead (since it finds the *greatest* key which is less than or + // equal to the search key). + // 5) Therefore, the found key must be between the match key and the search + // key, inclusive. + // 6) Since the search key must be a sub-symbol of the match key, if it is + // not equal to the match key, then search_key[match_key.size()] must + // be '.'. + // 7) Since '.' sorts before any other character that is valid in a symbol + // name, then if the found key is not equal to the match key, then + // found_key[match_key.size()] must also be '.', because any other value + // would make it sort after the search key. + // 8) Therefore, if the found key is not equal to the match key, then the + // found key must be a sub-symbol of the match key. However, this would + // contradict our map invariant which says that no symbol in the map is + // a sub-symbol of any other. + // 9) Therefore, the found key must match the match key. + // + // The above proof assumes the match key exists. In the case that the + // match key does not exist, then step (1) will return some other symbol. + // That symbol cannot be a super-symbol of the search key since if it were, + // then it would be a match, and we're assuming the match key doesn't exist. + // Therefore, step 2 will correctly return no match. + }; + + DescriptorIndex<const FileDescriptorProto*> index_; + std::vector<std::unique_ptr<const FileDescriptorProto>> files_to_delete_; + + // If file is non-nullptr, copy it into *output and return true, otherwise + // return false. + bool MaybeCopy(const FileDescriptorProto* file, FileDescriptorProto* output); + + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(SimpleDescriptorDatabase); +}; + +// Very similar to SimpleDescriptorDatabase, but stores all the descriptors +// as raw bytes and generally tries to use as little memory as possible. +// +// The same caveats regarding FindFileContainingExtension() apply as with +// SimpleDescriptorDatabase. +class PROTOBUF_EXPORT EncodedDescriptorDatabase : public DescriptorDatabase { + public: + EncodedDescriptorDatabase(); + ~EncodedDescriptorDatabase() override; + + // Adds the FileDescriptorProto to the database. The descriptor is provided + // in encoded form. The database does not make a copy of the bytes, nor + // does it take ownership; it's up to the caller to make sure the bytes + // remain valid for the life of the database. Returns false and logs an error + // if the bytes are not a valid FileDescriptorProto or if the file conflicted + // with a file already in the database. + bool Add(const void* encoded_file_descriptor, int size); + + // Like Add(), but makes a copy of the data, so that the caller does not + // need to keep it around. + bool AddCopy(const void* encoded_file_descriptor, int size); + + // Like FindFileContainingSymbol but returns only the name of the file. + bool FindNameOfFileContainingSymbol(const std::string& symbol_name, + std::string* output); + + // implements DescriptorDatabase ----------------------------------- + bool FindFileByName(const std::string& filename, + FileDescriptorProto* output) override; + bool FindFileContainingSymbol(const std::string& symbol_name, + FileDescriptorProto* output) override; + bool FindFileContainingExtension(const std::string& containing_type, + int field_number, + FileDescriptorProto* output) override; + bool FindAllExtensionNumbers(const std::string& extendee_type, + std::vector<int>* output) override; + bool FindAllFileNames(std::vector<std::string>* output) override; + + private: + class DescriptorIndex; + // Keep DescriptorIndex by pointer to hide the implementation to keep a + // cleaner header. + std::unique_ptr<DescriptorIndex> index_; + std::vector<void*> files_to_delete_; + + // If encoded_file.first is non-nullptr, parse the data into *output and + // return true, otherwise return false. + bool MaybeParse(std::pair<const void*, int> encoded_file, + FileDescriptorProto* output); + + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(EncodedDescriptorDatabase); +}; + +// A DescriptorDatabase that fetches files from a given pool. +class PROTOBUF_EXPORT DescriptorPoolDatabase : public DescriptorDatabase { + public: + explicit DescriptorPoolDatabase(const DescriptorPool& pool); + ~DescriptorPoolDatabase() override; + + // implements DescriptorDatabase ----------------------------------- + bool FindFileByName(const std::string& filename, + FileDescriptorProto* output) override; + bool FindFileContainingSymbol(const std::string& symbol_name, + FileDescriptorProto* output) override; + bool FindFileContainingExtension(const std::string& containing_type, + int field_number, + FileDescriptorProto* output) override; + bool FindAllExtensionNumbers(const std::string& extendee_type, + std::vector<int>* output) override; + + private: + const DescriptorPool& pool_; + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(DescriptorPoolDatabase); +}; + +// A DescriptorDatabase that wraps two or more others. It first searches the +// first database and, if that fails, tries the second, and so on. +class PROTOBUF_EXPORT MergedDescriptorDatabase : public DescriptorDatabase { + public: + // Merge just two databases. The sources remain property of the caller. + MergedDescriptorDatabase(DescriptorDatabase* source1, + DescriptorDatabase* source2); + // Merge more than two databases. The sources remain property of the caller. + // The vector may be deleted after the constructor returns but the + // DescriptorDatabases need to stick around. + explicit MergedDescriptorDatabase( + const std::vector<DescriptorDatabase*>& sources); + ~MergedDescriptorDatabase() override; + + // implements DescriptorDatabase ----------------------------------- + bool FindFileByName(const std::string& filename, + FileDescriptorProto* output) override; + bool FindFileContainingSymbol(const std::string& symbol_name, + FileDescriptorProto* output) override; + bool FindFileContainingExtension(const std::string& containing_type, + int field_number, + FileDescriptorProto* output) override; + // Merges the results of calling all databases. Returns true iff any + // of the databases returned true. + bool FindAllExtensionNumbers(const std::string& extendee_type, + std::vector<int>* output) override; + + + // This function is best-effort. Returns true if at least one underlying + // DescriptorDatabase returns true. + bool FindAllFileNames(std::vector<std::string>* output) override; + + private: + std::vector<DescriptorDatabase*> sources_; + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MergedDescriptorDatabase); +}; + +} // namespace protobuf +} // namespace google + +#include <google/protobuf/port_undef.inc> + +#endif // GOOGLE_PROTOBUF_DESCRIPTOR_DATABASE_H__ diff --git a/toolkit/components/protobuf/src/google/protobuf/duration.pb.cc b/toolkit/components/protobuf/src/google/protobuf/duration.pb.cc new file mode 100644 index 0000000000..72766bd3b4 --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/duration.pb.cc @@ -0,0 +1,307 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: google/protobuf/duration.proto + +#include <google/protobuf/duration.pb.h> + +#include <algorithm> + +#include <google/protobuf/io/coded_stream.h> +#include <google/protobuf/extension_set.h> +#include <google/protobuf/wire_format_lite.h> +#include <google/protobuf/descriptor.h> +#include <google/protobuf/generated_message_reflection.h> +#include <google/protobuf/reflection_ops.h> +#include <google/protobuf/wire_format.h> +// @@protoc_insertion_point(includes) +#include <google/protobuf/port_def.inc> + +PROTOBUF_PRAGMA_INIT_SEG + +namespace _pb = ::PROTOBUF_NAMESPACE_ID; +namespace _pbi = _pb::internal; + +PROTOBUF_NAMESPACE_OPEN +PROTOBUF_CONSTEXPR Duration::Duration( + ::_pbi::ConstantInitialized): _impl_{ + /*decltype(_impl_.seconds_)*/int64_t{0} + , /*decltype(_impl_.nanos_)*/0 + , /*decltype(_impl_._cached_size_)*/{}} {} +struct DurationDefaultTypeInternal { + PROTOBUF_CONSTEXPR DurationDefaultTypeInternal() + : _instance(::_pbi::ConstantInitialized{}) {} + ~DurationDefaultTypeInternal() {} + union { + Duration _instance; + }; +}; +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 DurationDefaultTypeInternal _Duration_default_instance_; +PROTOBUF_NAMESPACE_CLOSE +static ::_pb::Metadata file_level_metadata_google_2fprotobuf_2fduration_2eproto[1]; +static constexpr ::_pb::EnumDescriptor const** file_level_enum_descriptors_google_2fprotobuf_2fduration_2eproto = nullptr; +static constexpr ::_pb::ServiceDescriptor const** file_level_service_descriptors_google_2fprotobuf_2fduration_2eproto = nullptr; + +const uint32_t TableStruct_google_2fprotobuf_2fduration_2eproto::offsets[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = { + ~0u, // no _has_bits_ + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Duration, _internal_metadata_), + ~0u, // no _extensions_ + ~0u, // no _oneof_case_ + ~0u, // no _weak_field_map_ + ~0u, // no _inlined_string_donated_ + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Duration, _impl_.seconds_), + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Duration, _impl_.nanos_), +}; +static const ::_pbi::MigrationSchema schemas[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = { + { 0, -1, -1, sizeof(::PROTOBUF_NAMESPACE_ID::Duration)}, +}; + +static const ::_pb::Message* const file_default_instances[] = { + &::PROTOBUF_NAMESPACE_ID::_Duration_default_instance_._instance, +}; + +const char descriptor_table_protodef_google_2fprotobuf_2fduration_2eproto[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = + "\n\036google/protobuf/duration.proto\022\017google" + ".protobuf\"*\n\010Duration\022\017\n\007seconds\030\001 \001(\003\022\r" + "\n\005nanos\030\002 \001(\005B\203\001\n\023com.google.protobufB\rD" + "urationProtoP\001Z1google.golang.org/protob" + "uf/types/known/durationpb\370\001\001\242\002\003GPB\252\002\036Goo" + "gle.Protobuf.WellKnownTypesb\006proto3" + ; +static ::_pbi::once_flag descriptor_table_google_2fprotobuf_2fduration_2eproto_once; +const ::_pbi::DescriptorTable descriptor_table_google_2fprotobuf_2fduration_2eproto = { + false, false, 235, descriptor_table_protodef_google_2fprotobuf_2fduration_2eproto, + "google/protobuf/duration.proto", + &descriptor_table_google_2fprotobuf_2fduration_2eproto_once, nullptr, 0, 1, + schemas, file_default_instances, TableStruct_google_2fprotobuf_2fduration_2eproto::offsets, + file_level_metadata_google_2fprotobuf_2fduration_2eproto, file_level_enum_descriptors_google_2fprotobuf_2fduration_2eproto, + file_level_service_descriptors_google_2fprotobuf_2fduration_2eproto, +}; +PROTOBUF_ATTRIBUTE_WEAK const ::_pbi::DescriptorTable* descriptor_table_google_2fprotobuf_2fduration_2eproto_getter() { + return &descriptor_table_google_2fprotobuf_2fduration_2eproto; +} + +// Force running AddDescriptors() at dynamic initialization time. +PROTOBUF_ATTRIBUTE_INIT_PRIORITY2 static ::_pbi::AddDescriptorsRunner dynamic_init_dummy_google_2fprotobuf_2fduration_2eproto(&descriptor_table_google_2fprotobuf_2fduration_2eproto); +PROTOBUF_NAMESPACE_OPEN + +// =================================================================== + +class Duration::_Internal { + public: +}; + +Duration::Duration(::PROTOBUF_NAMESPACE_ID::Arena* arena, + bool is_message_owned) + : ::PROTOBUF_NAMESPACE_ID::Message(arena, is_message_owned) { + SharedCtor(arena, is_message_owned); + // @@protoc_insertion_point(arena_constructor:google.protobuf.Duration) +} +Duration::Duration(const Duration& from) + : ::PROTOBUF_NAMESPACE_ID::Message() { + Duration* const _this = this; (void)_this; + new (&_impl_) Impl_{ + decltype(_impl_.seconds_){} + , decltype(_impl_.nanos_){} + , /*decltype(_impl_._cached_size_)*/{}}; + + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); + ::memcpy(&_impl_.seconds_, &from._impl_.seconds_, + static_cast<size_t>(reinterpret_cast<char*>(&_impl_.nanos_) - + reinterpret_cast<char*>(&_impl_.seconds_)) + sizeof(_impl_.nanos_)); + // @@protoc_insertion_point(copy_constructor:google.protobuf.Duration) +} + +inline void Duration::SharedCtor( + ::_pb::Arena* arena, bool is_message_owned) { + (void)arena; + (void)is_message_owned; + new (&_impl_) Impl_{ + decltype(_impl_.seconds_){int64_t{0}} + , decltype(_impl_.nanos_){0} + , /*decltype(_impl_._cached_size_)*/{} + }; +} + +Duration::~Duration() { + // @@protoc_insertion_point(destructor:google.protobuf.Duration) + if (auto *arena = _internal_metadata_.DeleteReturnArena<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>()) { + (void)arena; + return; + } + SharedDtor(); +} + +inline void Duration::SharedDtor() { + GOOGLE_DCHECK(GetArenaForAllocation() == nullptr); +} + +void Duration::SetCachedSize(int size) const { + _impl_._cached_size_.Set(size); +} + +void Duration::Clear() { +// @@protoc_insertion_point(message_clear_start:google.protobuf.Duration) + uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + ::memset(&_impl_.seconds_, 0, static_cast<size_t>( + reinterpret_cast<char*>(&_impl_.nanos_) - + reinterpret_cast<char*>(&_impl_.seconds_)) + sizeof(_impl_.nanos_)); + _internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); +} + +const char* Duration::_InternalParse(const char* ptr, ::_pbi::ParseContext* ctx) { +#define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure + while (!ctx->Done(&ptr)) { + uint32_t tag; + ptr = ::_pbi::ReadTag(ptr, &tag); + switch (tag >> 3) { + // int64 seconds = 1; + case 1: + if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 8)) { + _impl_.seconds_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr); + CHK_(ptr); + } else + goto handle_unusual; + continue; + // int32 nanos = 2; + case 2: + if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 16)) { + _impl_.nanos_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint32(&ptr); + CHK_(ptr); + } else + goto handle_unusual; + continue; + default: + goto handle_unusual; + } // switch + handle_unusual: + if ((tag == 0) || ((tag & 7) == 4)) { + CHK_(ptr); + ctx->SetLastTag(tag); + goto message_done; + } + ptr = UnknownFieldParse( + tag, + _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(), + ptr, ctx); + CHK_(ptr != nullptr); + } // while +message_done: + return ptr; +failure: + ptr = nullptr; + goto message_done; +#undef CHK_ +} + +uint8_t* Duration::_InternalSerialize( + uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const { + // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.Duration) + uint32_t cached_has_bits = 0; + (void) cached_has_bits; + + // int64 seconds = 1; + if (this->_internal_seconds() != 0) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteInt64ToArray(1, this->_internal_seconds(), target); + } + + // int32 nanos = 2; + if (this->_internal_nanos() != 0) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteInt32ToArray(2, this->_internal_nanos(), target); + } + + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + target = ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( + _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.Duration) + return target; +} + +size_t Duration::ByteSizeLong() const { +// @@protoc_insertion_point(message_byte_size_start:google.protobuf.Duration) + size_t total_size = 0; + + uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + // int64 seconds = 1; + if (this->_internal_seconds() != 0) { + total_size += ::_pbi::WireFormatLite::Int64SizePlusOne(this->_internal_seconds()); + } + + // int32 nanos = 2; + if (this->_internal_nanos() != 0) { + total_size += ::_pbi::WireFormatLite::Int32SizePlusOne(this->_internal_nanos()); + } + + return MaybeComputeUnknownFieldsSize(total_size, &_impl_._cached_size_); +} + +const ::PROTOBUF_NAMESPACE_ID::Message::ClassData Duration::_class_data_ = { + ::PROTOBUF_NAMESPACE_ID::Message::CopyWithSourceCheck, + Duration::MergeImpl +}; +const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*Duration::GetClassData() const { return &_class_data_; } + + +void Duration::MergeImpl(::PROTOBUF_NAMESPACE_ID::Message& to_msg, const ::PROTOBUF_NAMESPACE_ID::Message& from_msg) { + auto* const _this = static_cast<Duration*>(&to_msg); + auto& from = static_cast<const Duration&>(from_msg); + // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.Duration) + GOOGLE_DCHECK_NE(&from, _this); + uint32_t cached_has_bits = 0; + (void) cached_has_bits; + + if (from._internal_seconds() != 0) { + _this->_internal_set_seconds(from._internal_seconds()); + } + if (from._internal_nanos() != 0) { + _this->_internal_set_nanos(from._internal_nanos()); + } + _this->_internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); +} + +void Duration::CopyFrom(const Duration& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.Duration) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool Duration::IsInitialized() const { + return true; +} + +void Duration::InternalSwap(Duration* other) { + using std::swap; + _internal_metadata_.InternalSwap(&other->_internal_metadata_); + ::PROTOBUF_NAMESPACE_ID::internal::memswap< + PROTOBUF_FIELD_OFFSET(Duration, _impl_.nanos_) + + sizeof(Duration::_impl_.nanos_) + - PROTOBUF_FIELD_OFFSET(Duration, _impl_.seconds_)>( + reinterpret_cast<char*>(&_impl_.seconds_), + reinterpret_cast<char*>(&other->_impl_.seconds_)); +} + +::PROTOBUF_NAMESPACE_ID::Metadata Duration::GetMetadata() const { + return ::_pbi::AssignDescriptors( + &descriptor_table_google_2fprotobuf_2fduration_2eproto_getter, &descriptor_table_google_2fprotobuf_2fduration_2eproto_once, + file_level_metadata_google_2fprotobuf_2fduration_2eproto[0]); +} + +// @@protoc_insertion_point(namespace_scope) +PROTOBUF_NAMESPACE_CLOSE +PROTOBUF_NAMESPACE_OPEN +template<> PROTOBUF_NOINLINE ::PROTOBUF_NAMESPACE_ID::Duration* +Arena::CreateMaybeMessage< ::PROTOBUF_NAMESPACE_ID::Duration >(Arena* arena) { + return Arena::CreateMessageInternal< ::PROTOBUF_NAMESPACE_ID::Duration >(arena); +} +PROTOBUF_NAMESPACE_CLOSE + +// @@protoc_insertion_point(global_scope) +#include <google/protobuf/port_undef.inc> diff --git a/toolkit/components/protobuf/src/google/protobuf/duration.pb.h b/toolkit/components/protobuf/src/google/protobuf/duration.pb.h new file mode 100644 index 0000000000..c4a94c5394 --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/duration.pb.h @@ -0,0 +1,278 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: google/protobuf/duration.proto + +#ifndef GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2fduration_2eproto +#define GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2fduration_2eproto + +#include <limits> +#include <string> + +#include <google/protobuf/port_def.inc> +#if PROTOBUF_VERSION < 3021000 +#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 3021006 < 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. +#endif + +#include <google/protobuf/port_undef.inc> +#include <google/protobuf/io/coded_stream.h> +#include <google/protobuf/arena.h> +#include <google/protobuf/arenastring.h> +#include <google/protobuf/generated_message_util.h> +#include <google/protobuf/metadata_lite.h> +#include <google/protobuf/generated_message_reflection.h> +#include <google/protobuf/message.h> +#include <google/protobuf/repeated_field.h> // IWYU pragma: export +#include <google/protobuf/extension_set.h> // IWYU pragma: export +#include <google/protobuf/unknown_field_set.h> +// @@protoc_insertion_point(includes) +#include <google/protobuf/port_def.inc> +#define PROTOBUF_INTERNAL_EXPORT_google_2fprotobuf_2fduration_2eproto PROTOBUF_EXPORT +PROTOBUF_NAMESPACE_OPEN +namespace internal { +class AnyMetadata; +} // namespace internal +PROTOBUF_NAMESPACE_CLOSE + +// Internal implementation detail -- do not use these members. +struct PROTOBUF_EXPORT TableStruct_google_2fprotobuf_2fduration_2eproto { + static const uint32_t offsets[]; +}; +PROTOBUF_EXPORT extern const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable descriptor_table_google_2fprotobuf_2fduration_2eproto; +PROTOBUF_NAMESPACE_OPEN +class Duration; +struct DurationDefaultTypeInternal; +PROTOBUF_EXPORT extern DurationDefaultTypeInternal _Duration_default_instance_; +PROTOBUF_NAMESPACE_CLOSE +PROTOBUF_NAMESPACE_OPEN +template<> PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::Duration* Arena::CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::Duration>(Arena*); +PROTOBUF_NAMESPACE_CLOSE +PROTOBUF_NAMESPACE_OPEN + +// =================================================================== + +class PROTOBUF_EXPORT Duration final : + public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.Duration) */ { + public: + inline Duration() : Duration(nullptr) {} + ~Duration() override; + explicit PROTOBUF_CONSTEXPR Duration(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized); + + Duration(const Duration& from); + Duration(Duration&& from) noexcept + : Duration() { + *this = ::std::move(from); + } + + inline Duration& operator=(const Duration& from) { + CopyFrom(from); + return *this; + } + inline Duration& operator=(Duration&& from) noexcept { + if (this == &from) return *this; + if (GetOwningArena() == from.GetOwningArena() + #ifdef PROTOBUF_FORCE_COPY_IN_MOVE + && GetOwningArena() != nullptr + #endif // !PROTOBUF_FORCE_COPY_IN_MOVE + ) { + InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* descriptor() { + return GetDescriptor(); + } + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() { + return default_instance().GetMetadata().descriptor; + } + static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() { + return default_instance().GetMetadata().reflection; + } + static const Duration& default_instance() { + return *internal_default_instance(); + } + static inline const Duration* internal_default_instance() { + return reinterpret_cast<const Duration*>( + &_Duration_default_instance_); + } + static constexpr int kIndexInFileMessages = + 0; + + friend void swap(Duration& a, Duration& b) { + a.Swap(&b); + } + inline void Swap(Duration* other) { + if (other == this) return; + #ifdef PROTOBUF_FORCE_COPY_IN_SWAP + if (GetOwningArena() != nullptr && + GetOwningArena() == other->GetOwningArena()) { + #else // PROTOBUF_FORCE_COPY_IN_SWAP + if (GetOwningArena() == other->GetOwningArena()) { + #endif // !PROTOBUF_FORCE_COPY_IN_SWAP + InternalSwap(other); + } else { + ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(Duration* other) { + if (other == this) return; + GOOGLE_DCHECK(GetOwningArena() == other->GetOwningArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + Duration* New(::PROTOBUF_NAMESPACE_ID::Arena* arena = nullptr) const final { + return CreateMaybeMessage<Duration>(arena); + } + using ::PROTOBUF_NAMESPACE_ID::Message::CopyFrom; + void CopyFrom(const Duration& from); + using ::PROTOBUF_NAMESPACE_ID::Message::MergeFrom; + void MergeFrom( const Duration& from) { + Duration::MergeImpl(*this, from); + } + private: + static void MergeImpl(::PROTOBUF_NAMESPACE_ID::Message& to_msg, const ::PROTOBUF_NAMESPACE_ID::Message& from_msg); + public: + PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + bool IsInitialized() const final; + + size_t ByteSizeLong() const final; + const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final; + uint8_t* _InternalSerialize( + uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final; + int GetCachedSize() const final { return _impl_._cached_size_.Get(); } + + private: + void SharedCtor(::PROTOBUF_NAMESPACE_ID::Arena* arena, bool is_message_owned); + void SharedDtor(); + void SetCachedSize(int size) const final; + void InternalSwap(Duration* other); + + private: + friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata; + static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() { + return "google.protobuf.Duration"; + } + protected: + explicit Duration(::PROTOBUF_NAMESPACE_ID::Arena* arena, + bool is_message_owned = false); + public: + + static const ClassData _class_data_; + const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*GetClassData() const final; + + ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final; + + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + + enum : int { + kSecondsFieldNumber = 1, + kNanosFieldNumber = 2, + }; + // int64 seconds = 1; + void clear_seconds(); + int64_t seconds() const; + void set_seconds(int64_t value); + private: + int64_t _internal_seconds() const; + void _internal_set_seconds(int64_t value); + public: + + // int32 nanos = 2; + void clear_nanos(); + int32_t nanos() const; + void set_nanos(int32_t value); + private: + int32_t _internal_nanos() const; + void _internal_set_nanos(int32_t value); + public: + + // @@protoc_insertion_point(class_scope:google.protobuf.Duration) + private: + class _Internal; + + template <typename T> friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper; + typedef void InternalArenaConstructable_; + typedef void DestructorSkippable_; + struct Impl_ { + int64_t seconds_; + int32_t nanos_; + mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_; + }; + union { Impl_ _impl_; }; + friend struct ::TableStruct_google_2fprotobuf_2fduration_2eproto; +}; +// =================================================================== + + +// =================================================================== + +#ifdef __GNUC__ + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wstrict-aliasing" +#endif // __GNUC__ +// Duration + +// int64 seconds = 1; +inline void Duration::clear_seconds() { + _impl_.seconds_ = int64_t{0}; +} +inline int64_t Duration::_internal_seconds() const { + return _impl_.seconds_; +} +inline int64_t Duration::seconds() const { + // @@protoc_insertion_point(field_get:google.protobuf.Duration.seconds) + return _internal_seconds(); +} +inline void Duration::_internal_set_seconds(int64_t value) { + + _impl_.seconds_ = value; +} +inline void Duration::set_seconds(int64_t value) { + _internal_set_seconds(value); + // @@protoc_insertion_point(field_set:google.protobuf.Duration.seconds) +} + +// int32 nanos = 2; +inline void Duration::clear_nanos() { + _impl_.nanos_ = 0; +} +inline int32_t Duration::_internal_nanos() const { + return _impl_.nanos_; +} +inline int32_t Duration::nanos() const { + // @@protoc_insertion_point(field_get:google.protobuf.Duration.nanos) + return _internal_nanos(); +} +inline void Duration::_internal_set_nanos(int32_t value) { + + _impl_.nanos_ = value; +} +inline void Duration::set_nanos(int32_t value) { + _internal_set_nanos(value); + // @@protoc_insertion_point(field_set:google.protobuf.Duration.nanos) +} + +#ifdef __GNUC__ + #pragma GCC diagnostic pop +#endif // __GNUC__ + +// @@protoc_insertion_point(namespace_scope) + +PROTOBUF_NAMESPACE_CLOSE + +// @@protoc_insertion_point(global_scope) + +#include <google/protobuf/port_undef.inc> +#endif // GOOGLE_PROTOBUF_INCLUDED_GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2fduration_2eproto diff --git a/toolkit/components/protobuf/src/google/protobuf/duration.proto b/toolkit/components/protobuf/src/google/protobuf/duration.proto new file mode 100644 index 0000000000..81c3e369fd --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/duration.proto @@ -0,0 +1,116 @@ +// 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. + +syntax = "proto3"; + +package google.protobuf; + +option csharp_namespace = "Google.Protobuf.WellKnownTypes"; +option cc_enable_arenas = true; +option go_package = "google.golang.org/protobuf/types/known/durationpb"; +option java_package = "com.google.protobuf"; +option java_outer_classname = "DurationProto"; +option java_multiple_files = true; +option objc_class_prefix = "GPB"; + +// A Duration represents a signed, fixed-length span of time represented +// as a count of seconds and fractions of seconds at nanosecond +// resolution. It is independent of any calendar and concepts like "day" +// or "month". It is related to Timestamp in that the difference between +// two Timestamp values is a Duration and it can be added or subtracted +// from a Timestamp. Range is approximately +-10,000 years. +// +// # Examples +// +// Example 1: Compute Duration from two Timestamps in pseudo code. +// +// Timestamp start = ...; +// Timestamp end = ...; +// Duration duration = ...; +// +// duration.seconds = end.seconds - start.seconds; +// duration.nanos = end.nanos - start.nanos; +// +// if (duration.seconds < 0 && duration.nanos > 0) { +// duration.seconds += 1; +// duration.nanos -= 1000000000; +// } else if (duration.seconds > 0 && duration.nanos < 0) { +// duration.seconds -= 1; +// duration.nanos += 1000000000; +// } +// +// Example 2: Compute Timestamp from Timestamp + Duration in pseudo code. +// +// Timestamp start = ...; +// Duration duration = ...; +// Timestamp end = ...; +// +// end.seconds = start.seconds + duration.seconds; +// end.nanos = start.nanos + duration.nanos; +// +// if (end.nanos < 0) { +// end.seconds -= 1; +// end.nanos += 1000000000; +// } else if (end.nanos >= 1000000000) { +// end.seconds += 1; +// end.nanos -= 1000000000; +// } +// +// Example 3: Compute Duration from datetime.timedelta in Python. +// +// td = datetime.timedelta(days=3, minutes=10) +// duration = Duration() +// duration.FromTimedelta(td) +// +// # JSON Mapping +// +// In JSON format, the Duration type is encoded as a string rather than an +// object, where the string ends in the suffix "s" (indicating seconds) and +// is preceded by the number of seconds, with nanoseconds expressed as +// fractional seconds. For example, 3 seconds with 0 nanoseconds should be +// encoded in JSON format as "3s", while 3 seconds and 1 nanosecond should +// be expressed in JSON format as "3.000000001s", and 3 seconds and 1 +// microsecond should be expressed in JSON format as "3.000001s". +// +// +message Duration { + // Signed seconds of the span of time. Must be from -315,576,000,000 + // to +315,576,000,000 inclusive. Note: these bounds are computed from: + // 60 sec/min * 60 min/hr * 24 hr/day * 365.25 days/year * 10000 years + int64 seconds = 1; + + // Signed fractions of a second at nanosecond resolution of the span + // of time. Durations less than one second are represented with a 0 + // `seconds` field and a positive or negative `nanos` field. For durations + // of one second or more, a non-zero value for the `nanos` field must be + // of the same sign as the `seconds` field. Must be from -999,999,999 + // to +999,999,999 inclusive. + int32 nanos = 2; +} diff --git a/toolkit/components/protobuf/src/google/protobuf/dynamic_message.cc b/toolkit/components/protobuf/src/google/protobuf/dynamic_message.cc new file mode 100644 index 0000000000..1c96ca2080 --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/dynamic_message.cc @@ -0,0 +1,826 @@ +// 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. + +// Author: kenton@google.com (Kenton Varda) +// Based on original Protocol Buffers design by +// Sanjay Ghemawat, Jeff Dean, and others. +// +// DynamicMessage is implemented by constructing a data structure which +// has roughly the same memory layout as a generated message would have. +// Then, we use Reflection to implement our reflection interface. All +// the other operations we need to implement (e.g. parsing, copying, +// etc.) are already implemented in terms of Reflection, so the rest is +// easy. +// +// The up side of this strategy is that it's very efficient. We don't +// need to use hash_maps or generic representations of fields. The +// down side is that this is a low-level memory management hack which +// can be tricky to get right. +// +// As mentioned in the header, we only expose a DynamicMessageFactory +// publicly, not the DynamicMessage class itself. This is because +// GenericMessageReflection wants to have a pointer to a "default" +// copy of the class, with all fields initialized to their default +// values. We only want to construct one of these per message type, +// so DynamicMessageFactory stores a cache of default messages for +// each type it sees (each unique Descriptor pointer). The code +// refers to the "default" copy of the class as the "prototype". +// +// Note on memory allocation: This module often calls "operator new()" +// to allocate untyped memory, rather than calling something like +// "new uint8_t[]". This is because "operator new()" means "Give me some +// space which I can use as I please." while "new uint8_t[]" means "Give +// me an array of 8-bit integers.". In practice, the later may return +// a pointer that is not aligned correctly for general use. I believe +// Item 8 of "More Effective C++" discusses this in more detail, though +// I don't have the book on me right now so I'm not sure. + +#include <google/protobuf/dynamic_message.h> + +#include <algorithm> +#include <cstddef> +#include <memory> +#include <new> +#include <unordered_map> + +#include <google/protobuf/descriptor.h> +#include <google/protobuf/descriptor.pb.h> +#include <google/protobuf/generated_message_reflection.h> +#include <google/protobuf/generated_message_util.h> +#include <google/protobuf/unknown_field_set.h> +#include <google/protobuf/stubs/hash.h> +#include <google/protobuf/arenastring.h> +#include <google/protobuf/extension_set.h> +#include <google/protobuf/map_field.h> +#include <google/protobuf/map_field_inl.h> +#include <google/protobuf/map_type_handler.h> +#include <google/protobuf/reflection_ops.h> +#include <google/protobuf/repeated_field.h> +#include <google/protobuf/wire_format.h> + +// Must be included last. +#include <google/protobuf/port_def.inc> + +namespace google { +namespace protobuf { + +using internal::DynamicMapField; +using internal::ExtensionSet; +using internal::MapField; + + +using internal::ArenaStringPtr; + +// =================================================================== +// Some helper tables and functions... + +namespace { + +bool IsMapFieldInApi(const FieldDescriptor* field) { return field->is_map(); } + +// Sync with helpers.h. +inline bool HasHasbit(const FieldDescriptor* field) { + // This predicate includes proto3 message fields only if they have "optional". + // Foo submsg1 = 1; // HasHasbit() == false + // optional Foo submsg2 = 2; // HasHasbit() == true + // This is slightly odd, as adding "optional" to a singular proto3 field does + // not change the semantics or API. However whenever any field in a message + // has a hasbit, it forces reflection to include hasbit offsets for *all* + // fields, even if almost all of them are set to -1 (no hasbit). So to avoid + // causing a sudden size regression for ~all proto3 messages, we give proto3 + // message fields a hasbit only if "optional" is present. If the user is + // explicitly writing "optional", it is likely they are writing it on + // primitive fields also. + return (field->has_optional_keyword() || field->is_required()) && + !field->options().weak(); +} + +inline bool InRealOneof(const FieldDescriptor* field) { + return field->containing_oneof() && + !field->containing_oneof()->is_synthetic(); +} + +// Compute the byte size of the in-memory representation of the field. +int FieldSpaceUsed(const FieldDescriptor* field) { + typedef FieldDescriptor FD; // avoid line wrapping + if (field->label() == FD::LABEL_REPEATED) { + switch (field->cpp_type()) { + case FD::CPPTYPE_INT32: + return sizeof(RepeatedField<int32_t>); + case FD::CPPTYPE_INT64: + return sizeof(RepeatedField<int64_t>); + case FD::CPPTYPE_UINT32: + return sizeof(RepeatedField<uint32_t>); + case FD::CPPTYPE_UINT64: + return sizeof(RepeatedField<uint64_t>); + case FD::CPPTYPE_DOUBLE: + return sizeof(RepeatedField<double>); + case FD::CPPTYPE_FLOAT: + return sizeof(RepeatedField<float>); + case FD::CPPTYPE_BOOL: + return sizeof(RepeatedField<bool>); + case FD::CPPTYPE_ENUM: + return sizeof(RepeatedField<int>); + case FD::CPPTYPE_MESSAGE: + if (IsMapFieldInApi(field)) { + return sizeof(DynamicMapField); + } else { + return sizeof(RepeatedPtrField<Message>); + } + + case FD::CPPTYPE_STRING: + switch (field->options().ctype()) { + default: // TODO(kenton): Support other string reps. + case FieldOptions::STRING: + return sizeof(RepeatedPtrField<std::string>); + } + break; + } + } else { + switch (field->cpp_type()) { + case FD::CPPTYPE_INT32: + return sizeof(int32_t); + case FD::CPPTYPE_INT64: + return sizeof(int64_t); + case FD::CPPTYPE_UINT32: + return sizeof(uint32_t); + case FD::CPPTYPE_UINT64: + return sizeof(uint64_t); + case FD::CPPTYPE_DOUBLE: + return sizeof(double); + case FD::CPPTYPE_FLOAT: + return sizeof(float); + case FD::CPPTYPE_BOOL: + return sizeof(bool); + case FD::CPPTYPE_ENUM: + return sizeof(int); + + case FD::CPPTYPE_MESSAGE: + return sizeof(Message*); + + case FD::CPPTYPE_STRING: + switch (field->options().ctype()) { + default: // TODO(kenton): Support other string reps. + case FieldOptions::STRING: + return sizeof(ArenaStringPtr); + } + break; + } + } + + GOOGLE_LOG(DFATAL) << "Can't get here."; + return 0; +} + +inline int DivideRoundingUp(int i, int j) { return (i + (j - 1)) / j; } + +static const int kSafeAlignment = sizeof(uint64_t); +static const int kMaxOneofUnionSize = sizeof(uint64_t); + +inline int AlignTo(int offset, int alignment) { + return DivideRoundingUp(offset, alignment) * alignment; +} + +// Rounds the given byte offset up to the next offset aligned such that any +// type may be stored at it. +inline int AlignOffset(int offset) { return AlignTo(offset, kSafeAlignment); } + +#define bitsizeof(T) (sizeof(T) * 8) + +} // namespace + +// =================================================================== + +class DynamicMessage : public Message { + public: + explicit DynamicMessage(const DynamicMessageFactory::TypeInfo* type_info); + + // This should only be used by GetPrototypeNoLock() to avoid dead lock. + DynamicMessage(DynamicMessageFactory::TypeInfo* type_info, bool lock_factory); + + ~DynamicMessage() override; + + // Called on the prototype after construction to initialize message fields. + // Cross linking the default instances allows for fast reflection access of + // unset message fields. Without it we would have to go to the MessageFactory + // to get the prototype, which is a much more expensive operation. + // + // Generated messages do not cross-link to avoid dynamic initialization of the + // global instances. + // Instead, they keep the default instances in the FieldDescriptor objects. + void CrossLinkPrototypes(); + + // implements Message ---------------------------------------------- + + Message* New(Arena* arena) const override; + + int GetCachedSize() const override; + void SetCachedSize(int size) const override; + + Metadata GetMetadata() const override; + +#if defined(__cpp_lib_destroying_delete) && defined(__cpp_sized_deallocation) + static void operator delete(DynamicMessage* msg, std::destroying_delete_t); +#else + // We actually allocate more memory than sizeof(*this) when this + // class's memory is allocated via the global operator new. Thus, we need to + // manually call the global operator delete. Calling the destructor is taken + // care of for us. This makes DynamicMessage compatible with -fsized-delete. + // It doesn't work for MSVC though. +#ifndef _MSC_VER + static void operator delete(void* ptr) { ::operator delete(ptr); } +#endif // !_MSC_VER +#endif + + private: + DynamicMessage(const DynamicMessageFactory::TypeInfo* type_info, + Arena* arena); + + void SharedCtor(bool lock_factory); + + // Needed to get the offset of the internal metadata member. + friend class DynamicMessageFactory; + + bool is_prototype() const; + + inline void* OffsetToPointer(int offset) { + return reinterpret_cast<uint8_t*>(this) + offset; + } + inline const void* OffsetToPointer(int offset) const { + return reinterpret_cast<const uint8_t*>(this) + offset; + } + + void* MutableRaw(int i); + void* MutableExtensionsRaw(); + void* MutableWeakFieldMapRaw(); + void* MutableOneofCaseRaw(int i); + void* MutableOneofFieldRaw(const FieldDescriptor* f); + + const DynamicMessageFactory::TypeInfo* type_info_; + mutable std::atomic<int> cached_byte_size_; + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(DynamicMessage); +}; + +struct DynamicMessageFactory::TypeInfo { + int size; + int has_bits_offset; + int oneof_case_offset; + int extensions_offset; + + // Not owned by the TypeInfo. + DynamicMessageFactory* factory; // The factory that created this object. + const DescriptorPool* pool; // The factory's DescriptorPool. + const Descriptor* type; // Type of this DynamicMessage. + + // Warning: The order in which the following pointers are defined is + // important (the prototype must be deleted *before* the offsets). + std::unique_ptr<uint32_t[]> offsets; + std::unique_ptr<uint32_t[]> has_bits_indices; + std::unique_ptr<const Reflection> reflection; + // Don't use a unique_ptr to hold the prototype: the destructor for + // DynamicMessage needs to know whether it is the prototype, and does so by + // looking back at this field. This would assume details about the + // implementation of unique_ptr. + const DynamicMessage* prototype; + int weak_field_map_offset; // The offset for the weak_field_map; + + TypeInfo() : prototype(nullptr) {} + + ~TypeInfo() { delete prototype; } +}; + +DynamicMessage::DynamicMessage(const DynamicMessageFactory::TypeInfo* type_info) + : type_info_(type_info), cached_byte_size_(0) { + SharedCtor(true); +} + +DynamicMessage::DynamicMessage(const DynamicMessageFactory::TypeInfo* type_info, + Arena* arena) + : Message(arena), type_info_(type_info), cached_byte_size_(0) { + SharedCtor(true); +} + +DynamicMessage::DynamicMessage(DynamicMessageFactory::TypeInfo* type_info, + bool lock_factory) + : type_info_(type_info), cached_byte_size_(0) { + // The prototype in type_info has to be set before creating the prototype + // instance on memory. e.g., message Foo { map<int32_t, Foo> a = 1; }. When + // creating prototype for Foo, prototype of the map entry will also be + // created, which needs the address of the prototype of Foo (the value in + // map). To break the cyclic dependency, we have to assign the address of + // prototype into type_info first. + type_info->prototype = this; + SharedCtor(lock_factory); +} + +inline void* DynamicMessage::MutableRaw(int i) { + return OffsetToPointer(type_info_->offsets[i]); +} +inline void* DynamicMessage::MutableExtensionsRaw() { + return OffsetToPointer(type_info_->extensions_offset); +} +inline void* DynamicMessage::MutableWeakFieldMapRaw() { + return OffsetToPointer(type_info_->weak_field_map_offset); +} +inline void* DynamicMessage::MutableOneofCaseRaw(int i) { + return OffsetToPointer(type_info_->oneof_case_offset + sizeof(uint32_t) * i); +} +inline void* DynamicMessage::MutableOneofFieldRaw(const FieldDescriptor* f) { + return OffsetToPointer(type_info_->offsets[type_info_->type->field_count() + + f->containing_oneof()->index()]); +} + +void DynamicMessage::SharedCtor(bool lock_factory) { + // We need to call constructors for various fields manually and set + // default values where appropriate. We use placement new to call + // constructors. If you haven't heard of placement new, I suggest Googling + // it now. We use placement new even for primitive types that don't have + // constructors for consistency. (In theory, placement new should be used + // any time you are trying to convert untyped memory to typed memory, though + // in practice that's not strictly necessary for types that don't have a + // constructor.) + + const Descriptor* descriptor = type_info_->type; + // Initialize oneof cases. + int oneof_count = 0; + for (int i = 0; i < descriptor->oneof_decl_count(); ++i) { + if (descriptor->oneof_decl(i)->is_synthetic()) continue; + new (MutableOneofCaseRaw(oneof_count++)) uint32_t{0}; + } + + if (type_info_->extensions_offset != -1) { + new (MutableExtensionsRaw()) ExtensionSet(GetArenaForAllocation()); + } + for (int i = 0; i < descriptor->field_count(); i++) { + const FieldDescriptor* field = descriptor->field(i); + void* field_ptr = MutableRaw(i); + if (InRealOneof(field)) { + continue; + } + switch (field->cpp_type()) { +#define HANDLE_TYPE(CPPTYPE, TYPE) \ + case FieldDescriptor::CPPTYPE_##CPPTYPE: \ + if (!field->is_repeated()) { \ + new (field_ptr) TYPE(field->default_value_##TYPE()); \ + } else { \ + new (field_ptr) RepeatedField<TYPE>(GetArenaForAllocation()); \ + } \ + break; + + HANDLE_TYPE(INT32, int32_t); + HANDLE_TYPE(INT64, int64_t); + HANDLE_TYPE(UINT32, uint32_t); + HANDLE_TYPE(UINT64, uint64_t); + HANDLE_TYPE(DOUBLE, double); + HANDLE_TYPE(FLOAT, float); + HANDLE_TYPE(BOOL, bool); +#undef HANDLE_TYPE + + case FieldDescriptor::CPPTYPE_ENUM: + if (!field->is_repeated()) { + new (field_ptr) int{field->default_value_enum()->number()}; + } else { + new (field_ptr) RepeatedField<int>(GetArenaForAllocation()); + } + break; + + case FieldDescriptor::CPPTYPE_STRING: + switch (field->options().ctype()) { + default: // TODO(kenton): Support other string reps. + case FieldOptions::STRING: + if (!field->is_repeated()) { + ArenaStringPtr* asp = new (field_ptr) ArenaStringPtr(); + asp->InitDefault(); + } else { + new (field_ptr) + RepeatedPtrField<std::string>(GetArenaForAllocation()); + } + break; + } + break; + + case FieldDescriptor::CPPTYPE_MESSAGE: { + if (!field->is_repeated()) { + new (field_ptr) Message*(nullptr); + } else { + if (IsMapFieldInApi(field)) { + // We need to lock in most cases to avoid data racing. Only not lock + // when the constructor is called inside GetPrototype(), in which + // case we have already locked the factory. + if (lock_factory) { + if (GetArenaForAllocation() != nullptr) { + new (field_ptr) DynamicMapField( + type_info_->factory->GetPrototype(field->message_type()), + GetArenaForAllocation()); + if (GetOwningArena() != nullptr) { + // Needs to destroy the mutex member. + GetOwningArena()->OwnDestructor( + static_cast<DynamicMapField*>(field_ptr)); + } + } else { + new (field_ptr) DynamicMapField( + type_info_->factory->GetPrototype(field->message_type())); + } + } else { + if (GetArenaForAllocation() != nullptr) { + new (field_ptr) + DynamicMapField(type_info_->factory->GetPrototypeNoLock( + field->message_type()), + GetArenaForAllocation()); + if (GetOwningArena() != nullptr) { + // Needs to destroy the mutex member. + GetOwningArena()->OwnDestructor( + static_cast<DynamicMapField*>(field_ptr)); + } + } else { + new (field_ptr) + DynamicMapField(type_info_->factory->GetPrototypeNoLock( + field->message_type())); + } + } + } else { + new (field_ptr) RepeatedPtrField<Message>(GetArenaForAllocation()); + } + } + break; + } + } + } +} + +bool DynamicMessage::is_prototype() const { + return type_info_->prototype == this || + // If type_info_->prototype is nullptr, then we must be constructing + // the prototype now, which means we must be the prototype. + type_info_->prototype == nullptr; +} + +#if defined(__cpp_lib_destroying_delete) && defined(__cpp_sized_deallocation) +void DynamicMessage::operator delete(DynamicMessage* msg, + std::destroying_delete_t) { + const size_t size = msg->type_info_->size; + msg->~DynamicMessage(); + ::operator delete(msg, size); +} +#endif + +DynamicMessage::~DynamicMessage() { + const Descriptor* descriptor = type_info_->type; + + _internal_metadata_.Delete<UnknownFieldSet>(); + + if (type_info_->extensions_offset != -1) { + reinterpret_cast<ExtensionSet*>(MutableExtensionsRaw())->~ExtensionSet(); + } + + // We need to manually run the destructors for repeated fields and strings, + // just as we ran their constructors in the DynamicMessage constructor. + // We also need to manually delete oneof fields if it is set and is string + // or message. + // Additionally, if any singular embedded messages have been allocated, we + // need to delete them, UNLESS we are the prototype message of this type, + // in which case any embedded messages are other prototypes and shouldn't + // be touched. + for (int i = 0; i < descriptor->field_count(); i++) { + const FieldDescriptor* field = descriptor->field(i); + if (InRealOneof(field)) { + void* field_ptr = MutableOneofCaseRaw(field->containing_oneof()->index()); + if (*(reinterpret_cast<const int32_t*>(field_ptr)) == field->number()) { + field_ptr = MutableOneofFieldRaw(field); + if (field->cpp_type() == FieldDescriptor::CPPTYPE_STRING) { + switch (field->options().ctype()) { + default: + case FieldOptions::STRING: { + reinterpret_cast<ArenaStringPtr*>(field_ptr)->Destroy(); + break; + } + } + } else if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { + delete *reinterpret_cast<Message**>(field_ptr); + } + } + continue; + } + void* field_ptr = MutableRaw(i); + + if (field->is_repeated()) { + switch (field->cpp_type()) { +#define HANDLE_TYPE(UPPERCASE, LOWERCASE) \ + case FieldDescriptor::CPPTYPE_##UPPERCASE: \ + reinterpret_cast<RepeatedField<LOWERCASE>*>(field_ptr) \ + ->~RepeatedField<LOWERCASE>(); \ + break + + HANDLE_TYPE(INT32, int32_t); + HANDLE_TYPE(INT64, int64_t); + HANDLE_TYPE(UINT32, uint32_t); + HANDLE_TYPE(UINT64, uint64_t); + HANDLE_TYPE(DOUBLE, double); + HANDLE_TYPE(FLOAT, float); + HANDLE_TYPE(BOOL, bool); + HANDLE_TYPE(ENUM, int); +#undef HANDLE_TYPE + + case FieldDescriptor::CPPTYPE_STRING: + switch (field->options().ctype()) { + default: // TODO(kenton): Support other string reps. + case FieldOptions::STRING: + reinterpret_cast<RepeatedPtrField<std::string>*>(field_ptr) + ->~RepeatedPtrField<std::string>(); + break; + } + break; + + case FieldDescriptor::CPPTYPE_MESSAGE: + if (IsMapFieldInApi(field)) { + reinterpret_cast<DynamicMapField*>(field_ptr)->~DynamicMapField(); + } else { + reinterpret_cast<RepeatedPtrField<Message>*>(field_ptr) + ->~RepeatedPtrField<Message>(); + } + break; + } + + } else if (field->cpp_type() == FieldDescriptor::CPPTYPE_STRING) { + switch (field->options().ctype()) { + default: // TODO(kenton): Support other string reps. + case FieldOptions::STRING: { + reinterpret_cast<ArenaStringPtr*>(field_ptr)->Destroy(); + break; + } + } + } else if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { + if (!is_prototype()) { + Message* message = *reinterpret_cast<Message**>(field_ptr); + if (message != nullptr) { + delete message; + } + } + } + } +} + +void DynamicMessage::CrossLinkPrototypes() { + // This should only be called on the prototype message. + GOOGLE_CHECK(is_prototype()); + + DynamicMessageFactory* factory = type_info_->factory; + const Descriptor* descriptor = type_info_->type; + + // Cross-link default messages. + for (int i = 0; i < descriptor->field_count(); i++) { + const FieldDescriptor* field = descriptor->field(i); + if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE && + !field->options().weak() && !InRealOneof(field) && + !field->is_repeated()) { + void* field_ptr = MutableRaw(i); + // For fields with message types, we need to cross-link with the + // prototype for the field's type. + // For singular fields, the field is just a pointer which should + // point to the prototype. + *reinterpret_cast<const Message**>(field_ptr) = + factory->GetPrototypeNoLock(field->message_type()); + } + } +} + +Message* DynamicMessage::New(Arena* arena) const { + if (arena != nullptr) { + void* new_base = Arena::CreateArray<char>(arena, type_info_->size); + memset(new_base, 0, type_info_->size); + return new (new_base) DynamicMessage(type_info_, arena); + } else { + void* new_base = operator new(type_info_->size); + memset(new_base, 0, type_info_->size); + return new (new_base) DynamicMessage(type_info_); + } +} + +int DynamicMessage::GetCachedSize() const { + return cached_byte_size_.load(std::memory_order_relaxed); +} + +void DynamicMessage::SetCachedSize(int size) const { + cached_byte_size_.store(size, std::memory_order_relaxed); +} + +Metadata DynamicMessage::GetMetadata() const { + Metadata metadata; + metadata.descriptor = type_info_->type; + metadata.reflection = type_info_->reflection.get(); + return metadata; +} + +// =================================================================== + +DynamicMessageFactory::DynamicMessageFactory() + : pool_(nullptr), delegate_to_generated_factory_(false) {} + +DynamicMessageFactory::DynamicMessageFactory(const DescriptorPool* pool) + : pool_(pool), delegate_to_generated_factory_(false) {} + +DynamicMessageFactory::~DynamicMessageFactory() { + for (auto iter = prototypes_.begin(); iter != prototypes_.end(); ++iter) { + delete iter->second; + } +} + +const Message* DynamicMessageFactory::GetPrototype(const Descriptor* type) { + MutexLock lock(&prototypes_mutex_); + return GetPrototypeNoLock(type); +} + +const Message* DynamicMessageFactory::GetPrototypeNoLock( + const Descriptor* type) { + if (delegate_to_generated_factory_ && + type->file()->pool() == DescriptorPool::generated_pool()) { + return MessageFactory::generated_factory()->GetPrototype(type); + } + + const TypeInfo** target = &prototypes_[type]; + if (*target != nullptr) { + // Already exists. + return (*target)->prototype; + } + + TypeInfo* type_info = new TypeInfo; + *target = type_info; + + type_info->type = type; + type_info->pool = (pool_ == nullptr) ? type->file()->pool() : pool_; + type_info->factory = this; + + // We need to construct all the structures passed to Reflection's constructor. + // This includes: + // - A block of memory that contains space for all the message's fields. + // - An array of integers indicating the byte offset of each field within + // this block. + // - A big bitfield containing a bit for each field indicating whether + // or not that field is set. + int real_oneof_count = 0; + for (int i = 0; i < type->oneof_decl_count(); i++) { + if (!type->oneof_decl(i)->is_synthetic()) { + real_oneof_count++; + } + } + + // Compute size and offsets. + uint32_t* offsets = new uint32_t[type->field_count() + real_oneof_count]; + type_info->offsets.reset(offsets); + + // Decide all field offsets by packing in order. + // We place the DynamicMessage object itself at the beginning of the allocated + // space. + int size = sizeof(DynamicMessage); + size = AlignOffset(size); + + // Next the has_bits, which is an array of uint32s. + type_info->has_bits_offset = -1; + int max_hasbit = 0; + for (int i = 0; i < type->field_count(); i++) { + if (HasHasbit(type->field(i))) { + if (type_info->has_bits_offset == -1) { + // At least one field in the message requires a hasbit, so allocate + // hasbits. + type_info->has_bits_offset = size; + uint32_t* has_bits_indices = new uint32_t[type->field_count()]; + for (int j = 0; j < type->field_count(); j++) { + // Initialize to -1, fields that need a hasbit will overwrite. + has_bits_indices[j] = static_cast<uint32_t>(-1); + } + type_info->has_bits_indices.reset(has_bits_indices); + } + type_info->has_bits_indices[i] = max_hasbit++; + } + } + + if (max_hasbit > 0) { + int has_bits_array_size = DivideRoundingUp(max_hasbit, bitsizeof(uint32_t)); + size += has_bits_array_size * sizeof(uint32_t); + size = AlignOffset(size); + } + + // The oneof_case, if any. It is an array of uint32s. + if (real_oneof_count > 0) { + type_info->oneof_case_offset = size; + size += real_oneof_count * sizeof(uint32_t); + size = AlignOffset(size); + } + + // The ExtensionSet, if any. + if (type->extension_range_count() > 0) { + type_info->extensions_offset = size; + size += sizeof(ExtensionSet); + size = AlignOffset(size); + } else { + // No extensions. + type_info->extensions_offset = -1; + } + + // All the fields. + // + // TODO(b/31226269): Optimize the order of fields to minimize padding. + for (int i = 0; i < type->field_count(); i++) { + // Make sure field is aligned to avoid bus errors. + // Oneof fields do not use any space. + if (!InRealOneof(type->field(i))) { + int field_size = FieldSpaceUsed(type->field(i)); + size = AlignTo(size, std::min(kSafeAlignment, field_size)); + offsets[i] = size; + size += field_size; + } + } + + // The oneofs. + for (int i = 0; i < type->oneof_decl_count(); i++) { + if (!type->oneof_decl(i)->is_synthetic()) { + size = AlignTo(size, kSafeAlignment); + offsets[type->field_count() + i] = size; + size += kMaxOneofUnionSize; + } + } + + type_info->weak_field_map_offset = -1; + + // Align the final size to make sure no clever allocators think that + // alignment is not necessary. + type_info->size = size; + + // Construct the reflection object. + + // Compute the size of default oneof instance and offsets of default + // oneof fields. + for (int i = 0; i < type->oneof_decl_count(); i++) { + if (type->oneof_decl(i)->is_synthetic()) continue; + for (int j = 0; j < type->oneof_decl(i)->field_count(); j++) { + const FieldDescriptor* field = type->oneof_decl(i)->field(j); + // oneof fields are not accessed through offsets, but we still have the + // entry from a legacy implementation. This should be removed at some + // point. + // Mark the field to prevent unintentional access through reflection. + // Don't use the top bit because that is for unused fields. + offsets[field->index()] = internal::kInvalidFieldOffsetTag; + } + } + + // Allocate the prototype fields. + void* base = operator new(size); + memset(base, 0, size); + + // We have already locked the factory so we should not lock in the constructor + // of dynamic message to avoid dead lock. + DynamicMessage* prototype = new (base) DynamicMessage(type_info, false); + + internal::ReflectionSchema schema = { + type_info->prototype, + type_info->offsets.get(), + type_info->has_bits_indices.get(), + type_info->has_bits_offset, + PROTOBUF_FIELD_OFFSET(DynamicMessage, _internal_metadata_), + type_info->extensions_offset, + type_info->oneof_case_offset, + type_info->size, + type_info->weak_field_map_offset, + nullptr /* inlined_string_indices_ */, + 0 /* inlined_string_donated_offset_ */}; + + type_info->reflection.reset( + new Reflection(type_info->type, schema, type_info->pool, this)); + + // Cross link prototypes. + prototype->CrossLinkPrototypes(); + + return prototype; +} + +} // namespace protobuf +} // namespace google + +#include <google/protobuf/port_undef.inc> // NOLINT diff --git a/toolkit/components/protobuf/src/google/protobuf/dynamic_message.h b/toolkit/components/protobuf/src/google/protobuf/dynamic_message.h new file mode 100644 index 0000000000..6fa64259ee --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/dynamic_message.h @@ -0,0 +1,227 @@ +// 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. + +// Author: kenton@google.com (Kenton Varda) +// Based on original Protocol Buffers design by +// Sanjay Ghemawat, Jeff Dean, and others. +// +// Defines an implementation of Message which can emulate types which are not +// known at compile-time. + +#ifndef GOOGLE_PROTOBUF_DYNAMIC_MESSAGE_H__ +#define GOOGLE_PROTOBUF_DYNAMIC_MESSAGE_H__ + + +#include <algorithm> +#include <memory> +#include <unordered_map> +#include <vector> + +#include <google/protobuf/stubs/common.h> +#include <google/protobuf/stubs/mutex.h> +#include <google/protobuf/message.h> +#include <google/protobuf/reflection.h> +#include <google/protobuf/repeated_field.h> + +#ifdef SWIG +#error "You cannot SWIG proto headers" +#endif + +// Must be included last. +#include <google/protobuf/port_def.inc> + +namespace google { +namespace protobuf { + +// Defined in other files. +class Descriptor; // descriptor.h +class DescriptorPool; // descriptor.h + +// Constructs implementations of Message which can emulate types which are not +// known at compile-time. +// +// Sometimes you want to be able to manipulate protocol types that you don't +// know about at compile time. It would be nice to be able to construct +// a Message object which implements the message type given by any arbitrary +// Descriptor. DynamicMessage provides this. +// +// As it turns out, a DynamicMessage needs to construct extra +// information about its type in order to operate. Most of this information +// can be shared between all DynamicMessages of the same type. But, caching +// this information in some sort of global map would be a bad idea, since +// the cached information for a particular descriptor could outlive the +// descriptor itself. To avoid this problem, DynamicMessageFactory +// encapsulates this "cache". All DynamicMessages of the same type created +// from the same factory will share the same support data. Any Descriptors +// used with a particular factory must outlive the factory. +class PROTOBUF_EXPORT DynamicMessageFactory : public MessageFactory { + public: + // Construct a DynamicMessageFactory that will search for extensions in + // the DescriptorPool in which the extendee is defined. + DynamicMessageFactory(); + + // Construct a DynamicMessageFactory that will search for extensions in + // the given DescriptorPool. + // + // DEPRECATED: Use CodedInputStream::SetExtensionRegistry() to tell the + // parser to look for extensions in an alternate pool. However, note that + // this is almost never what you want to do. Almost all users should use + // the zero-arg constructor. + DynamicMessageFactory(const DescriptorPool* pool); + + ~DynamicMessageFactory() override; + + // Call this to tell the DynamicMessageFactory that if it is given a + // Descriptor d for which: + // d->file()->pool() == DescriptorPool::generated_pool(), + // then it should delegate to MessageFactory::generated_factory() instead + // of constructing a dynamic implementation of the message. In theory there + // is no down side to doing this, so it may become the default in the future. + void SetDelegateToGeneratedFactory(bool enable) { + delegate_to_generated_factory_ = enable; + } + + // implements MessageFactory --------------------------------------- + + // Given a Descriptor, constructs the default (prototype) Message of that + // type. You can then call that message's New() method to construct a + // mutable message of that type. + // + // Calling this method twice with the same Descriptor returns the same + // object. The returned object remains property of the factory and will + // be destroyed when the factory is destroyed. Also, any objects created + // by calling the prototype's New() method share some data with the + // prototype, so these must be destroyed before the DynamicMessageFactory + // is destroyed. + // + // The given descriptor must outlive the returned message, and hence must + // outlive the DynamicMessageFactory. + // + // The method is thread-safe. + const Message* GetPrototype(const Descriptor* type) override; + + private: + const DescriptorPool* pool_; + bool delegate_to_generated_factory_; + + struct TypeInfo; + std::unordered_map<const Descriptor*, const TypeInfo*> prototypes_; + mutable internal::WrappedMutex prototypes_mutex_; + + friend class DynamicMessage; + const Message* GetPrototypeNoLock(const Descriptor* type); + + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(DynamicMessageFactory); +}; + +// Helper for computing a sorted list of map entries via reflection. +class PROTOBUF_EXPORT DynamicMapSorter { + public: + static std::vector<const Message*> Sort(const Message& message, int map_size, + const Reflection* reflection, + const FieldDescriptor* field) { + std::vector<const Message*> result; + result.reserve(map_size); + RepeatedFieldRef<Message> map_field = + reflection->GetRepeatedFieldRef<Message>(message, field); + for (auto it = map_field.begin(); it != map_field.end(); ++it) { + result.push_back(&*it); + } + MapEntryMessageComparator comparator(field->message_type()); + std::stable_sort(result.begin(), result.end(), comparator); + // Complain if the keys aren't in ascending order. +#ifndef NDEBUG + for (size_t j = 1; j < static_cast<size_t>(map_size); j++) { + if (!comparator(result[j - 1], result[j])) { + GOOGLE_LOG(ERROR) << (comparator(result[j], result[j - 1]) + ? "internal error in map key sorting" + : "map keys are not unique"); + } + } +#endif + return result; + } + + private: + class PROTOBUF_EXPORT MapEntryMessageComparator { + public: + explicit MapEntryMessageComparator(const Descriptor* descriptor) + : field_(descriptor->field(0)) {} + + bool operator()(const Message* a, const Message* b) { + const Reflection* reflection = a->GetReflection(); + switch (field_->cpp_type()) { + case FieldDescriptor::CPPTYPE_BOOL: { + bool first = reflection->GetBool(*a, field_); + bool second = reflection->GetBool(*b, field_); + return first < second; + } + case FieldDescriptor::CPPTYPE_INT32: { + int32_t first = reflection->GetInt32(*a, field_); + int32_t second = reflection->GetInt32(*b, field_); + return first < second; + } + case FieldDescriptor::CPPTYPE_INT64: { + int64_t first = reflection->GetInt64(*a, field_); + int64_t second = reflection->GetInt64(*b, field_); + return first < second; + } + case FieldDescriptor::CPPTYPE_UINT32: { + uint32_t first = reflection->GetUInt32(*a, field_); + uint32_t second = reflection->GetUInt32(*b, field_); + return first < second; + } + case FieldDescriptor::CPPTYPE_UINT64: { + uint64_t first = reflection->GetUInt64(*a, field_); + uint64_t second = reflection->GetUInt64(*b, field_); + return first < second; + } + case FieldDescriptor::CPPTYPE_STRING: { + std::string first = reflection->GetString(*a, field_); + std::string second = reflection->GetString(*b, field_); + return first < second; + } + default: + GOOGLE_LOG(DFATAL) << "Invalid key for map field."; + return true; + } + } + + private: + const FieldDescriptor* field_; + }; +}; + +} // namespace protobuf +} // namespace google + +#include <google/protobuf/port_undef.inc> + +#endif // GOOGLE_PROTOBUF_DYNAMIC_MESSAGE_H__ diff --git a/toolkit/components/protobuf/src/google/protobuf/empty.pb.cc b/toolkit/components/protobuf/src/google/protobuf/empty.pb.cc new file mode 100644 index 0000000000..3a30776386 --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/empty.pb.cc @@ -0,0 +1,130 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: google/protobuf/empty.proto + +#include <google/protobuf/empty.pb.h> + +#include <algorithm> + +#include <google/protobuf/io/coded_stream.h> +#include <google/protobuf/extension_set.h> +#include <google/protobuf/wire_format_lite.h> +#include <google/protobuf/descriptor.h> +#include <google/protobuf/generated_message_reflection.h> +#include <google/protobuf/reflection_ops.h> +#include <google/protobuf/wire_format.h> +// @@protoc_insertion_point(includes) +#include <google/protobuf/port_def.inc> + +PROTOBUF_PRAGMA_INIT_SEG + +namespace _pb = ::PROTOBUF_NAMESPACE_ID; +namespace _pbi = _pb::internal; + +PROTOBUF_NAMESPACE_OPEN +PROTOBUF_CONSTEXPR Empty::Empty( + ::_pbi::ConstantInitialized) {} +struct EmptyDefaultTypeInternal { + PROTOBUF_CONSTEXPR EmptyDefaultTypeInternal() + : _instance(::_pbi::ConstantInitialized{}) {} + ~EmptyDefaultTypeInternal() {} + union { + Empty _instance; + }; +}; +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 EmptyDefaultTypeInternal _Empty_default_instance_; +PROTOBUF_NAMESPACE_CLOSE +static ::_pb::Metadata file_level_metadata_google_2fprotobuf_2fempty_2eproto[1]; +static constexpr ::_pb::EnumDescriptor const** file_level_enum_descriptors_google_2fprotobuf_2fempty_2eproto = nullptr; +static constexpr ::_pb::ServiceDescriptor const** file_level_service_descriptors_google_2fprotobuf_2fempty_2eproto = nullptr; + +const uint32_t TableStruct_google_2fprotobuf_2fempty_2eproto::offsets[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = { + ~0u, // no _has_bits_ + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Empty, _internal_metadata_), + ~0u, // no _extensions_ + ~0u, // no _oneof_case_ + ~0u, // no _weak_field_map_ + ~0u, // no _inlined_string_donated_ +}; +static const ::_pbi::MigrationSchema schemas[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = { + { 0, -1, -1, sizeof(::PROTOBUF_NAMESPACE_ID::Empty)}, +}; + +static const ::_pb::Message* const file_default_instances[] = { + &::PROTOBUF_NAMESPACE_ID::_Empty_default_instance_._instance, +}; + +const char descriptor_table_protodef_google_2fprotobuf_2fempty_2eproto[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = + "\n\033google/protobuf/empty.proto\022\017google.pr" + "otobuf\"\007\n\005EmptyB}\n\023com.google.protobufB\n" + "EmptyProtoP\001Z.google.golang.org/protobuf" + "/types/known/emptypb\370\001\001\242\002\003GPB\252\002\036Google.P" + "rotobuf.WellKnownTypesb\006proto3" + ; +static ::_pbi::once_flag descriptor_table_google_2fprotobuf_2fempty_2eproto_once; +const ::_pbi::DescriptorTable descriptor_table_google_2fprotobuf_2fempty_2eproto = { + false, false, 190, descriptor_table_protodef_google_2fprotobuf_2fempty_2eproto, + "google/protobuf/empty.proto", + &descriptor_table_google_2fprotobuf_2fempty_2eproto_once, nullptr, 0, 1, + schemas, file_default_instances, TableStruct_google_2fprotobuf_2fempty_2eproto::offsets, + file_level_metadata_google_2fprotobuf_2fempty_2eproto, file_level_enum_descriptors_google_2fprotobuf_2fempty_2eproto, + file_level_service_descriptors_google_2fprotobuf_2fempty_2eproto, +}; +PROTOBUF_ATTRIBUTE_WEAK const ::_pbi::DescriptorTable* descriptor_table_google_2fprotobuf_2fempty_2eproto_getter() { + return &descriptor_table_google_2fprotobuf_2fempty_2eproto; +} + +// Force running AddDescriptors() at dynamic initialization time. +PROTOBUF_ATTRIBUTE_INIT_PRIORITY2 static ::_pbi::AddDescriptorsRunner dynamic_init_dummy_google_2fprotobuf_2fempty_2eproto(&descriptor_table_google_2fprotobuf_2fempty_2eproto); +PROTOBUF_NAMESPACE_OPEN + +// =================================================================== + +class Empty::_Internal { + public: +}; + +Empty::Empty(::PROTOBUF_NAMESPACE_ID::Arena* arena, + bool is_message_owned) + : ::PROTOBUF_NAMESPACE_ID::internal::ZeroFieldsBase(arena, is_message_owned) { + // @@protoc_insertion_point(arena_constructor:google.protobuf.Empty) +} +Empty::Empty(const Empty& from) + : ::PROTOBUF_NAMESPACE_ID::internal::ZeroFieldsBase() { + Empty* const _this = this; (void)_this; + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); + // @@protoc_insertion_point(copy_constructor:google.protobuf.Empty) +} + + + + + +const ::PROTOBUF_NAMESPACE_ID::Message::ClassData Empty::_class_data_ = { + ::PROTOBUF_NAMESPACE_ID::internal::ZeroFieldsBase::CopyImpl, + ::PROTOBUF_NAMESPACE_ID::internal::ZeroFieldsBase::MergeImpl, +}; +const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*Empty::GetClassData() const { return &_class_data_; } + + + + + + + +::PROTOBUF_NAMESPACE_ID::Metadata Empty::GetMetadata() const { + return ::_pbi::AssignDescriptors( + &descriptor_table_google_2fprotobuf_2fempty_2eproto_getter, &descriptor_table_google_2fprotobuf_2fempty_2eproto_once, + file_level_metadata_google_2fprotobuf_2fempty_2eproto[0]); +} + +// @@protoc_insertion_point(namespace_scope) +PROTOBUF_NAMESPACE_CLOSE +PROTOBUF_NAMESPACE_OPEN +template<> PROTOBUF_NOINLINE ::PROTOBUF_NAMESPACE_ID::Empty* +Arena::CreateMaybeMessage< ::PROTOBUF_NAMESPACE_ID::Empty >(Arena* arena) { + return Arena::CreateMessageInternal< ::PROTOBUF_NAMESPACE_ID::Empty >(arena); +} +PROTOBUF_NAMESPACE_CLOSE + +// @@protoc_insertion_point(global_scope) +#include <google/protobuf/port_undef.inc> diff --git a/toolkit/components/protobuf/src/google/protobuf/empty.pb.h b/toolkit/components/protobuf/src/google/protobuf/empty.pb.h new file mode 100644 index 0000000000..00a4481544 --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/empty.pb.h @@ -0,0 +1,198 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: google/protobuf/empty.proto + +#ifndef GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2fempty_2eproto +#define GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2fempty_2eproto + +#include <limits> +#include <string> + +#include <google/protobuf/port_def.inc> +#if PROTOBUF_VERSION < 3021000 +#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 3021006 < 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. +#endif + +#include <google/protobuf/port_undef.inc> +#include <google/protobuf/io/coded_stream.h> +#include <google/protobuf/arena.h> +#include <google/protobuf/arenastring.h> +#include <google/protobuf/generated_message_bases.h> +#include <google/protobuf/generated_message_util.h> +#include <google/protobuf/metadata_lite.h> +#include <google/protobuf/generated_message_reflection.h> +#include <google/protobuf/message.h> +#include <google/protobuf/repeated_field.h> // IWYU pragma: export +#include <google/protobuf/extension_set.h> // IWYU pragma: export +#include <google/protobuf/unknown_field_set.h> +// @@protoc_insertion_point(includes) +#include <google/protobuf/port_def.inc> +#define PROTOBUF_INTERNAL_EXPORT_google_2fprotobuf_2fempty_2eproto PROTOBUF_EXPORT +PROTOBUF_NAMESPACE_OPEN +namespace internal { +class AnyMetadata; +} // namespace internal +PROTOBUF_NAMESPACE_CLOSE + +// Internal implementation detail -- do not use these members. +struct PROTOBUF_EXPORT TableStruct_google_2fprotobuf_2fempty_2eproto { + static const uint32_t offsets[]; +}; +PROTOBUF_EXPORT extern const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable descriptor_table_google_2fprotobuf_2fempty_2eproto; +PROTOBUF_NAMESPACE_OPEN +class Empty; +struct EmptyDefaultTypeInternal; +PROTOBUF_EXPORT extern EmptyDefaultTypeInternal _Empty_default_instance_; +PROTOBUF_NAMESPACE_CLOSE +PROTOBUF_NAMESPACE_OPEN +template<> PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::Empty* Arena::CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::Empty>(Arena*); +PROTOBUF_NAMESPACE_CLOSE +PROTOBUF_NAMESPACE_OPEN + +// =================================================================== + +class PROTOBUF_EXPORT Empty final : + public ::PROTOBUF_NAMESPACE_ID::internal::ZeroFieldsBase /* @@protoc_insertion_point(class_definition:google.protobuf.Empty) */ { + public: + inline Empty() : Empty(nullptr) {} + explicit PROTOBUF_CONSTEXPR Empty(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized); + + Empty(const Empty& from); + Empty(Empty&& from) noexcept + : Empty() { + *this = ::std::move(from); + } + + inline Empty& operator=(const Empty& from) { + CopyFrom(from); + return *this; + } + inline Empty& operator=(Empty&& from) noexcept { + if (this == &from) return *this; + if (GetOwningArena() == from.GetOwningArena() + #ifdef PROTOBUF_FORCE_COPY_IN_MOVE + && GetOwningArena() != nullptr + #endif // !PROTOBUF_FORCE_COPY_IN_MOVE + ) { + InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* descriptor() { + return GetDescriptor(); + } + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() { + return default_instance().GetMetadata().descriptor; + } + static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() { + return default_instance().GetMetadata().reflection; + } + static const Empty& default_instance() { + return *internal_default_instance(); + } + static inline const Empty* internal_default_instance() { + return reinterpret_cast<const Empty*>( + &_Empty_default_instance_); + } + static constexpr int kIndexInFileMessages = + 0; + + friend void swap(Empty& a, Empty& b) { + a.Swap(&b); + } + inline void Swap(Empty* other) { + if (other == this) return; + #ifdef PROTOBUF_FORCE_COPY_IN_SWAP + if (GetOwningArena() != nullptr && + GetOwningArena() == other->GetOwningArena()) { + #else // PROTOBUF_FORCE_COPY_IN_SWAP + if (GetOwningArena() == other->GetOwningArena()) { + #endif // !PROTOBUF_FORCE_COPY_IN_SWAP + InternalSwap(other); + } else { + ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(Empty* other) { + if (other == this) return; + GOOGLE_DCHECK(GetOwningArena() == other->GetOwningArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + Empty* New(::PROTOBUF_NAMESPACE_ID::Arena* arena = nullptr) const final { + return CreateMaybeMessage<Empty>(arena); + } + using ::PROTOBUF_NAMESPACE_ID::internal::ZeroFieldsBase::CopyFrom; + inline void CopyFrom(const Empty& from) { + ::PROTOBUF_NAMESPACE_ID::internal::ZeroFieldsBase::CopyImpl(*this, from); + } + using ::PROTOBUF_NAMESPACE_ID::internal::ZeroFieldsBase::MergeFrom; + void MergeFrom(const Empty& from) { + ::PROTOBUF_NAMESPACE_ID::internal::ZeroFieldsBase::MergeImpl(*this, from); + } + public: + + private: + friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata; + static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() { + return "google.protobuf.Empty"; + } + protected: + explicit Empty(::PROTOBUF_NAMESPACE_ID::Arena* arena, + bool is_message_owned = false); + public: + + static const ClassData _class_data_; + const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*GetClassData() const final; + + ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final; + + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + + // @@protoc_insertion_point(class_scope:google.protobuf.Empty) + private: + class _Internal; + + template <typename T> friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper; + typedef void InternalArenaConstructable_; + typedef void DestructorSkippable_; + struct Impl_ { + }; + friend struct ::TableStruct_google_2fprotobuf_2fempty_2eproto; +}; +// =================================================================== + + +// =================================================================== + +#ifdef __GNUC__ + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wstrict-aliasing" +#endif // __GNUC__ +// Empty + +#ifdef __GNUC__ + #pragma GCC diagnostic pop +#endif // __GNUC__ + +// @@protoc_insertion_point(namespace_scope) + +PROTOBUF_NAMESPACE_CLOSE + +// @@protoc_insertion_point(global_scope) + +#include <google/protobuf/port_undef.inc> +#endif // GOOGLE_PROTOBUF_INCLUDED_GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2fempty_2eproto diff --git a/toolkit/components/protobuf/src/google/protobuf/empty.proto b/toolkit/components/protobuf/src/google/protobuf/empty.proto new file mode 100644 index 0000000000..2227462198 --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/empty.proto @@ -0,0 +1,51 @@ +// 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. + +syntax = "proto3"; + +package google.protobuf; + +option csharp_namespace = "Google.Protobuf.WellKnownTypes"; +option go_package = "google.golang.org/protobuf/types/known/emptypb"; +option java_package = "com.google.protobuf"; +option java_outer_classname = "EmptyProto"; +option java_multiple_files = true; +option objc_class_prefix = "GPB"; +option cc_enable_arenas = true; + +// A generic empty message that you can re-use to avoid defining duplicated +// empty messages in your APIs. A typical example is to use it as the request +// or the response type of an API method. For instance: +// +// service Foo { +// rpc Bar(google.protobuf.Empty) returns (google.protobuf.Empty); +// } +// +message Empty {} diff --git a/toolkit/components/protobuf/src/google/protobuf/endian.h b/toolkit/components/protobuf/src/google/protobuf/endian.h new file mode 100644 index 0000000000..e0ee6cdf28 --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/endian.h @@ -0,0 +1,198 @@ +// 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. + +#ifndef GOOGLE_PROTOBUF_ENDIAN_H__ +#define GOOGLE_PROTOBUF_ENDIAN_H__ + +#if defined(_MSC_VER) +#include <stdlib.h> +#endif + +#include <cstdint> + +// Must be included last. +#include <google/protobuf/port_def.inc> + +namespace google { +namespace protobuf { +namespace internal { + +inline uint64_t BSwap64(uint64_t host_int) { +#if defined(PROTOBUF_BUILTIN_BSWAP64) + return PROTOBUF_BUILTIN_BSWAP64(host_int); +#elif defined(_MSC_VER) + return _byteswap_uint64(host_int); +#else + return (((host_int & uint64_t{0xFF}) << 56) | + ((host_int & uint64_t{0xFF00}) << 40) | + ((host_int & uint64_t{0xFF0000}) << 24) | + ((host_int & uint64_t{0xFF000000}) << 8) | + ((host_int & uint64_t{0xFF00000000}) >> 8) | + ((host_int & uint64_t{0xFF0000000000}) >> 24) | + ((host_int & uint64_t{0xFF000000000000}) >> 40) | + ((host_int & uint64_t{0xFF00000000000000}) >> 56)); +#endif +} + +inline uint32_t BSwap32(uint32_t host_int) { +#if defined(PROTOBUF_BUILTIN_BSWAP32) + return PROTOBUF_BUILTIN_BSWAP32(host_int); +#elif defined(_MSC_VER) + return _byteswap_ulong(host_int); +#else + return (((host_int & uint32_t{0xFF}) << 24) | + ((host_int & uint32_t{0xFF00}) << 8) | + ((host_int & uint32_t{0xFF0000}) >> 8) | + ((host_int & uint32_t{0xFF000000}) >> 24)); +#endif +} + +inline uint16_t BSwap16(uint16_t host_int) { +#if defined(PROTOBUF_BUILTIN_BSWAP16) + return PROTOBUF_BUILTIN_BSWAP16(host_int); +#elif defined(_MSC_VER) + return _byteswap_ushort(host_int); +#else + return (((host_int & uint16_t{0xFF}) << 8) | + ((host_int & uint16_t{0xFF00}) >> 8)); +#endif +} + +namespace little_endian { + +inline uint16_t FromHost(uint16_t value) { +#if defined(PROTOBUF_BIG_ENDIAN) + return BSwap16(value); +#else + return value; +#endif +} + +inline uint32_t FromHost(uint32_t value) { +#if defined(PROTOBUF_BIG_ENDIAN) + return BSwap32(value); +#else + return value; +#endif +} + +inline uint64_t FromHost(uint64_t value) { +#if defined(PROTOBUF_BIG_ENDIAN) + return BSwap64(value); +#else + return value; +#endif +} + +inline uint16_t ToHost(uint16_t value) { +#if defined(PROTOBUF_BIG_ENDIAN) + return BSwap16(value); +#else + return value; +#endif +} + +inline uint32_t ToHost(uint32_t value) { +#if defined(PROTOBUF_BIG_ENDIAN) + return BSwap32(value); +#else + return value; +#endif +} + +inline uint64_t ToHost(uint64_t value) { +#if defined(PROTOBUF_BIG_ENDIAN) + return BSwap64(value); +#else + return value; +#endif +} + +} // namespace little_endian + +namespace big_endian { + +inline uint16_t FromHost(uint16_t value) { +#if defined(PROTOBUF_BIG_ENDIAN) + return value; +#else + return BSwap16(value); +#endif +} + +inline uint32_t FromHost(uint32_t value) { +#if defined(PROTOBUF_BIG_ENDIAN) + return value; +#else + return BSwap32(value); +#endif +} + +inline uint64_t FromHost(uint64_t value) { +#if defined(PROTOBUF_BIG_ENDIAN) + return value; +#else + return BSwap64(value); +#endif +} + +inline uint16_t ToHost(uint16_t value) { +#if defined(PROTOBUF_BIG_ENDIAN) + return value; +#else + return BSwap16(value); +#endif +} + +inline uint32_t ToHost(uint32_t value) { +#if defined(PROTOBUF_BIG_ENDIAN) + return value; +#else + return BSwap32(value); +#endif +} + +inline uint64_t ToHost(uint64_t value) { +#if defined(PROTOBUF_BIG_ENDIAN) + return value; +#else + return BSwap64(value); +#endif +} + +} // namespace big_endian + +} // namespace internal +} // namespace protobuf +} // namespace google + +#include <google/protobuf/port_undef.inc> + +#endif // GOOGLE_PROTOBUF_ENDIAN_H__ diff --git a/toolkit/components/protobuf/src/google/protobuf/explicitly_constructed.h b/toolkit/components/protobuf/src/google/protobuf/explicitly_constructed.h new file mode 100644 index 0000000000..174c59ab4b --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/explicitly_constructed.h @@ -0,0 +1,97 @@ +// 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. + +#ifndef GOOGLE_PROTOBUF_EXPLICITLY_CONSTRUCTED_H__ +#define GOOGLE_PROTOBUF_EXPLICITLY_CONSTRUCTED_H__ + +#include <stdint.h> + +#include <utility> + +#include <google/protobuf/stubs/logging.h> +#include <google/protobuf/stubs/common.h> + +// clang-format off +#include <google/protobuf/port_def.inc> +// clang-format on + +namespace google { +namespace protobuf { +namespace internal { + +// Wraps a variable whose constructor and destructor are explicitly +// called. It is particularly useful for a global variable, without its +// constructor and destructor run on start and end of the program lifetime. +// This circumvents the initial construction order fiasco, while keeping +// the address of the empty string a compile time constant. +// +// Pay special attention to the initialization state of the object. +// 1. The object is "uninitialized" to begin with. +// 2. Call Construct() or DefaultConstruct() only if the object is +// uninitialized. After the call, the object becomes "initialized". +// 3. Call get() and get_mutable() only if the object is initialized. +// 4. Call Destruct() only if the object is initialized. +// After the call, the object becomes uninitialized. +template <typename T, size_t min_align = 1> +class ExplicitlyConstructed { + public: + void DefaultConstruct() { new (&union_) T(); } + + template <typename... Args> + void Construct(Args&&... args) { + new (&union_) T(std::forward<Args>(args)...); + } + + void Destruct() { get_mutable()->~T(); } + + constexpr const T& get() const { return reinterpret_cast<const T&>(union_); } + T* get_mutable() { return reinterpret_cast<T*>(&union_); } + + private: + union AlignedUnion { + alignas(min_align > alignof(T) ? min_align + : alignof(T)) char space[sizeof(T)]; + int64_t align_to_int64; + void* align_to_ptr; + } union_; +}; + +// ArenaStringPtr compatible explicitly constructed string type. +// This empty string type is aligned with a minimum alignment of 8 bytes +// which is the minimum requirement of ArenaStringPtr +using ExplicitlyConstructedArenaString = ExplicitlyConstructed<std::string, 8>; + +} // namespace internal +} // namespace protobuf +} // namespace google + +#include <google/protobuf/port_undef.inc> + +#endif // GOOGLE_PROTOBUF_EXPLICITLY_CONSTRUCTED_H__ diff --git a/toolkit/components/protobuf/src/google/protobuf/extension_set.cc b/toolkit/components/protobuf/src/google/protobuf/extension_set.cc new file mode 100644 index 0000000000..fada4f5a98 --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/extension_set.cc @@ -0,0 +1,1967 @@ +// 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. + +// Author: kenton@google.com (Kenton Varda) +// Based on original Protocol Buffers design by +// Sanjay Ghemawat, Jeff Dean, and others. + +#include <google/protobuf/extension_set.h> + +#include <tuple> +#include <unordered_set> +#include <utility> + +#include <google/protobuf/stubs/common.h> +#include <google/protobuf/io/coded_stream.h> +#include <google/protobuf/io/zero_copy_stream_impl_lite.h> +#include <google/protobuf/arena.h> +#include <google/protobuf/extension_set_inl.h> +#include <google/protobuf/message_lite.h> +#include <google/protobuf/metadata_lite.h> +#include <google/protobuf/parse_context.h> +#include <google/protobuf/port.h> +#include <google/protobuf/repeated_field.h> +#include <google/protobuf/stubs/map_util.h> +#include <google/protobuf/stubs/hash.h> + +// clang-format off +#include <google/protobuf/port_def.inc> // must be last. +// clang-format on +namespace google { +namespace protobuf { +namespace internal { + +namespace { + +inline WireFormatLite::FieldType real_type(FieldType type) { + GOOGLE_DCHECK(type > 0 && type <= WireFormatLite::MAX_FIELD_TYPE); + return static_cast<WireFormatLite::FieldType>(type); +} + +inline WireFormatLite::CppType cpp_type(FieldType type) { + return WireFormatLite::FieldTypeToCppType(real_type(type)); +} + +// Registry stuff. + +// Note that we cannot use hetererogeneous lookup for std containers since we +// need to support C++11. +struct ExtensionEq { + bool operator()(const ExtensionInfo& lhs, const ExtensionInfo& rhs) const { + return lhs.message == rhs.message && lhs.number == rhs.number; + } +}; + +struct ExtensionHasher { + std::size_t operator()(const ExtensionInfo& info) const { + return std::hash<const MessageLite*>{}(info.message) ^ + std::hash<int>{}(info.number); + } +}; + +using ExtensionRegistry = + std::unordered_set<ExtensionInfo, ExtensionHasher, ExtensionEq>; + +static const ExtensionRegistry* global_registry = nullptr; + +// This function is only called at startup, so there is no need for thread- +// safety. +void Register(const ExtensionInfo& info) { + static auto local_static_registry = OnShutdownDelete(new ExtensionRegistry); + global_registry = local_static_registry; + if (!InsertIfNotPresent(local_static_registry, info)) { + GOOGLE_LOG(FATAL) << "Multiple extension registrations for type \"" + << info.message->GetTypeName() << "\", field number " + << info.number << "."; + } +} + +const ExtensionInfo* FindRegisteredExtension(const MessageLite* extendee, + int number) { + if (!global_registry) return nullptr; + + ExtensionInfo info; + info.message = extendee; + info.number = number; + + auto it = global_registry->find(info); + if (it == global_registry->end()) { + return nullptr; + } else { + return &*it; + } +} + +} // namespace + +bool GeneratedExtensionFinder::Find(int number, ExtensionInfo* output) { + const ExtensionInfo* extension = FindRegisteredExtension(extendee_, number); + if (extension == nullptr) { + return false; + } else { + *output = *extension; + return true; + } +} + +void ExtensionSet::RegisterExtension(const MessageLite* extendee, int number, + FieldType type, bool is_repeated, + bool is_packed, + LazyEagerVerifyFnType verify_func) { + GOOGLE_CHECK_NE(type, WireFormatLite::TYPE_ENUM); + GOOGLE_CHECK_NE(type, WireFormatLite::TYPE_MESSAGE); + GOOGLE_CHECK_NE(type, WireFormatLite::TYPE_GROUP); + ExtensionInfo info(extendee, number, type, is_repeated, is_packed, + verify_func); + Register(info); +} + +static bool CallNoArgValidityFunc(const void* arg, int number) { + // Note: Must use C-style cast here rather than reinterpret_cast because + // the C++ standard at one point did not allow casts between function and + // data pointers and some compilers enforce this for C++-style casts. No + // compiler enforces it for C-style casts since lots of C-style code has + // relied on these kinds of casts for a long time, despite being + // technically undefined. See: + // http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#195 + // Also note: Some compilers do not allow function pointers to be "const". + // Which makes sense, I suppose, because it's meaningless. + return ((EnumValidityFunc*)arg)(number); +} + +void ExtensionSet::RegisterEnumExtension(const MessageLite* extendee, + int number, FieldType type, + bool is_repeated, bool is_packed, + EnumValidityFunc* is_valid) { + GOOGLE_CHECK_EQ(type, WireFormatLite::TYPE_ENUM); + ExtensionInfo info(extendee, number, type, is_repeated, is_packed, nullptr); + info.enum_validity_check.func = CallNoArgValidityFunc; + // See comment in CallNoArgValidityFunc() about why we use a c-style cast. + info.enum_validity_check.arg = (void*)is_valid; + Register(info); +} + +void ExtensionSet::RegisterMessageExtension(const MessageLite* extendee, + int number, FieldType type, + bool is_repeated, bool is_packed, + const MessageLite* prototype, + LazyEagerVerifyFnType verify_func) { + GOOGLE_CHECK(type == WireFormatLite::TYPE_MESSAGE || + type == WireFormatLite::TYPE_GROUP); + ExtensionInfo info(extendee, number, type, is_repeated, is_packed, + verify_func); + info.message_info = {prototype}; + Register(info); +} + +// =================================================================== +// Constructors and basic methods. + +ExtensionSet::ExtensionSet(Arena* arena) + : arena_(arena), + flat_capacity_(0), + flat_size_(0), + map_{flat_capacity_ == 0 + ? nullptr + : Arena::CreateArray<KeyValue>(arena_, flat_capacity_)} {} + +ExtensionSet::~ExtensionSet() { + // Deletes all allocated extensions. + if (arena_ == nullptr) { + ForEach([](int /* number */, Extension& ext) { ext.Free(); }); + if (PROTOBUF_PREDICT_FALSE(is_large())) { + delete map_.large; + } else { + DeleteFlatMap(map_.flat, flat_capacity_); + } + } +} + +void ExtensionSet::DeleteFlatMap(const ExtensionSet::KeyValue* flat, + uint16_t flat_capacity) { + // Arena::CreateArray already requires a trivially destructible type, but + // ensure this constraint is not violated in the future. + static_assert(std::is_trivially_destructible<KeyValue>::value, + "CreateArray requires a trivially destructible type"); + // A const-cast is needed, but this is safe as we are about to deallocate the + // array. + internal::SizedArrayDelete(const_cast<KeyValue*>(flat), + sizeof(*flat) * flat_capacity); +} + +// Defined in extension_set_heavy.cc. +// void ExtensionSet::AppendToList(const Descriptor* extendee, +// const DescriptorPool* pool, +// vector<const FieldDescriptor*>* output) const + +bool ExtensionSet::Has(int number) const { + const Extension* ext = FindOrNull(number); + if (ext == nullptr) return false; + GOOGLE_DCHECK(!ext->is_repeated); + return !ext->is_cleared; +} + +bool ExtensionSet::HasLazy(int number) const { + return Has(number) && FindOrNull(number)->is_lazy; +} + +int ExtensionSet::NumExtensions() const { + int result = 0; + ForEach([&result](int /* number */, const Extension& ext) { + if (!ext.is_cleared) { + ++result; + } + }); + return result; +} + +int ExtensionSet::ExtensionSize(int number) const { + const Extension* ext = FindOrNull(number); + return ext == nullptr ? 0 : ext->GetSize(); +} + +FieldType ExtensionSet::ExtensionType(int number) const { + const Extension* ext = FindOrNull(number); + if (ext == nullptr) { + GOOGLE_LOG(DFATAL) << "Don't lookup extension types if they aren't present (1). "; + return 0; + } + if (ext->is_cleared) { + GOOGLE_LOG(DFATAL) << "Don't lookup extension types if they aren't present (2). "; + } + return ext->type; +} + +void ExtensionSet::ClearExtension(int number) { + Extension* ext = FindOrNull(number); + if (ext == nullptr) return; + ext->Clear(); +} + +// =================================================================== +// Field accessors + +namespace { + +enum { REPEATED_FIELD, OPTIONAL_FIELD }; + +} // namespace + +#define GOOGLE_DCHECK_TYPE(EXTENSION, LABEL, CPPTYPE) \ + GOOGLE_DCHECK_EQ((EXTENSION).is_repeated ? REPEATED_FIELD : OPTIONAL_FIELD, LABEL); \ + GOOGLE_DCHECK_EQ(cpp_type((EXTENSION).type), WireFormatLite::CPPTYPE_##CPPTYPE) + +// ------------------------------------------------------------------- +// Primitives + +#define PRIMITIVE_ACCESSORS(UPPERCASE, LOWERCASE, CAMELCASE) \ + \ + LOWERCASE ExtensionSet::Get##CAMELCASE(int number, LOWERCASE default_value) \ + const { \ + const Extension* extension = FindOrNull(number); \ + if (extension == nullptr || extension->is_cleared) { \ + return default_value; \ + } else { \ + GOOGLE_DCHECK_TYPE(*extension, OPTIONAL_FIELD, UPPERCASE); \ + return extension->LOWERCASE##_value; \ + } \ + } \ + \ + const LOWERCASE& ExtensionSet::GetRef##CAMELCASE( \ + int number, const LOWERCASE& default_value) const { \ + const Extension* extension = FindOrNull(number); \ + if (extension == nullptr || extension->is_cleared) { \ + return default_value; \ + } else { \ + GOOGLE_DCHECK_TYPE(*extension, OPTIONAL_FIELD, UPPERCASE); \ + return extension->LOWERCASE##_value; \ + } \ + } \ + \ + void ExtensionSet::Set##CAMELCASE(int number, FieldType type, \ + LOWERCASE value, \ + const FieldDescriptor* descriptor) { \ + Extension* extension; \ + if (MaybeNewExtension(number, descriptor, &extension)) { \ + extension->type = type; \ + GOOGLE_DCHECK_EQ(cpp_type(extension->type), \ + WireFormatLite::CPPTYPE_##UPPERCASE); \ + extension->is_repeated = false; \ + } else { \ + GOOGLE_DCHECK_TYPE(*extension, OPTIONAL_FIELD, UPPERCASE); \ + } \ + extension->is_cleared = false; \ + extension->LOWERCASE##_value = value; \ + } \ + \ + LOWERCASE ExtensionSet::GetRepeated##CAMELCASE(int number, int index) \ + const { \ + const Extension* extension = FindOrNull(number); \ + GOOGLE_CHECK(extension != nullptr) << "Index out-of-bounds (field is empty)."; \ + GOOGLE_DCHECK_TYPE(*extension, REPEATED_FIELD, UPPERCASE); \ + return extension->repeated_##LOWERCASE##_value->Get(index); \ + } \ + \ + const LOWERCASE& ExtensionSet::GetRefRepeated##CAMELCASE(int number, \ + int index) const { \ + const Extension* extension = FindOrNull(number); \ + GOOGLE_CHECK(extension != nullptr) << "Index out-of-bounds (field is empty)."; \ + GOOGLE_DCHECK_TYPE(*extension, REPEATED_FIELD, UPPERCASE); \ + return extension->repeated_##LOWERCASE##_value->Get(index); \ + } \ + \ + void ExtensionSet::SetRepeated##CAMELCASE(int number, int index, \ + LOWERCASE value) { \ + Extension* extension = FindOrNull(number); \ + GOOGLE_CHECK(extension != nullptr) << "Index out-of-bounds (field is empty)."; \ + GOOGLE_DCHECK_TYPE(*extension, REPEATED_FIELD, UPPERCASE); \ + extension->repeated_##LOWERCASE##_value->Set(index, value); \ + } \ + \ + void ExtensionSet::Add##CAMELCASE(int number, FieldType type, bool packed, \ + LOWERCASE value, \ + const FieldDescriptor* descriptor) { \ + Extension* extension; \ + if (MaybeNewExtension(number, descriptor, &extension)) { \ + extension->type = type; \ + GOOGLE_DCHECK_EQ(cpp_type(extension->type), \ + WireFormatLite::CPPTYPE_##UPPERCASE); \ + extension->is_repeated = true; \ + extension->is_packed = packed; \ + extension->repeated_##LOWERCASE##_value = \ + Arena::CreateMessage<RepeatedField<LOWERCASE>>(arena_); \ + } else { \ + GOOGLE_DCHECK_TYPE(*extension, REPEATED_FIELD, UPPERCASE); \ + GOOGLE_DCHECK_EQ(extension->is_packed, packed); \ + } \ + extension->repeated_##LOWERCASE##_value->Add(value); \ + } + +PRIMITIVE_ACCESSORS(INT32, int32_t, Int32) +PRIMITIVE_ACCESSORS(INT64, int64_t, Int64) +PRIMITIVE_ACCESSORS(UINT32, uint32_t, UInt32) +PRIMITIVE_ACCESSORS(UINT64, uint64_t, UInt64) +PRIMITIVE_ACCESSORS(FLOAT, float, Float) +PRIMITIVE_ACCESSORS(DOUBLE, double, Double) +PRIMITIVE_ACCESSORS(BOOL, bool, Bool) + +#undef PRIMITIVE_ACCESSORS + +const void* ExtensionSet::GetRawRepeatedField(int number, + const void* default_value) const { + const Extension* extension = FindOrNull(number); + if (extension == nullptr) { + return default_value; + } + // We assume that all the RepeatedField<>* pointers have the same + // size and alignment within the anonymous union in Extension. + return extension->repeated_int32_t_value; +} + +void* ExtensionSet::MutableRawRepeatedField(int number, FieldType field_type, + bool packed, + const FieldDescriptor* desc) { + Extension* extension; + + // We instantiate an empty Repeated{,Ptr}Field if one doesn't exist for this + // extension. + if (MaybeNewExtension(number, desc, &extension)) { + extension->is_repeated = true; + extension->type = field_type; + extension->is_packed = packed; + + switch (WireFormatLite::FieldTypeToCppType( + static_cast<WireFormatLite::FieldType>(field_type))) { + case WireFormatLite::CPPTYPE_INT32: + extension->repeated_int32_t_value = + Arena::CreateMessage<RepeatedField<int32_t>>(arena_); + break; + case WireFormatLite::CPPTYPE_INT64: + extension->repeated_int64_t_value = + Arena::CreateMessage<RepeatedField<int64_t>>(arena_); + break; + case WireFormatLite::CPPTYPE_UINT32: + extension->repeated_uint32_t_value = + Arena::CreateMessage<RepeatedField<uint32_t>>(arena_); + break; + case WireFormatLite::CPPTYPE_UINT64: + extension->repeated_uint64_t_value = + Arena::CreateMessage<RepeatedField<uint64_t>>(arena_); + break; + case WireFormatLite::CPPTYPE_DOUBLE: + extension->repeated_double_value = + Arena::CreateMessage<RepeatedField<double>>(arena_); + break; + case WireFormatLite::CPPTYPE_FLOAT: + extension->repeated_float_value = + Arena::CreateMessage<RepeatedField<float>>(arena_); + break; + case WireFormatLite::CPPTYPE_BOOL: + extension->repeated_bool_value = + Arena::CreateMessage<RepeatedField<bool>>(arena_); + break; + case WireFormatLite::CPPTYPE_ENUM: + extension->repeated_enum_value = + Arena::CreateMessage<RepeatedField<int>>(arena_); + break; + case WireFormatLite::CPPTYPE_STRING: + extension->repeated_string_value = + Arena::CreateMessage<RepeatedPtrField<std::string>>(arena_); + break; + case WireFormatLite::CPPTYPE_MESSAGE: + extension->repeated_message_value = + Arena::CreateMessage<RepeatedPtrField<MessageLite>>(arena_); + break; + } + } + + // We assume that all the RepeatedField<>* pointers have the same + // size and alignment within the anonymous union in Extension. + return extension->repeated_int32_t_value; +} + +// Compatible version using old call signature. Does not create extensions when +// the don't already exist; instead, just GOOGLE_CHECK-fails. +void* ExtensionSet::MutableRawRepeatedField(int number) { + Extension* extension = FindOrNull(number); + GOOGLE_CHECK(extension != nullptr) << "Extension not found."; + // We assume that all the RepeatedField<>* pointers have the same + // size and alignment within the anonymous union in Extension. + return extension->repeated_int32_t_value; +} + +// ------------------------------------------------------------------- +// Enums + +int ExtensionSet::GetEnum(int number, int default_value) const { + const Extension* extension = FindOrNull(number); + if (extension == nullptr || extension->is_cleared) { + // Not present. Return the default value. + return default_value; + } else { + GOOGLE_DCHECK_TYPE(*extension, OPTIONAL_FIELD, ENUM); + return extension->enum_value; + } +} + +const int& ExtensionSet::GetRefEnum(int number, + const int& default_value) const { + const Extension* extension = FindOrNull(number); + if (extension == nullptr || extension->is_cleared) { + // Not present. Return the default value. + return default_value; + } else { + GOOGLE_DCHECK_TYPE(*extension, OPTIONAL_FIELD, ENUM); + return extension->enum_value; + } +} + +void ExtensionSet::SetEnum(int number, FieldType type, int value, + const FieldDescriptor* descriptor) { + Extension* extension; + if (MaybeNewExtension(number, descriptor, &extension)) { + extension->type = type; + GOOGLE_DCHECK_EQ(cpp_type(extension->type), WireFormatLite::CPPTYPE_ENUM); + extension->is_repeated = false; + } else { + GOOGLE_DCHECK_TYPE(*extension, OPTIONAL_FIELD, ENUM); + } + extension->is_cleared = false; + extension->enum_value = value; +} + +int ExtensionSet::GetRepeatedEnum(int number, int index) const { + const Extension* extension = FindOrNull(number); + GOOGLE_CHECK(extension != nullptr) << "Index out-of-bounds (field is empty)."; + GOOGLE_DCHECK_TYPE(*extension, REPEATED_FIELD, ENUM); + return extension->repeated_enum_value->Get(index); +} + +const int& ExtensionSet::GetRefRepeatedEnum(int number, int index) const { + const Extension* extension = FindOrNull(number); + GOOGLE_CHECK(extension != nullptr) << "Index out-of-bounds (field is empty)."; + GOOGLE_DCHECK_TYPE(*extension, REPEATED_FIELD, ENUM); + return extension->repeated_enum_value->Get(index); +} + +void ExtensionSet::SetRepeatedEnum(int number, int index, int value) { + Extension* extension = FindOrNull(number); + GOOGLE_CHECK(extension != nullptr) << "Index out-of-bounds (field is empty)."; + GOOGLE_DCHECK_TYPE(*extension, REPEATED_FIELD, ENUM); + extension->repeated_enum_value->Set(index, value); +} + +void ExtensionSet::AddEnum(int number, FieldType type, bool packed, int value, + const FieldDescriptor* descriptor) { + Extension* extension; + if (MaybeNewExtension(number, descriptor, &extension)) { + extension->type = type; + GOOGLE_DCHECK_EQ(cpp_type(extension->type), WireFormatLite::CPPTYPE_ENUM); + extension->is_repeated = true; + extension->is_packed = packed; + extension->repeated_enum_value = + Arena::CreateMessage<RepeatedField<int>>(arena_); + } else { + GOOGLE_DCHECK_TYPE(*extension, REPEATED_FIELD, ENUM); + GOOGLE_DCHECK_EQ(extension->is_packed, packed); + } + extension->repeated_enum_value->Add(value); +} + +// ------------------------------------------------------------------- +// Strings + +const std::string& ExtensionSet::GetString( + int number, const std::string& default_value) const { + const Extension* extension = FindOrNull(number); + if (extension == nullptr || extension->is_cleared) { + // Not present. Return the default value. + return default_value; + } else { + GOOGLE_DCHECK_TYPE(*extension, OPTIONAL_FIELD, STRING); + return *extension->string_value; + } +} + +std::string* ExtensionSet::MutableString(int number, FieldType type, + const FieldDescriptor* descriptor) { + Extension* extension; + if (MaybeNewExtension(number, descriptor, &extension)) { + extension->type = type; + GOOGLE_DCHECK_EQ(cpp_type(extension->type), WireFormatLite::CPPTYPE_STRING); + extension->is_repeated = false; + extension->string_value = Arena::Create<std::string>(arena_); + } else { + GOOGLE_DCHECK_TYPE(*extension, OPTIONAL_FIELD, STRING); + } + extension->is_cleared = false; + return extension->string_value; +} + +const std::string& ExtensionSet::GetRepeatedString(int number, + int index) const { + const Extension* extension = FindOrNull(number); + GOOGLE_CHECK(extension != nullptr) << "Index out-of-bounds (field is empty)."; + GOOGLE_DCHECK_TYPE(*extension, REPEATED_FIELD, STRING); + return extension->repeated_string_value->Get(index); +} + +std::string* ExtensionSet::MutableRepeatedString(int number, int index) { + Extension* extension = FindOrNull(number); + GOOGLE_CHECK(extension != nullptr) << "Index out-of-bounds (field is empty)."; + GOOGLE_DCHECK_TYPE(*extension, REPEATED_FIELD, STRING); + return extension->repeated_string_value->Mutable(index); +} + +std::string* ExtensionSet::AddString(int number, FieldType type, + const FieldDescriptor* descriptor) { + Extension* extension; + if (MaybeNewExtension(number, descriptor, &extension)) { + extension->type = type; + GOOGLE_DCHECK_EQ(cpp_type(extension->type), WireFormatLite::CPPTYPE_STRING); + extension->is_repeated = true; + extension->is_packed = false; + extension->repeated_string_value = + Arena::CreateMessage<RepeatedPtrField<std::string>>(arena_); + } else { + GOOGLE_DCHECK_TYPE(*extension, REPEATED_FIELD, STRING); + } + return extension->repeated_string_value->Add(); +} + +// ------------------------------------------------------------------- +// Messages + +const MessageLite& ExtensionSet::GetMessage( + int number, const MessageLite& default_value) const { + const Extension* extension = FindOrNull(number); + if (extension == nullptr) { + // Not present. Return the default value. + return default_value; + } else { + GOOGLE_DCHECK_TYPE(*extension, OPTIONAL_FIELD, MESSAGE); + if (extension->is_lazy) { + return extension->lazymessage_value->GetMessage(default_value, arena_); + } else { + return *extension->message_value; + } + } +} + +// Defined in extension_set_heavy.cc. +// const MessageLite& ExtensionSet::GetMessage(int number, +// const Descriptor* message_type, +// MessageFactory* factory) const + +MessageLite* ExtensionSet::MutableMessage(int number, FieldType type, + const MessageLite& prototype, + const FieldDescriptor* descriptor) { + Extension* extension; + if (MaybeNewExtension(number, descriptor, &extension)) { + extension->type = type; + GOOGLE_DCHECK_EQ(cpp_type(extension->type), WireFormatLite::CPPTYPE_MESSAGE); + extension->is_repeated = false; + extension->is_lazy = false; + extension->message_value = prototype.New(arena_); + extension->is_cleared = false; + return extension->message_value; + } else { + GOOGLE_DCHECK_TYPE(*extension, OPTIONAL_FIELD, MESSAGE); + extension->is_cleared = false; + if (extension->is_lazy) { + return extension->lazymessage_value->MutableMessage(prototype, arena_); + } else { + return extension->message_value; + } + } +} + +// Defined in extension_set_heavy.cc. +// MessageLite* ExtensionSet::MutableMessage(int number, FieldType type, +// const Descriptor* message_type, +// MessageFactory* factory) + +void ExtensionSet::SetAllocatedMessage(int number, FieldType type, + const FieldDescriptor* descriptor, + MessageLite* message) { + if (message == nullptr) { + ClearExtension(number); + return; + } + GOOGLE_DCHECK(message->GetOwningArena() == nullptr || + message->GetOwningArena() == arena_); + Arena* message_arena = message->GetOwningArena(); + Extension* extension; + if (MaybeNewExtension(number, descriptor, &extension)) { + extension->type = type; + GOOGLE_DCHECK_EQ(cpp_type(extension->type), WireFormatLite::CPPTYPE_MESSAGE); + extension->is_repeated = false; + extension->is_lazy = false; + if (message_arena == arena_) { + extension->message_value = message; + } else if (message_arena == nullptr) { + extension->message_value = message; + arena_->Own(message); // not nullptr because not equal to message_arena + } else { + extension->message_value = message->New(arena_); + extension->message_value->CheckTypeAndMergeFrom(*message); + } + } else { + GOOGLE_DCHECK_TYPE(*extension, OPTIONAL_FIELD, MESSAGE); + if (extension->is_lazy) { + extension->lazymessage_value->SetAllocatedMessage(message, arena_); + } else { + if (arena_ == nullptr) { + delete extension->message_value; + } + if (message_arena == arena_) { + extension->message_value = message; + } else if (message_arena == nullptr) { + extension->message_value = message; + arena_->Own(message); // not nullptr because not equal to message_arena + } else { + extension->message_value = message->New(arena_); + extension->message_value->CheckTypeAndMergeFrom(*message); + } + } + } + extension->is_cleared = false; +} + +void ExtensionSet::UnsafeArenaSetAllocatedMessage( + int number, FieldType type, const FieldDescriptor* descriptor, + MessageLite* message) { + if (message == nullptr) { + ClearExtension(number); + return; + } + Extension* extension; + if (MaybeNewExtension(number, descriptor, &extension)) { + extension->type = type; + GOOGLE_DCHECK_EQ(cpp_type(extension->type), WireFormatLite::CPPTYPE_MESSAGE); + extension->is_repeated = false; + extension->is_lazy = false; + extension->message_value = message; + } else { + GOOGLE_DCHECK_TYPE(*extension, OPTIONAL_FIELD, MESSAGE); + if (extension->is_lazy) { + extension->lazymessage_value->UnsafeArenaSetAllocatedMessage(message, + arena_); + } else { + if (arena_ == nullptr) { + delete extension->message_value; + } + extension->message_value = message; + } + } + extension->is_cleared = false; +} + +MessageLite* ExtensionSet::ReleaseMessage(int number, + const MessageLite& prototype) { + Extension* extension = FindOrNull(number); + if (extension == nullptr) { + // Not present. Return nullptr. + return nullptr; + } else { + GOOGLE_DCHECK_TYPE(*extension, OPTIONAL_FIELD, MESSAGE); + MessageLite* ret = nullptr; + if (extension->is_lazy) { + ret = extension->lazymessage_value->ReleaseMessage(prototype, arena_); + if (arena_ == nullptr) { + delete extension->lazymessage_value; + } + } else { + if (arena_ == nullptr) { + ret = extension->message_value; + } else { + // ReleaseMessage() always returns a heap-allocated message, and we are + // on an arena, so we need to make a copy of this message to return. + ret = extension->message_value->New(); + ret->CheckTypeAndMergeFrom(*extension->message_value); + } + } + Erase(number); + return ret; + } +} + +MessageLite* ExtensionSet::UnsafeArenaReleaseMessage( + int number, const MessageLite& prototype) { + Extension* extension = FindOrNull(number); + if (extension == nullptr) { + // Not present. Return nullptr. + return nullptr; + } else { + GOOGLE_DCHECK_TYPE(*extension, OPTIONAL_FIELD, MESSAGE); + MessageLite* ret = nullptr; + if (extension->is_lazy) { + ret = extension->lazymessage_value->UnsafeArenaReleaseMessage(prototype, + arena_); + if (arena_ == nullptr) { + delete extension->lazymessage_value; + } + } else { + ret = extension->message_value; + } + Erase(number); + return ret; + } +} + +// Defined in extension_set_heavy.cc. +// MessageLite* ExtensionSet::ReleaseMessage(const FieldDescriptor* descriptor, +// MessageFactory* factory); + +const MessageLite& ExtensionSet::GetRepeatedMessage(int number, + int index) const { + const Extension* extension = FindOrNull(number); + GOOGLE_CHECK(extension != nullptr) << "Index out-of-bounds (field is empty)."; + GOOGLE_DCHECK_TYPE(*extension, REPEATED_FIELD, MESSAGE); + return extension->repeated_message_value->Get(index); +} + +MessageLite* ExtensionSet::MutableRepeatedMessage(int number, int index) { + Extension* extension = FindOrNull(number); + GOOGLE_CHECK(extension != nullptr) << "Index out-of-bounds (field is empty)."; + GOOGLE_DCHECK_TYPE(*extension, REPEATED_FIELD, MESSAGE); + return extension->repeated_message_value->Mutable(index); +} + +MessageLite* ExtensionSet::AddMessage(int number, FieldType type, + const MessageLite& prototype, + const FieldDescriptor* descriptor) { + Extension* extension; + if (MaybeNewExtension(number, descriptor, &extension)) { + extension->type = type; + GOOGLE_DCHECK_EQ(cpp_type(extension->type), WireFormatLite::CPPTYPE_MESSAGE); + extension->is_repeated = true; + extension->repeated_message_value = + Arena::CreateMessage<RepeatedPtrField<MessageLite>>(arena_); + } else { + GOOGLE_DCHECK_TYPE(*extension, REPEATED_FIELD, MESSAGE); + } + + // RepeatedPtrField<MessageLite> does not know how to Add() since it cannot + // allocate an abstract object, so we have to be tricky. + MessageLite* result = reinterpret_cast<internal::RepeatedPtrFieldBase*>( + extension->repeated_message_value) + ->AddFromCleared<GenericTypeHandler<MessageLite>>(); + if (result == nullptr) { + result = prototype.New(arena_); + extension->repeated_message_value->AddAllocated(result); + } + return result; +} + +// Defined in extension_set_heavy.cc. +// MessageLite* ExtensionSet::AddMessage(int number, FieldType type, +// const Descriptor* message_type, +// MessageFactory* factory) + +#undef GOOGLE_DCHECK_TYPE + +void ExtensionSet::RemoveLast(int number) { + Extension* extension = FindOrNull(number); + GOOGLE_CHECK(extension != nullptr) << "Index out-of-bounds (field is empty)."; + GOOGLE_DCHECK(extension->is_repeated); + + switch (cpp_type(extension->type)) { + case WireFormatLite::CPPTYPE_INT32: + extension->repeated_int32_t_value->RemoveLast(); + break; + case WireFormatLite::CPPTYPE_INT64: + extension->repeated_int64_t_value->RemoveLast(); + break; + case WireFormatLite::CPPTYPE_UINT32: + extension->repeated_uint32_t_value->RemoveLast(); + break; + case WireFormatLite::CPPTYPE_UINT64: + extension->repeated_uint64_t_value->RemoveLast(); + break; + case WireFormatLite::CPPTYPE_FLOAT: + extension->repeated_float_value->RemoveLast(); + break; + case WireFormatLite::CPPTYPE_DOUBLE: + extension->repeated_double_value->RemoveLast(); + break; + case WireFormatLite::CPPTYPE_BOOL: + extension->repeated_bool_value->RemoveLast(); + break; + case WireFormatLite::CPPTYPE_ENUM: + extension->repeated_enum_value->RemoveLast(); + break; + case WireFormatLite::CPPTYPE_STRING: + extension->repeated_string_value->RemoveLast(); + break; + case WireFormatLite::CPPTYPE_MESSAGE: + extension->repeated_message_value->RemoveLast(); + break; + } +} + +MessageLite* ExtensionSet::ReleaseLast(int number) { + Extension* extension = FindOrNull(number); + GOOGLE_CHECK(extension != nullptr) << "Index out-of-bounds (field is empty)."; + GOOGLE_DCHECK(extension->is_repeated); + GOOGLE_DCHECK(cpp_type(extension->type) == WireFormatLite::CPPTYPE_MESSAGE); + return extension->repeated_message_value->ReleaseLast(); +} + +MessageLite* ExtensionSet::UnsafeArenaReleaseLast(int number) { + Extension* extension = FindOrNull(number); + GOOGLE_CHECK(extension != nullptr) << "Index out-of-bounds (field is empty)."; + GOOGLE_DCHECK(extension->is_repeated); + GOOGLE_DCHECK(cpp_type(extension->type) == WireFormatLite::CPPTYPE_MESSAGE); + return extension->repeated_message_value->UnsafeArenaReleaseLast(); +} + +void ExtensionSet::SwapElements(int number, int index1, int index2) { + Extension* extension = FindOrNull(number); + GOOGLE_CHECK(extension != nullptr) << "Index out-of-bounds (field is empty)."; + GOOGLE_DCHECK(extension->is_repeated); + + switch (cpp_type(extension->type)) { + case WireFormatLite::CPPTYPE_INT32: + extension->repeated_int32_t_value->SwapElements(index1, index2); + break; + case WireFormatLite::CPPTYPE_INT64: + extension->repeated_int64_t_value->SwapElements(index1, index2); + break; + case WireFormatLite::CPPTYPE_UINT32: + extension->repeated_uint32_t_value->SwapElements(index1, index2); + break; + case WireFormatLite::CPPTYPE_UINT64: + extension->repeated_uint64_t_value->SwapElements(index1, index2); + break; + case WireFormatLite::CPPTYPE_FLOAT: + extension->repeated_float_value->SwapElements(index1, index2); + break; + case WireFormatLite::CPPTYPE_DOUBLE: + extension->repeated_double_value->SwapElements(index1, index2); + break; + case WireFormatLite::CPPTYPE_BOOL: + extension->repeated_bool_value->SwapElements(index1, index2); + break; + case WireFormatLite::CPPTYPE_ENUM: + extension->repeated_enum_value->SwapElements(index1, index2); + break; + case WireFormatLite::CPPTYPE_STRING: + extension->repeated_string_value->SwapElements(index1, index2); + break; + case WireFormatLite::CPPTYPE_MESSAGE: + extension->repeated_message_value->SwapElements(index1, index2); + break; + } +} + +// =================================================================== + +void ExtensionSet::Clear() { + ForEach([](int /* number */, Extension& ext) { ext.Clear(); }); +} + +namespace { +// Computes the size of an ExtensionSet union without actually constructing the +// union. Note that we do not count cleared extensions from the source to be +// part of the total, because there is no need to allocate space for those. We +// do include cleared extensions in the destination, though, because those are +// already allocated and will not be going away. +template <typename ItX, typename ItY> +size_t SizeOfUnion(ItX it_dest, ItX end_dest, ItY it_source, ItY end_source) { + size_t result = 0; + while (it_dest != end_dest && it_source != end_source) { + if (it_dest->first < it_source->first) { + ++result; + ++it_dest; + } else if (it_dest->first == it_source->first) { + ++result; + ++it_dest; + ++it_source; + } else { + if (!it_source->second.is_cleared) { + ++result; + } + ++it_source; + } + } + result += std::distance(it_dest, end_dest); + for (; it_source != end_source; ++it_source) { + if (!it_source->second.is_cleared) { + ++result; + } + } + return result; +} +} // namespace + +void ExtensionSet::MergeFrom(const MessageLite* extendee, + const ExtensionSet& other) { + if (PROTOBUF_PREDICT_TRUE(!is_large())) { + if (PROTOBUF_PREDICT_TRUE(!other.is_large())) { + GrowCapacity(SizeOfUnion(flat_begin(), flat_end(), other.flat_begin(), + other.flat_end())); + } else { + GrowCapacity(SizeOfUnion(flat_begin(), flat_end(), + other.map_.large->begin(), + other.map_.large->end())); + } + } + other.ForEach([extendee, this, &other](int number, const Extension& ext) { + this->InternalExtensionMergeFrom(extendee, number, ext, other.arena_); + }); +} + +void ExtensionSet::InternalExtensionMergeFrom(const MessageLite* extendee, + int number, + const Extension& other_extension, + Arena* other_arena) { + if (other_extension.is_repeated) { + Extension* extension; + bool is_new = + MaybeNewExtension(number, other_extension.descriptor, &extension); + if (is_new) { + // Extension did not already exist in set. + extension->type = other_extension.type; + extension->is_packed = other_extension.is_packed; + extension->is_repeated = true; + } else { + GOOGLE_DCHECK_EQ(extension->type, other_extension.type); + GOOGLE_DCHECK_EQ(extension->is_packed, other_extension.is_packed); + GOOGLE_DCHECK(extension->is_repeated); + } + + switch (cpp_type(other_extension.type)) { +#define HANDLE_TYPE(UPPERCASE, LOWERCASE, REPEATED_TYPE) \ + case WireFormatLite::CPPTYPE_##UPPERCASE: \ + if (is_new) { \ + extension->repeated_##LOWERCASE##_value = \ + Arena::CreateMessage<REPEATED_TYPE>(arena_); \ + } \ + extension->repeated_##LOWERCASE##_value->MergeFrom( \ + *other_extension.repeated_##LOWERCASE##_value); \ + break; + + HANDLE_TYPE(INT32, int32_t, RepeatedField<int32_t>); + HANDLE_TYPE(INT64, int64_t, RepeatedField<int64_t>); + HANDLE_TYPE(UINT32, uint32_t, RepeatedField<uint32_t>); + HANDLE_TYPE(UINT64, uint64_t, RepeatedField<uint64_t>); + HANDLE_TYPE(FLOAT, float, RepeatedField<float>); + HANDLE_TYPE(DOUBLE, double, RepeatedField<double>); + HANDLE_TYPE(BOOL, bool, RepeatedField<bool>); + HANDLE_TYPE(ENUM, enum, RepeatedField<int>); + HANDLE_TYPE(STRING, string, RepeatedPtrField<std::string>); +#undef HANDLE_TYPE + + case WireFormatLite::CPPTYPE_MESSAGE: + if (is_new) { + extension->repeated_message_value = + Arena::CreateMessage<RepeatedPtrField<MessageLite>>(arena_); + } + // We can't call RepeatedPtrField<MessageLite>::MergeFrom() because + // it would attempt to allocate new objects. + RepeatedPtrField<MessageLite>* other_repeated_message = + other_extension.repeated_message_value; + for (int i = 0; i < other_repeated_message->size(); i++) { + const MessageLite& other_message = other_repeated_message->Get(i); + MessageLite* target = + reinterpret_cast<internal::RepeatedPtrFieldBase*>( + extension->repeated_message_value) + ->AddFromCleared<GenericTypeHandler<MessageLite>>(); + if (target == nullptr) { + target = other_message.New(arena_); + extension->repeated_message_value->AddAllocated(target); + } + target->CheckTypeAndMergeFrom(other_message); + } + break; + } + } else { + if (!other_extension.is_cleared) { + switch (cpp_type(other_extension.type)) { +#define HANDLE_TYPE(UPPERCASE, LOWERCASE, CAMELCASE) \ + case WireFormatLite::CPPTYPE_##UPPERCASE: \ + Set##CAMELCASE(number, other_extension.type, \ + other_extension.LOWERCASE##_value, \ + other_extension.descriptor); \ + break; + + HANDLE_TYPE(INT32, int32_t, Int32); + HANDLE_TYPE(INT64, int64_t, Int64); + HANDLE_TYPE(UINT32, uint32_t, UInt32); + HANDLE_TYPE(UINT64, uint64_t, UInt64); + HANDLE_TYPE(FLOAT, float, Float); + HANDLE_TYPE(DOUBLE, double, Double); + HANDLE_TYPE(BOOL, bool, Bool); + HANDLE_TYPE(ENUM, enum, Enum); +#undef HANDLE_TYPE + case WireFormatLite::CPPTYPE_STRING: + SetString(number, other_extension.type, *other_extension.string_value, + other_extension.descriptor); + break; + case WireFormatLite::CPPTYPE_MESSAGE: { + Extension* extension; + bool is_new = + MaybeNewExtension(number, other_extension.descriptor, &extension); + if (is_new) { + extension->type = other_extension.type; + extension->is_packed = other_extension.is_packed; + extension->is_repeated = false; + if (other_extension.is_lazy) { + extension->is_lazy = true; + extension->lazymessage_value = + other_extension.lazymessage_value->New(arena_); + extension->lazymessage_value->MergeFrom( + GetPrototypeForLazyMessage(extendee, number), + *other_extension.lazymessage_value, arena_); + } else { + extension->is_lazy = false; + extension->message_value = + other_extension.message_value->New(arena_); + extension->message_value->CheckTypeAndMergeFrom( + *other_extension.message_value); + } + } else { + GOOGLE_DCHECK_EQ(extension->type, other_extension.type); + GOOGLE_DCHECK_EQ(extension->is_packed, other_extension.is_packed); + GOOGLE_DCHECK(!extension->is_repeated); + if (other_extension.is_lazy) { + if (extension->is_lazy) { + extension->lazymessage_value->MergeFrom( + GetPrototypeForLazyMessage(extendee, number), + *other_extension.lazymessage_value, arena_); + } else { + extension->message_value->CheckTypeAndMergeFrom( + other_extension.lazymessage_value->GetMessage( + *extension->message_value, other_arena)); + } + } else { + if (extension->is_lazy) { + extension->lazymessage_value + ->MutableMessage(*other_extension.message_value, arena_) + ->CheckTypeAndMergeFrom(*other_extension.message_value); + } else { + extension->message_value->CheckTypeAndMergeFrom( + *other_extension.message_value); + } + } + } + extension->is_cleared = false; + break; + } + } + } + } +} + +void ExtensionSet::Swap(const MessageLite* extendee, ExtensionSet* other) { +#ifdef PROTOBUF_FORCE_COPY_IN_SWAP + if (GetArena() != nullptr && GetArena() == other->GetArena()) { +#else // PROTOBUF_FORCE_COPY_IN_SWAP + if (GetArena() == other->GetArena()) { +#endif // !PROTOBUF_FORCE_COPY_IN_SWAP + InternalSwap(other); + } else { + // TODO(cfallin, rohananil): We maybe able to optimize a case where we are + // swapping from heap to arena-allocated extension set, by just Own()'ing + // the extensions. + ExtensionSet extension_set; + extension_set.MergeFrom(extendee, *other); + other->Clear(); + other->MergeFrom(extendee, *this); + Clear(); + MergeFrom(extendee, extension_set); + } +} + +void ExtensionSet::InternalSwap(ExtensionSet* other) { + using std::swap; + swap(arena_, other->arena_); + swap(flat_capacity_, other->flat_capacity_); + swap(flat_size_, other->flat_size_); + swap(map_, other->map_); +} + +void ExtensionSet::SwapExtension(const MessageLite* extendee, + ExtensionSet* other, int number) { + if (this == other) return; + + if (GetArena() == other->GetArena()) { + UnsafeShallowSwapExtension(other, number); + return; + } + + Extension* this_ext = FindOrNull(number); + Extension* other_ext = other->FindOrNull(number); + + if (this_ext == other_ext) return; + + if (this_ext != nullptr && other_ext != nullptr) { + // TODO(cfallin, rohananil): We could further optimize these cases, + // especially avoid creation of ExtensionSet, and move MergeFrom logic + // into Extensions itself (which takes arena as an argument). + // We do it this way to reuse the copy-across-arenas logic already + // implemented in ExtensionSet's MergeFrom. + ExtensionSet temp; + temp.InternalExtensionMergeFrom(extendee, number, *other_ext, + other->GetArena()); + Extension* temp_ext = temp.FindOrNull(number); + + other_ext->Clear(); + other->InternalExtensionMergeFrom(extendee, number, *this_ext, + this->GetArena()); + this_ext->Clear(); + InternalExtensionMergeFrom(extendee, number, *temp_ext, temp.GetArena()); + } else if (this_ext == nullptr) { + InternalExtensionMergeFrom(extendee, number, *other_ext, other->GetArena()); + if (other->GetArena() == nullptr) other_ext->Free(); + other->Erase(number); + } else { + other->InternalExtensionMergeFrom(extendee, number, *this_ext, + this->GetArena()); + if (GetArena() == nullptr) this_ext->Free(); + Erase(number); + } +} + +void ExtensionSet::UnsafeShallowSwapExtension(ExtensionSet* other, int number) { + if (this == other) return; + + Extension* this_ext = FindOrNull(number); + Extension* other_ext = other->FindOrNull(number); + + if (this_ext == other_ext) return; + + GOOGLE_DCHECK_EQ(GetArena(), other->GetArena()); + + if (this_ext != nullptr && other_ext != nullptr) { + std::swap(*this_ext, *other_ext); + } else if (this_ext == nullptr) { + *Insert(number).first = *other_ext; + other->Erase(number); + } else { + *other->Insert(number).first = *this_ext; + Erase(number); + } +} + +bool ExtensionSet::IsInitialized() const { + // Extensions are never required. However, we need to check that all + // embedded messages are initialized. + if (PROTOBUF_PREDICT_FALSE(is_large())) { + for (const auto& kv : *map_.large) { + if (!kv.second.IsInitialized()) return false; + } + return true; + } + for (const KeyValue* it = flat_begin(); it != flat_end(); ++it) { + if (!it->second.IsInitialized()) return false; + } + return true; +} + +const char* ExtensionSet::ParseField(uint64_t tag, const char* ptr, + const MessageLite* extendee, + internal::InternalMetadata* metadata, + internal::ParseContext* ctx) { + GeneratedExtensionFinder finder(extendee); + int number = tag >> 3; + bool was_packed_on_wire; + ExtensionInfo extension; + if (!FindExtensionInfoFromFieldNumber(tag & 7, number, &finder, &extension, + &was_packed_on_wire)) { + return UnknownFieldParse( + tag, metadata->mutable_unknown_fields<std::string>(), ptr, ctx); + } + return ParseFieldWithExtensionInfo<std::string>( + number, was_packed_on_wire, extension, metadata, ptr, ctx); +} + +const char* ExtensionSet::ParseMessageSetItem( + const char* ptr, const MessageLite* extendee, + internal::InternalMetadata* metadata, internal::ParseContext* ctx) { + return ParseMessageSetItemTmpl<MessageLite, std::string>(ptr, extendee, + metadata, ctx); +} + +uint8_t* ExtensionSet::_InternalSerializeImpl( + const MessageLite* extendee, int start_field_number, int end_field_number, + uint8_t* target, io::EpsCopyOutputStream* stream) const { + if (PROTOBUF_PREDICT_FALSE(is_large())) { + const auto& end = map_.large->end(); + for (auto it = map_.large->lower_bound(start_field_number); + it != end && it->first < end_field_number; ++it) { + target = it->second.InternalSerializeFieldWithCachedSizesToArray( + extendee, this, it->first, target, stream); + } + return target; + } + const KeyValue* end = flat_end(); + for (const KeyValue* it = std::lower_bound( + flat_begin(), end, start_field_number, KeyValue::FirstComparator()); + it != end && it->first < end_field_number; ++it) { + target = it->second.InternalSerializeFieldWithCachedSizesToArray( + extendee, this, it->first, target, stream); + } + return target; +} + +uint8_t* ExtensionSet::InternalSerializeMessageSetWithCachedSizesToArray( + const MessageLite* extendee, uint8_t* target, + io::EpsCopyOutputStream* stream) const { + const ExtensionSet* extension_set = this; + ForEach([&target, extendee, stream, extension_set](int number, + const Extension& ext) { + target = ext.InternalSerializeMessageSetItemWithCachedSizesToArray( + extendee, extension_set, number, target, stream); + }); + return target; +} + +size_t ExtensionSet::ByteSize() const { + size_t total_size = 0; + ForEach([&total_size](int number, const Extension& ext) { + total_size += ext.ByteSize(number); + }); + return total_size; +} + +// Defined in extension_set_heavy.cc. +// int ExtensionSet::SpaceUsedExcludingSelf() const + +bool ExtensionSet::MaybeNewExtension(int number, + const FieldDescriptor* descriptor, + Extension** result) { + bool extension_is_new = false; + std::tie(*result, extension_is_new) = Insert(number); + (*result)->descriptor = descriptor; + return extension_is_new; +} + +// =================================================================== +// Methods of ExtensionSet::Extension + +void ExtensionSet::Extension::Clear() { + if (is_repeated) { + switch (cpp_type(type)) { +#define HANDLE_TYPE(UPPERCASE, LOWERCASE) \ + case WireFormatLite::CPPTYPE_##UPPERCASE: \ + repeated_##LOWERCASE##_value->Clear(); \ + break + + HANDLE_TYPE(INT32, int32_t); + HANDLE_TYPE(INT64, int64_t); + HANDLE_TYPE(UINT32, uint32_t); + HANDLE_TYPE(UINT64, uint64_t); + HANDLE_TYPE(FLOAT, float); + HANDLE_TYPE(DOUBLE, double); + HANDLE_TYPE(BOOL, bool); + HANDLE_TYPE(ENUM, enum); + HANDLE_TYPE(STRING, string); + HANDLE_TYPE(MESSAGE, message); +#undef HANDLE_TYPE + } + } else { + if (!is_cleared) { + switch (cpp_type(type)) { + case WireFormatLite::CPPTYPE_STRING: + string_value->clear(); + break; + case WireFormatLite::CPPTYPE_MESSAGE: + if (is_lazy) { + lazymessage_value->Clear(); + } else { + message_value->Clear(); + } + break; + default: + // No need to do anything. Get*() will return the default value + // as long as is_cleared is true and Set*() will overwrite the + // previous value. + break; + } + + is_cleared = true; + } + } +} + +size_t ExtensionSet::Extension::ByteSize(int number) const { + size_t result = 0; + + if (is_repeated) { + if (is_packed) { + switch (real_type(type)) { +#define HANDLE_TYPE(UPPERCASE, CAMELCASE, LOWERCASE) \ + case WireFormatLite::TYPE_##UPPERCASE: \ + for (int i = 0; i < repeated_##LOWERCASE##_value->size(); i++) { \ + result += WireFormatLite::CAMELCASE##Size( \ + repeated_##LOWERCASE##_value->Get(i)); \ + } \ + break + + HANDLE_TYPE(INT32, Int32, int32_t); + HANDLE_TYPE(INT64, Int64, int64_t); + HANDLE_TYPE(UINT32, UInt32, uint32_t); + HANDLE_TYPE(UINT64, UInt64, uint64_t); + HANDLE_TYPE(SINT32, SInt32, int32_t); + HANDLE_TYPE(SINT64, SInt64, int64_t); + HANDLE_TYPE(ENUM, Enum, enum); +#undef HANDLE_TYPE + + // Stuff with fixed size. +#define HANDLE_TYPE(UPPERCASE, CAMELCASE, LOWERCASE) \ + case WireFormatLite::TYPE_##UPPERCASE: \ + result += WireFormatLite::k##CAMELCASE##Size * \ + FromIntSize(repeated_##LOWERCASE##_value->size()); \ + break + HANDLE_TYPE(FIXED32, Fixed32, uint32_t); + HANDLE_TYPE(FIXED64, Fixed64, uint64_t); + HANDLE_TYPE(SFIXED32, SFixed32, int32_t); + HANDLE_TYPE(SFIXED64, SFixed64, int64_t); + HANDLE_TYPE(FLOAT, Float, float); + HANDLE_TYPE(DOUBLE, Double, double); + HANDLE_TYPE(BOOL, Bool, bool); +#undef HANDLE_TYPE + + case WireFormatLite::TYPE_STRING: + case WireFormatLite::TYPE_BYTES: + case WireFormatLite::TYPE_GROUP: + case WireFormatLite::TYPE_MESSAGE: + GOOGLE_LOG(FATAL) << "Non-primitive types can't be packed."; + break; + } + + cached_size = ToCachedSize(result); + if (result > 0) { + result += io::CodedOutputStream::VarintSize32(result); + result += io::CodedOutputStream::VarintSize32(WireFormatLite::MakeTag( + number, WireFormatLite::WIRETYPE_LENGTH_DELIMITED)); + } + } else { + size_t tag_size = WireFormatLite::TagSize(number, real_type(type)); + + switch (real_type(type)) { +#define HANDLE_TYPE(UPPERCASE, CAMELCASE, LOWERCASE) \ + case WireFormatLite::TYPE_##UPPERCASE: \ + result += tag_size * FromIntSize(repeated_##LOWERCASE##_value->size()); \ + for (int i = 0; i < repeated_##LOWERCASE##_value->size(); i++) { \ + result += WireFormatLite::CAMELCASE##Size( \ + repeated_##LOWERCASE##_value->Get(i)); \ + } \ + break + + HANDLE_TYPE(INT32, Int32, int32_t); + HANDLE_TYPE(INT64, Int64, int64_t); + HANDLE_TYPE(UINT32, UInt32, uint32_t); + HANDLE_TYPE(UINT64, UInt64, uint64_t); + HANDLE_TYPE(SINT32, SInt32, int32_t); + HANDLE_TYPE(SINT64, SInt64, int64_t); + HANDLE_TYPE(STRING, String, string); + HANDLE_TYPE(BYTES, Bytes, string); + HANDLE_TYPE(ENUM, Enum, enum); + HANDLE_TYPE(GROUP, Group, message); + HANDLE_TYPE(MESSAGE, Message, message); +#undef HANDLE_TYPE + + // Stuff with fixed size. +#define HANDLE_TYPE(UPPERCASE, CAMELCASE, LOWERCASE) \ + case WireFormatLite::TYPE_##UPPERCASE: \ + result += (tag_size + WireFormatLite::k##CAMELCASE##Size) * \ + FromIntSize(repeated_##LOWERCASE##_value->size()); \ + break + HANDLE_TYPE(FIXED32, Fixed32, uint32_t); + HANDLE_TYPE(FIXED64, Fixed64, uint64_t); + HANDLE_TYPE(SFIXED32, SFixed32, int32_t); + HANDLE_TYPE(SFIXED64, SFixed64, int64_t); + HANDLE_TYPE(FLOAT, Float, float); + HANDLE_TYPE(DOUBLE, Double, double); + HANDLE_TYPE(BOOL, Bool, bool); +#undef HANDLE_TYPE + } + } + } else if (!is_cleared) { + result += WireFormatLite::TagSize(number, real_type(type)); + switch (real_type(type)) { +#define HANDLE_TYPE(UPPERCASE, CAMELCASE, LOWERCASE) \ + case WireFormatLite::TYPE_##UPPERCASE: \ + result += WireFormatLite::CAMELCASE##Size(LOWERCASE); \ + break + + HANDLE_TYPE(INT32, Int32, int32_t_value); + HANDLE_TYPE(INT64, Int64, int64_t_value); + HANDLE_TYPE(UINT32, UInt32, uint32_t_value); + HANDLE_TYPE(UINT64, UInt64, uint64_t_value); + HANDLE_TYPE(SINT32, SInt32, int32_t_value); + HANDLE_TYPE(SINT64, SInt64, int64_t_value); + HANDLE_TYPE(STRING, String, *string_value); + HANDLE_TYPE(BYTES, Bytes, *string_value); + HANDLE_TYPE(ENUM, Enum, enum_value); + HANDLE_TYPE(GROUP, Group, *message_value); +#undef HANDLE_TYPE + case WireFormatLite::TYPE_MESSAGE: { + if (is_lazy) { + size_t size = lazymessage_value->ByteSizeLong(); + result += io::CodedOutputStream::VarintSize32(size) + size; + } else { + result += WireFormatLite::MessageSize(*message_value); + } + break; + } + + // Stuff with fixed size. +#define HANDLE_TYPE(UPPERCASE, CAMELCASE) \ + case WireFormatLite::TYPE_##UPPERCASE: \ + result += WireFormatLite::k##CAMELCASE##Size; \ + break + HANDLE_TYPE(FIXED32, Fixed32); + HANDLE_TYPE(FIXED64, Fixed64); + HANDLE_TYPE(SFIXED32, SFixed32); + HANDLE_TYPE(SFIXED64, SFixed64); + HANDLE_TYPE(FLOAT, Float); + HANDLE_TYPE(DOUBLE, Double); + HANDLE_TYPE(BOOL, Bool); +#undef HANDLE_TYPE + } + } + + return result; +} + +int ExtensionSet::Extension::GetSize() const { + GOOGLE_DCHECK(is_repeated); + switch (cpp_type(type)) { +#define HANDLE_TYPE(UPPERCASE, LOWERCASE) \ + case WireFormatLite::CPPTYPE_##UPPERCASE: \ + return repeated_##LOWERCASE##_value->size() + + HANDLE_TYPE(INT32, int32_t); + HANDLE_TYPE(INT64, int64_t); + HANDLE_TYPE(UINT32, uint32_t); + HANDLE_TYPE(UINT64, uint64_t); + HANDLE_TYPE(FLOAT, float); + HANDLE_TYPE(DOUBLE, double); + HANDLE_TYPE(BOOL, bool); + HANDLE_TYPE(ENUM, enum); + HANDLE_TYPE(STRING, string); + HANDLE_TYPE(MESSAGE, message); +#undef HANDLE_TYPE + } + + GOOGLE_LOG(FATAL) << "Can't get here."; + return 0; +} + +// This function deletes all allocated objects. This function should be only +// called if the Extension was created without an arena. +void ExtensionSet::Extension::Free() { + if (is_repeated) { + switch (cpp_type(type)) { +#define HANDLE_TYPE(UPPERCASE, LOWERCASE) \ + case WireFormatLite::CPPTYPE_##UPPERCASE: \ + delete repeated_##LOWERCASE##_value; \ + break + + HANDLE_TYPE(INT32, int32_t); + HANDLE_TYPE(INT64, int64_t); + HANDLE_TYPE(UINT32, uint32_t); + HANDLE_TYPE(UINT64, uint64_t); + HANDLE_TYPE(FLOAT, float); + HANDLE_TYPE(DOUBLE, double); + HANDLE_TYPE(BOOL, bool); + HANDLE_TYPE(ENUM, enum); + HANDLE_TYPE(STRING, string); + HANDLE_TYPE(MESSAGE, message); +#undef HANDLE_TYPE + } + } else { + switch (cpp_type(type)) { + case WireFormatLite::CPPTYPE_STRING: + delete string_value; + break; + case WireFormatLite::CPPTYPE_MESSAGE: + if (is_lazy) { + delete lazymessage_value; + } else { + delete message_value; + } + break; + default: + break; + } + } +} + +// Defined in extension_set_heavy.cc. +// int ExtensionSet::Extension::SpaceUsedExcludingSelf() const + +bool ExtensionSet::Extension::IsInitialized() const { + if (cpp_type(type) == WireFormatLite::CPPTYPE_MESSAGE) { + if (is_repeated) { + for (int i = 0; i < repeated_message_value->size(); i++) { + if (!repeated_message_value->Get(i).IsInitialized()) { + return false; + } + } + } else { + if (!is_cleared) { + if (is_lazy) { + if (!lazymessage_value->IsInitialized()) return false; + } else { + if (!message_value->IsInitialized()) return false; + } + } + } + } + return true; +} + +// Dummy key method to avoid weak vtable. +void ExtensionSet::LazyMessageExtension::UnusedKeyMethod() {} + +const ExtensionSet::Extension* ExtensionSet::FindOrNull(int key) const { + if (flat_size_ == 0) { + return nullptr; + } else if (PROTOBUF_PREDICT_TRUE(!is_large())) { + auto it = std::lower_bound(flat_begin(), flat_end() - 1, key, + KeyValue::FirstComparator()); + return it->first == key ? &it->second : nullptr; + } else { + return FindOrNullInLargeMap(key); + } +} + +const ExtensionSet::Extension* ExtensionSet::FindOrNullInLargeMap( + int key) const { + assert(is_large()); + LargeMap::const_iterator it = map_.large->find(key); + if (it != map_.large->end()) { + return &it->second; + } + return nullptr; +} + +ExtensionSet::Extension* ExtensionSet::FindOrNull(int key) { + const auto* const_this = this; + return const_cast<ExtensionSet::Extension*>(const_this->FindOrNull(key)); +} + +ExtensionSet::Extension* ExtensionSet::FindOrNullInLargeMap(int key) { + const auto* const_this = this; + return const_cast<ExtensionSet::Extension*>( + const_this->FindOrNullInLargeMap(key)); +} + +std::pair<ExtensionSet::Extension*, bool> ExtensionSet::Insert(int key) { + if (PROTOBUF_PREDICT_FALSE(is_large())) { + auto maybe = map_.large->insert({key, Extension()}); + return {&maybe.first->second, maybe.second}; + } + KeyValue* end = flat_end(); + KeyValue* it = + std::lower_bound(flat_begin(), end, key, KeyValue::FirstComparator()); + if (it != end && it->first == key) { + return {&it->second, false}; + } + if (flat_size_ < flat_capacity_) { + std::copy_backward(it, end, end + 1); + ++flat_size_; + it->first = key; + it->second = Extension(); + return {&it->second, true}; + } + GrowCapacity(flat_size_ + 1); + return Insert(key); +} + +void ExtensionSet::GrowCapacity(size_t minimum_new_capacity) { + if (PROTOBUF_PREDICT_FALSE(is_large())) { + return; // LargeMap does not have a "reserve" method. + } + if (flat_capacity_ >= minimum_new_capacity) { + return; + } + + auto new_flat_capacity = flat_capacity_; + do { + new_flat_capacity = new_flat_capacity == 0 ? 1 : new_flat_capacity * 4; + } while (new_flat_capacity < minimum_new_capacity); + + const KeyValue* begin = flat_begin(); + const KeyValue* end = flat_end(); + AllocatedData new_map; + if (new_flat_capacity > kMaximumFlatCapacity) { + new_map.large = Arena::Create<LargeMap>(arena_); + LargeMap::iterator hint = new_map.large->begin(); + for (const KeyValue* it = begin; it != end; ++it) { + hint = new_map.large->insert(hint, {it->first, it->second}); + } + flat_size_ = static_cast<uint16_t>(-1); + GOOGLE_DCHECK(is_large()); + } else { + new_map.flat = Arena::CreateArray<KeyValue>(arena_, new_flat_capacity); + std::copy(begin, end, new_map.flat); + } + + if (arena_ == nullptr) { + DeleteFlatMap(begin, flat_capacity_); + } + flat_capacity_ = new_flat_capacity; + map_ = new_map; +} + +#if (__cplusplus < 201703) && \ + (!defined(_MSC_VER) || (_MSC_VER >= 1900 && _MSC_VER < 1912)) +// static +constexpr uint16_t ExtensionSet::kMaximumFlatCapacity; +#endif // (__cplusplus < 201703) && (!defined(_MSC_VER) || (_MSC_VER >= 1900 + // && _MSC_VER < 1912)) + +void ExtensionSet::Erase(int key) { + if (PROTOBUF_PREDICT_FALSE(is_large())) { + map_.large->erase(key); + return; + } + KeyValue* end = flat_end(); + KeyValue* it = + std::lower_bound(flat_begin(), end, key, KeyValue::FirstComparator()); + if (it != end && it->first == key) { + std::copy(it + 1, end, it); + --flat_size_; + } +} + +// ================================================================== +// Default repeated field instances for iterator-compatible accessors + +const RepeatedPrimitiveDefaults* RepeatedPrimitiveDefaults::default_instance() { + static auto instance = OnShutdownDelete(new RepeatedPrimitiveDefaults); + return instance; +} + +const RepeatedStringTypeTraits::RepeatedFieldType* +RepeatedStringTypeTraits::GetDefaultRepeatedField() { + static auto instance = OnShutdownDelete(new RepeatedFieldType); + return instance; +} + +uint8_t* ExtensionSet::Extension::InternalSerializeFieldWithCachedSizesToArray( + const MessageLite* extendee, const ExtensionSet* extension_set, int number, + uint8_t* target, io::EpsCopyOutputStream* stream) const { + if (is_repeated) { + if (is_packed) { + if (cached_size == 0) return target; + + target = stream->EnsureSpace(target); + target = WireFormatLite::WriteTagToArray( + number, WireFormatLite::WIRETYPE_LENGTH_DELIMITED, target); + target = WireFormatLite::WriteInt32NoTagToArray(cached_size, target); + + switch (real_type(type)) { +#define HANDLE_TYPE(UPPERCASE, CAMELCASE, LOWERCASE) \ + case WireFormatLite::TYPE_##UPPERCASE: \ + for (int i = 0; i < repeated_##LOWERCASE##_value->size(); i++) { \ + target = stream->EnsureSpace(target); \ + target = WireFormatLite::Write##CAMELCASE##NoTagToArray( \ + repeated_##LOWERCASE##_value->Get(i), target); \ + } \ + break + + HANDLE_TYPE(INT32, Int32, int32_t); + HANDLE_TYPE(INT64, Int64, int64_t); + HANDLE_TYPE(UINT32, UInt32, uint32_t); + HANDLE_TYPE(UINT64, UInt64, uint64_t); + HANDLE_TYPE(SINT32, SInt32, int32_t); + HANDLE_TYPE(SINT64, SInt64, int64_t); + HANDLE_TYPE(FIXED32, Fixed32, uint32_t); + HANDLE_TYPE(FIXED64, Fixed64, uint64_t); + HANDLE_TYPE(SFIXED32, SFixed32, int32_t); + HANDLE_TYPE(SFIXED64, SFixed64, int64_t); + HANDLE_TYPE(FLOAT, Float, float); + HANDLE_TYPE(DOUBLE, Double, double); + HANDLE_TYPE(BOOL, Bool, bool); + HANDLE_TYPE(ENUM, Enum, enum); +#undef HANDLE_TYPE + + case WireFormatLite::TYPE_STRING: + case WireFormatLite::TYPE_BYTES: + case WireFormatLite::TYPE_GROUP: + case WireFormatLite::TYPE_MESSAGE: + GOOGLE_LOG(FATAL) << "Non-primitive types can't be packed."; + break; + } + } else { + switch (real_type(type)) { +#define HANDLE_TYPE(UPPERCASE, CAMELCASE, LOWERCASE) \ + case WireFormatLite::TYPE_##UPPERCASE: \ + for (int i = 0; i < repeated_##LOWERCASE##_value->size(); i++) { \ + target = stream->EnsureSpace(target); \ + target = WireFormatLite::Write##CAMELCASE##ToArray( \ + number, repeated_##LOWERCASE##_value->Get(i), target); \ + } \ + break + + HANDLE_TYPE(INT32, Int32, int32_t); + HANDLE_TYPE(INT64, Int64, int64_t); + HANDLE_TYPE(UINT32, UInt32, uint32_t); + HANDLE_TYPE(UINT64, UInt64, uint64_t); + HANDLE_TYPE(SINT32, SInt32, int32_t); + HANDLE_TYPE(SINT64, SInt64, int64_t); + HANDLE_TYPE(FIXED32, Fixed32, uint32_t); + HANDLE_TYPE(FIXED64, Fixed64, uint64_t); + HANDLE_TYPE(SFIXED32, SFixed32, int32_t); + HANDLE_TYPE(SFIXED64, SFixed64, int64_t); + HANDLE_TYPE(FLOAT, Float, float); + HANDLE_TYPE(DOUBLE, Double, double); + HANDLE_TYPE(BOOL, Bool, bool); + HANDLE_TYPE(ENUM, Enum, enum); +#undef HANDLE_TYPE +#define HANDLE_TYPE(UPPERCASE, CAMELCASE, LOWERCASE) \ + case WireFormatLite::TYPE_##UPPERCASE: \ + for (int i = 0; i < repeated_##LOWERCASE##_value->size(); i++) { \ + target = stream->EnsureSpace(target); \ + target = stream->WriteString( \ + number, repeated_##LOWERCASE##_value->Get(i), target); \ + } \ + break + HANDLE_TYPE(STRING, String, string); + HANDLE_TYPE(BYTES, Bytes, string); +#undef HANDLE_TYPE + case WireFormatLite::TYPE_GROUP: + for (int i = 0; i < repeated_message_value->size(); i++) { + target = stream->EnsureSpace(target); + target = WireFormatLite::InternalWriteGroup( + number, repeated_message_value->Get(i), target, stream); + } + break; + case WireFormatLite::TYPE_MESSAGE: + for (int i = 0; i < repeated_message_value->size(); i++) { + auto& msg = repeated_message_value->Get(i); + target = WireFormatLite::InternalWriteMessage( + number, msg, msg.GetCachedSize(), target, stream); + } + break; + } + } + } else if (!is_cleared) { + switch (real_type(type)) { +#define HANDLE_TYPE(UPPERCASE, CAMELCASE, VALUE) \ + case WireFormatLite::TYPE_##UPPERCASE: \ + target = stream->EnsureSpace(target); \ + target = WireFormatLite::Write##CAMELCASE##ToArray(number, VALUE, target); \ + break + + HANDLE_TYPE(INT32, Int32, int32_t_value); + HANDLE_TYPE(INT64, Int64, int64_t_value); + HANDLE_TYPE(UINT32, UInt32, uint32_t_value); + HANDLE_TYPE(UINT64, UInt64, uint64_t_value); + HANDLE_TYPE(SINT32, SInt32, int32_t_value); + HANDLE_TYPE(SINT64, SInt64, int64_t_value); + HANDLE_TYPE(FIXED32, Fixed32, uint32_t_value); + HANDLE_TYPE(FIXED64, Fixed64, uint64_t_value); + HANDLE_TYPE(SFIXED32, SFixed32, int32_t_value); + HANDLE_TYPE(SFIXED64, SFixed64, int64_t_value); + HANDLE_TYPE(FLOAT, Float, float_value); + HANDLE_TYPE(DOUBLE, Double, double_value); + HANDLE_TYPE(BOOL, Bool, bool_value); + HANDLE_TYPE(ENUM, Enum, enum_value); +#undef HANDLE_TYPE +#define HANDLE_TYPE(UPPERCASE, CAMELCASE, VALUE) \ + case WireFormatLite::TYPE_##UPPERCASE: \ + target = stream->EnsureSpace(target); \ + target = stream->WriteString(number, VALUE, target); \ + break + HANDLE_TYPE(STRING, String, *string_value); + HANDLE_TYPE(BYTES, Bytes, *string_value); +#undef HANDLE_TYPE + case WireFormatLite::TYPE_GROUP: + target = stream->EnsureSpace(target); + target = WireFormatLite::InternalWriteGroup(number, *message_value, + target, stream); + break; + case WireFormatLite::TYPE_MESSAGE: + if (is_lazy) { + const auto* prototype = + extension_set->GetPrototypeForLazyMessage(extendee, number); + target = lazymessage_value->WriteMessageToArray(prototype, number, + target, stream); + } else { + target = WireFormatLite::InternalWriteMessage( + number, *message_value, message_value->GetCachedSize(), target, + stream); + } + break; + } + } + return target; +} + +const MessageLite* ExtensionSet::GetPrototypeForLazyMessage( + const MessageLite* extendee, int number) const { + GeneratedExtensionFinder finder(extendee); + bool was_packed_on_wire = false; + ExtensionInfo extension_info; + if (!FindExtensionInfoFromFieldNumber( + WireFormatLite::WireType::WIRETYPE_LENGTH_DELIMITED, number, &finder, + &extension_info, &was_packed_on_wire)) { + return nullptr; + } + return extension_info.message_info.prototype; +} + +uint8_t* +ExtensionSet::Extension::InternalSerializeMessageSetItemWithCachedSizesToArray( + const MessageLite* extendee, const ExtensionSet* extension_set, int number, + uint8_t* target, io::EpsCopyOutputStream* stream) const { + if (type != WireFormatLite::TYPE_MESSAGE || is_repeated) { + // Not a valid MessageSet extension, but serialize it the normal way. + GOOGLE_LOG(WARNING) << "Invalid message set extension."; + return InternalSerializeFieldWithCachedSizesToArray(extendee, extension_set, + number, target, stream); + } + + if (is_cleared) return target; + + target = stream->EnsureSpace(target); + // Start group. + target = io::CodedOutputStream::WriteTagToArray( + WireFormatLite::kMessageSetItemStartTag, target); + // Write type ID. + target = WireFormatLite::WriteUInt32ToArray( + WireFormatLite::kMessageSetTypeIdNumber, number, target); + // Write message. + if (is_lazy) { + const auto* prototype = + extension_set->GetPrototypeForLazyMessage(extendee, number); + target = lazymessage_value->WriteMessageToArray( + prototype, WireFormatLite::kMessageSetMessageNumber, target, stream); + } else { + target = WireFormatLite::InternalWriteMessage( + WireFormatLite::kMessageSetMessageNumber, *message_value, + message_value->GetCachedSize(), target, stream); + } + // End group. + target = stream->EnsureSpace(target); + target = io::CodedOutputStream::WriteTagToArray( + WireFormatLite::kMessageSetItemEndTag, target); + return target; +} + +size_t ExtensionSet::Extension::MessageSetItemByteSize(int number) const { + if (type != WireFormatLite::TYPE_MESSAGE || is_repeated) { + // Not a valid MessageSet extension, but compute the byte size for it the + // normal way. + return ByteSize(number); + } + + if (is_cleared) return 0; + + size_t our_size = WireFormatLite::kMessageSetItemTagsSize; + + // type_id + our_size += io::CodedOutputStream::VarintSize32(number); + + // message + size_t message_size = 0; + if (is_lazy) { + message_size = lazymessage_value->ByteSizeLong(); + } else { + message_size = message_value->ByteSizeLong(); + } + + our_size += io::CodedOutputStream::VarintSize32(message_size); + our_size += message_size; + + return our_size; +} + +size_t ExtensionSet::MessageSetByteSize() const { + size_t total_size = 0; + ForEach([&total_size](int number, const Extension& ext) { + total_size += ext.MessageSetItemByteSize(number); + }); + return total_size; +} + +LazyEagerVerifyFnType FindExtensionLazyEagerVerifyFn( + const MessageLite* extendee, int number) { + const ExtensionInfo* registered = FindRegisteredExtension(extendee, number); + if (registered != nullptr) { + return registered->lazy_eager_verify_func; + } + return nullptr; +} + + +} // namespace internal +} // namespace protobuf +} // namespace google + +#include <google/protobuf/port_undef.inc> diff --git a/toolkit/components/protobuf/src/google/protobuf/extension_set.h b/toolkit/components/protobuf/src/google/protobuf/extension_set.h new file mode 100644 index 0000000000..0e6d052110 --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/extension_set.h @@ -0,0 +1,1561 @@ +// 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. + +// Author: kenton@google.com (Kenton Varda) +// Based on original Protocol Buffers design by +// Sanjay Ghemawat, Jeff Dean, and others. +// +// This header is logically internal, but is made public because it is used +// from protocol-compiler-generated code, which may reside in other components. + +#ifndef GOOGLE_PROTOBUF_EXTENSION_SET_H__ +#define GOOGLE_PROTOBUF_EXTENSION_SET_H__ + + +#include <algorithm> +#include <cassert> +#include <map> +#include <string> +#include <utility> +#include <vector> + +#include <google/protobuf/stubs/common.h> +#include <google/protobuf/stubs/logging.h> +#include <google/protobuf/io/coded_stream.h> +#include <google/protobuf/port.h> +#include <google/protobuf/parse_context.h> +#include <google/protobuf/repeated_field.h> +#include <google/protobuf/wire_format_lite.h> + +// clang-format off +#include <google/protobuf/port_def.inc> // Must be last +// clang-format on + +#ifdef SWIG +#error "You cannot SWIG proto headers" +#endif + +namespace google { +namespace protobuf { +class Arena; +class Descriptor; // descriptor.h +class FieldDescriptor; // descriptor.h +class DescriptorPool; // descriptor.h +class MessageLite; // message_lite.h +class Message; // message.h +class MessageFactory; // message.h +class Reflection; // message.h +class UnknownFieldSet; // unknown_field_set.h +namespace internal { +class FieldSkipper; // wire_format_lite.h +enum class LazyVerifyOption; +} // namespace internal +} // namespace protobuf +} // namespace google + +namespace google { +namespace protobuf { +namespace internal { + +class InternalMetadata; + +// Used to store values of type WireFormatLite::FieldType without having to +// #include wire_format_lite.h. Also, ensures that we use only one byte to +// store these values, which is important to keep the layout of +// ExtensionSet::Extension small. +typedef uint8_t FieldType; + +// A function which, given an integer value, returns true if the number +// matches one of the defined values for the corresponding enum type. This +// is used with RegisterEnumExtension, below. +typedef bool EnumValidityFunc(int number); + +// Version of the above which takes an argument. This is needed to deal with +// extensions that are not compiled in. +typedef bool EnumValidityFuncWithArg(const void* arg, int number); + +// Information about a registered extension. +struct ExtensionInfo { + constexpr ExtensionInfo() : enum_validity_check() {} + constexpr ExtensionInfo(const MessageLite* extendee, int param_number, + FieldType type_param, bool isrepeated, bool ispacked, + LazyEagerVerifyFnType verify_func) + : message(extendee), + number(param_number), + type(type_param), + is_repeated(isrepeated), + is_packed(ispacked), + enum_validity_check(), + lazy_eager_verify_func(verify_func) {} + + const MessageLite* message = nullptr; + int number = 0; + + FieldType type = 0; + bool is_repeated = false; + bool is_packed = false; + + struct EnumValidityCheck { + EnumValidityFuncWithArg* func; + const void* arg; + }; + + struct MessageInfo { + const MessageLite* prototype; + }; + + union { + EnumValidityCheck enum_validity_check; + MessageInfo message_info; + }; + + // The descriptor for this extension, if one exists and is known. May be + // nullptr. Must not be nullptr if the descriptor for the extension does not + // live in the same pool as the descriptor for the containing type. + const FieldDescriptor* descriptor = nullptr; + + // If this field is potentially lazy this function can be used as a cheap + // verification of the raw bytes. + // If nullptr then no verification is performed. + LazyEagerVerifyFnType lazy_eager_verify_func = nullptr; +}; + +// An ExtensionFinder is an object which looks up extension definitions. It +// must implement this method: +// +// bool Find(int number, ExtensionInfo* output); + +// GeneratedExtensionFinder is an ExtensionFinder which finds extensions +// defined in .proto files which have been compiled into the binary. +class PROTOBUF_EXPORT GeneratedExtensionFinder { + public: + explicit GeneratedExtensionFinder(const MessageLite* extendee) + : extendee_(extendee) {} + + // Returns true and fills in *output if found, otherwise returns false. + bool Find(int number, ExtensionInfo* output); + + private: + const MessageLite* extendee_; +}; + +// Note: extension_set_heavy.cc defines DescriptorPoolExtensionFinder for +// finding extensions from a DescriptorPool. + +// This is an internal helper class intended for use within the protocol buffer +// library and generated classes. Clients should not use it directly. Instead, +// use the generated accessors such as GetExtension() of the class being +// extended. +// +// This class manages extensions for a protocol message object. The +// message's HasExtension(), GetExtension(), MutableExtension(), and +// ClearExtension() methods are just thin wrappers around the embedded +// ExtensionSet. When parsing, if a tag number is encountered which is +// inside one of the message type's extension ranges, the tag is passed +// off to the ExtensionSet for parsing. Etc. +class PROTOBUF_EXPORT ExtensionSet { + public: + constexpr ExtensionSet(); + explicit ExtensionSet(Arena* arena); + ExtensionSet(ArenaInitialized, Arena* arena) : ExtensionSet(arena) {} + ~ExtensionSet(); + + // These are called at startup by protocol-compiler-generated code to + // register known extensions. The registrations are used by ParseField() + // to look up extensions for parsed field numbers. Note that dynamic parsing + // does not use ParseField(); only protocol-compiler-generated parsing + // methods do. + static void RegisterExtension(const MessageLite* extendee, int number, + FieldType type, bool is_repeated, + bool is_packed, + LazyEagerVerifyFnType verify_func); + static void RegisterEnumExtension(const MessageLite* extendee, int number, + FieldType type, bool is_repeated, + bool is_packed, EnumValidityFunc* is_valid); + static void RegisterMessageExtension(const MessageLite* extendee, int number, + FieldType type, bool is_repeated, + bool is_packed, + const MessageLite* prototype, + LazyEagerVerifyFnType verify_func); + + // ================================================================= + + // Add all fields which are currently present to the given vector. This + // is useful to implement Reflection::ListFields(). + void AppendToList(const Descriptor* extendee, const DescriptorPool* pool, + std::vector<const FieldDescriptor*>* output) const; + + // ================================================================= + // Accessors + // + // Generated message classes include type-safe templated wrappers around + // these methods. Generally you should use those rather than call these + // directly, unless you are doing low-level memory management. + // + // When calling any of these accessors, the extension number requested + // MUST exist in the DescriptorPool provided to the constructor. Otherwise, + // the method will fail an assert. Normally, though, you would not call + // these directly; you would either call the generated accessors of your + // message class (e.g. GetExtension()) or you would call the accessors + // of the reflection interface. In both cases, it is impossible to + // trigger this assert failure: the generated accessors only accept + // linked-in extension types as parameters, while the Reflection interface + // requires you to provide the FieldDescriptor describing the extension. + // + // When calling any of these accessors, a protocol-compiler-generated + // implementation of the extension corresponding to the number MUST + // be linked in, and the FieldDescriptor used to refer to it MUST be + // the one generated by that linked-in code. Otherwise, the method will + // die on an assert failure. The message objects returned by the message + // accessors are guaranteed to be of the correct linked-in type. + // + // These methods pretty much match Reflection except that: + // - They're not virtual. + // - They identify fields by number rather than FieldDescriptors. + // - They identify enum values using integers rather than descriptors. + // - Strings provide Mutable() in addition to Set() accessors. + + bool Has(int number) const; + int ExtensionSize(int number) const; // Size of a repeated extension. + int NumExtensions() const; // The number of extensions + FieldType ExtensionType(int number) const; + void ClearExtension(int number); + + // singular fields ------------------------------------------------- + + int32_t GetInt32(int number, int32_t default_value) const; + int64_t GetInt64(int number, int64_t default_value) const; + uint32_t GetUInt32(int number, uint32_t default_value) const; + uint64_t GetUInt64(int number, uint64_t default_value) const; + float GetFloat(int number, float default_value) const; + double GetDouble(int number, double default_value) const; + bool GetBool(int number, bool default_value) const; + int GetEnum(int number, int default_value) const; + const std::string& GetString(int number, + const std::string& default_value) const; + const MessageLite& GetMessage(int number, + const MessageLite& default_value) const; + const MessageLite& GetMessage(int number, const Descriptor* message_type, + MessageFactory* factory) const; + + // |descriptor| may be nullptr so long as it is known that the descriptor for + // the extension lives in the same pool as the descriptor for the containing + // type. +#define desc const FieldDescriptor* descriptor // avoid line wrapping + void SetInt32(int number, FieldType type, int32_t value, desc); + void SetInt64(int number, FieldType type, int64_t value, desc); + void SetUInt32(int number, FieldType type, uint32_t value, desc); + void SetUInt64(int number, FieldType type, uint64_t value, desc); + void SetFloat(int number, FieldType type, float value, desc); + void SetDouble(int number, FieldType type, double value, desc); + void SetBool(int number, FieldType type, bool value, desc); + void SetEnum(int number, FieldType type, int value, desc); + void SetString(int number, FieldType type, std::string value, desc); + std::string* MutableString(int number, FieldType type, desc); + MessageLite* MutableMessage(int number, FieldType type, + const MessageLite& prototype, desc); + MessageLite* MutableMessage(const FieldDescriptor* descriptor, + MessageFactory* factory); + // Adds the given message to the ExtensionSet, taking ownership of the + // message object. Existing message with the same number will be deleted. + // If "message" is nullptr, this is equivalent to "ClearExtension(number)". + void SetAllocatedMessage(int number, FieldType type, + const FieldDescriptor* descriptor, + MessageLite* message); + void UnsafeArenaSetAllocatedMessage(int number, FieldType type, + const FieldDescriptor* descriptor, + MessageLite* message); + PROTOBUF_NODISCARD MessageLite* ReleaseMessage(int number, + const MessageLite& prototype); + MessageLite* UnsafeArenaReleaseMessage(int number, + const MessageLite& prototype); + + PROTOBUF_NODISCARD MessageLite* ReleaseMessage( + const FieldDescriptor* descriptor, MessageFactory* factory); + MessageLite* UnsafeArenaReleaseMessage(const FieldDescriptor* descriptor, + MessageFactory* factory); +#undef desc + Arena* GetArena() const { return arena_; } + + // repeated fields ------------------------------------------------- + + // Fetches a RepeatedField extension by number; returns |default_value| + // if no such extension exists. User should not touch this directly; it is + // used by the GetRepeatedExtension() method. + const void* GetRawRepeatedField(int number, const void* default_value) const; + // Fetches a mutable version of a RepeatedField extension by number, + // instantiating one if none exists. Similar to above, user should not use + // this directly; it underlies MutableRepeatedExtension(). + void* MutableRawRepeatedField(int number, FieldType field_type, bool packed, + const FieldDescriptor* desc); + + // This is an overload of MutableRawRepeatedField to maintain compatibility + // with old code using a previous API. This version of + // MutableRawRepeatedField() will GOOGLE_CHECK-fail on a missing extension. + // (E.g.: borg/clients/internal/proto1/proto2_reflection.cc.) + void* MutableRawRepeatedField(int number); + + int32_t GetRepeatedInt32(int number, int index) const; + int64_t GetRepeatedInt64(int number, int index) const; + uint32_t GetRepeatedUInt32(int number, int index) const; + uint64_t GetRepeatedUInt64(int number, int index) const; + float GetRepeatedFloat(int number, int index) const; + double GetRepeatedDouble(int number, int index) const; + bool GetRepeatedBool(int number, int index) const; + int GetRepeatedEnum(int number, int index) const; + const std::string& GetRepeatedString(int number, int index) const; + const MessageLite& GetRepeatedMessage(int number, int index) const; + + void SetRepeatedInt32(int number, int index, int32_t value); + void SetRepeatedInt64(int number, int index, int64_t value); + void SetRepeatedUInt32(int number, int index, uint32_t value); + void SetRepeatedUInt64(int number, int index, uint64_t value); + void SetRepeatedFloat(int number, int index, float value); + void SetRepeatedDouble(int number, int index, double value); + void SetRepeatedBool(int number, int index, bool value); + void SetRepeatedEnum(int number, int index, int value); + void SetRepeatedString(int number, int index, std::string value); + std::string* MutableRepeatedString(int number, int index); + MessageLite* MutableRepeatedMessage(int number, int index); + +#define desc const FieldDescriptor* descriptor // avoid line wrapping + void AddInt32(int number, FieldType type, bool packed, int32_t value, desc); + void AddInt64(int number, FieldType type, bool packed, int64_t value, desc); + void AddUInt32(int number, FieldType type, bool packed, uint32_t value, desc); + void AddUInt64(int number, FieldType type, bool packed, uint64_t value, desc); + void AddFloat(int number, FieldType type, bool packed, float value, desc); + void AddDouble(int number, FieldType type, bool packed, double value, desc); + void AddBool(int number, FieldType type, bool packed, bool value, desc); + void AddEnum(int number, FieldType type, bool packed, int value, desc); + void AddString(int number, FieldType type, std::string value, desc); + std::string* AddString(int number, FieldType type, desc); + MessageLite* AddMessage(int number, FieldType type, + const MessageLite& prototype, desc); + MessageLite* AddMessage(const FieldDescriptor* descriptor, + MessageFactory* factory); + void AddAllocatedMessage(const FieldDescriptor* descriptor, + MessageLite* new_entry); + void UnsafeArenaAddAllocatedMessage(const FieldDescriptor* descriptor, + MessageLite* new_entry); +#undef desc + + void RemoveLast(int number); + PROTOBUF_NODISCARD MessageLite* ReleaseLast(int number); + MessageLite* UnsafeArenaReleaseLast(int number); + void SwapElements(int number, int index1, int index2); + + // ================================================================= + // convenience methods for implementing methods of Message + // + // These could all be implemented in terms of the other methods of this + // class, but providing them here helps keep the generated code size down. + + void Clear(); + void MergeFrom(const MessageLite* extendee, const ExtensionSet& other); + void Swap(const MessageLite* extendee, ExtensionSet* other); + void InternalSwap(ExtensionSet* other); + void SwapExtension(const MessageLite* extendee, ExtensionSet* other, + int number); + void UnsafeShallowSwapExtension(ExtensionSet* other, int number); + bool IsInitialized() const; + + // Lite parser + const char* ParseField(uint64_t tag, const char* ptr, + const MessageLite* extendee, + internal::InternalMetadata* metadata, + internal::ParseContext* ctx); + // Full parser + const char* ParseField(uint64_t tag, const char* ptr, const Message* extendee, + internal::InternalMetadata* metadata, + internal::ParseContext* ctx); + template <typename Msg> + const char* ParseMessageSet(const char* ptr, const Msg* extendee, + InternalMetadata* metadata, + internal::ParseContext* ctx) { + struct MessageSetItem { + const char* _InternalParse(const char* ptr, ParseContext* ctx) { + return me->ParseMessageSetItem(ptr, extendee, metadata, ctx); + } + ExtensionSet* me; + const Msg* extendee; + InternalMetadata* metadata; + } item{this, extendee, metadata}; + while (!ctx->Done(&ptr)) { + uint32_t tag; + ptr = ReadTag(ptr, &tag); + GOOGLE_PROTOBUF_PARSER_ASSERT(ptr); + if (tag == WireFormatLite::kMessageSetItemStartTag) { + ptr = ctx->ParseGroup(&item, ptr, tag); + GOOGLE_PROTOBUF_PARSER_ASSERT(ptr); + } else { + if (tag == 0 || (tag & 7) == 4) { + ctx->SetLastTag(tag); + return ptr; + } + ptr = ParseField(tag, ptr, extendee, metadata, ctx); + GOOGLE_PROTOBUF_PARSER_ASSERT(ptr); + } + } + return ptr; + } + + // Write all extension fields with field numbers in the range + // [start_field_number, end_field_number) + // to the output stream, using the cached sizes computed when ByteSize() was + // last called. Note that the range bounds are inclusive-exclusive. + void SerializeWithCachedSizes(const MessageLite* extendee, + int start_field_number, int end_field_number, + io::CodedOutputStream* output) const { + output->SetCur(_InternalSerialize(extendee, start_field_number, + end_field_number, output->Cur(), + output->EpsCopy())); + } + + // Same as SerializeWithCachedSizes, but without any bounds checking. + // The caller must ensure that target has sufficient capacity for the + // serialized extensions. + // + // Returns a pointer past the last written byte. + + uint8_t* _InternalSerialize(const MessageLite* extendee, + int start_field_number, int end_field_number, + uint8_t* target, + io::EpsCopyOutputStream* stream) const { + if (flat_size_ == 0) { + assert(!is_large()); + return target; + } + return _InternalSerializeImpl(extendee, start_field_number, + end_field_number, target, stream); + } + + // Like above but serializes in MessageSet format. + void SerializeMessageSetWithCachedSizes(const MessageLite* extendee, + io::CodedOutputStream* output) const { + output->SetCur(InternalSerializeMessageSetWithCachedSizesToArray( + extendee, output->Cur(), output->EpsCopy())); + } + uint8_t* InternalSerializeMessageSetWithCachedSizesToArray( + const MessageLite* extendee, uint8_t* target, + io::EpsCopyOutputStream* stream) const; + + // For backward-compatibility, versions of two of the above methods that + // serialize deterministically iff SetDefaultSerializationDeterministic() + // has been called. + uint8_t* SerializeWithCachedSizesToArray(int start_field_number, + int end_field_number, + uint8_t* target) const; + uint8_t* SerializeMessageSetWithCachedSizesToArray( + const MessageLite* extendee, uint8_t* target) const; + + // Returns the total serialized size of all the extensions. + size_t ByteSize() const; + + // Like ByteSize() but uses MessageSet format. + size_t MessageSetByteSize() const; + + // Returns (an estimate of) the total number of bytes used for storing the + // extensions in memory, excluding sizeof(*this). If the ExtensionSet is + // for a lite message (and thus possibly contains lite messages), the results + // are undefined (might work, might crash, might corrupt data, might not even + // be linked in). It's up to the protocol compiler to avoid calling this on + // such ExtensionSets (easy enough since lite messages don't implement + // SpaceUsed()). + size_t SpaceUsedExcludingSelfLong() const; + + // This method just calls SpaceUsedExcludingSelfLong() but it can not be + // inlined because the definition of SpaceUsedExcludingSelfLong() is not + // included in lite runtime and when an inline method refers to it MSVC + // will complain about unresolved symbols when building the lite runtime + // as .dll. + int SpaceUsedExcludingSelf() const; + + private: + template <typename Type> + friend class PrimitiveTypeTraits; + + template <typename Type> + friend class RepeatedPrimitiveTypeTraits; + + template <typename Type, bool IsValid(int)> + friend class EnumTypeTraits; + + template <typename Type, bool IsValid(int)> + friend class RepeatedEnumTypeTraits; + + friend class google::protobuf::Reflection; + + const int32_t& GetRefInt32(int number, const int32_t& default_value) const; + const int64_t& GetRefInt64(int number, const int64_t& default_value) const; + const uint32_t& GetRefUInt32(int number, const uint32_t& default_value) const; + const uint64_t& GetRefUInt64(int number, const uint64_t& default_value) const; + const float& GetRefFloat(int number, const float& default_value) const; + const double& GetRefDouble(int number, const double& default_value) const; + const bool& GetRefBool(int number, const bool& default_value) const; + const int& GetRefEnum(int number, const int& default_value) const; + const int32_t& GetRefRepeatedInt32(int number, int index) const; + const int64_t& GetRefRepeatedInt64(int number, int index) const; + const uint32_t& GetRefRepeatedUInt32(int number, int index) const; + const uint64_t& GetRefRepeatedUInt64(int number, int index) const; + const float& GetRefRepeatedFloat(int number, int index) const; + const double& GetRefRepeatedDouble(int number, int index) const; + const bool& GetRefRepeatedBool(int number, int index) const; + const int& GetRefRepeatedEnum(int number, int index) const; + + // Implementation of _InternalSerialize for non-empty map_. + uint8_t* _InternalSerializeImpl(const MessageLite* extendee, + int start_field_number, int end_field_number, + uint8_t* target, + io::EpsCopyOutputStream* stream) const; + // Interface of a lazily parsed singular message extension. + class PROTOBUF_EXPORT LazyMessageExtension { + public: + LazyMessageExtension() {} + virtual ~LazyMessageExtension() {} + + virtual LazyMessageExtension* New(Arena* arena) const = 0; + virtual const MessageLite& GetMessage(const MessageLite& prototype, + Arena* arena) const = 0; + virtual MessageLite* MutableMessage(const MessageLite& prototype, + Arena* arena) = 0; + virtual void SetAllocatedMessage(MessageLite* message, Arena* arena) = 0; + virtual void UnsafeArenaSetAllocatedMessage(MessageLite* message, + Arena* arena) = 0; + PROTOBUF_NODISCARD virtual MessageLite* ReleaseMessage( + const MessageLite& prototype, Arena* arena) = 0; + virtual MessageLite* UnsafeArenaReleaseMessage(const MessageLite& prototype, + Arena* arena) = 0; + + virtual bool IsInitialized() const = 0; + + PROTOBUF_DEPRECATED_MSG("Please use ByteSizeLong() instead") + virtual int ByteSize() const { return internal::ToIntSize(ByteSizeLong()); } + virtual size_t ByteSizeLong() const = 0; + virtual size_t SpaceUsedLong() const = 0; + + virtual void MergeFrom(const MessageLite* prototype, + const LazyMessageExtension& other, Arena* arena) = 0; + virtual void MergeFromMessage(const MessageLite& msg, Arena* arena) = 0; + virtual void Clear() = 0; + + virtual const char* _InternalParse(const Message& prototype, Arena* arena, + LazyVerifyOption option, const char* ptr, + ParseContext* ctx) = 0; + virtual uint8_t* WriteMessageToArray( + const MessageLite* prototype, int number, uint8_t* target, + io::EpsCopyOutputStream* stream) const = 0; + + private: + virtual void UnusedKeyMethod(); // Dummy key method to avoid weak vtable. + + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(LazyMessageExtension); + }; + // Give access to function defined below to see LazyMessageExtension. + friend LazyMessageExtension* MaybeCreateLazyExtension(Arena* arena); + struct Extension { + // The order of these fields packs Extension into 24 bytes when using 8 + // byte alignment. Consider this when adding or removing fields here. + union { + int32_t int32_t_value; + int64_t int64_t_value; + uint32_t uint32_t_value; + uint64_t uint64_t_value; + float float_value; + double double_value; + bool bool_value; + int enum_value; + std::string* string_value; + MessageLite* message_value; + LazyMessageExtension* lazymessage_value; + + RepeatedField<int32_t>* repeated_int32_t_value; + RepeatedField<int64_t>* repeated_int64_t_value; + RepeatedField<uint32_t>* repeated_uint32_t_value; + RepeatedField<uint64_t>* repeated_uint64_t_value; + RepeatedField<float>* repeated_float_value; + RepeatedField<double>* repeated_double_value; + RepeatedField<bool>* repeated_bool_value; + RepeatedField<int>* repeated_enum_value; + RepeatedPtrField<std::string>* repeated_string_value; + RepeatedPtrField<MessageLite>* repeated_message_value; + }; + + FieldType type; + bool is_repeated; + + // For singular types, indicates if the extension is "cleared". This + // happens when an extension is set and then later cleared by the caller. + // We want to keep the Extension object around for reuse, so instead of + // removing it from the map, we just set is_cleared = true. This has no + // meaning for repeated types; for those, the size of the RepeatedField + // simply becomes zero when cleared. + bool is_cleared : 4; + + // For singular message types, indicates whether lazy parsing is enabled + // for this extension. This field is only valid when type == TYPE_MESSAGE + // and !is_repeated because we only support lazy parsing for singular + // message types currently. If is_lazy = true, the extension is stored in + // lazymessage_value. Otherwise, the extension will be message_value. + bool is_lazy : 4; + + // For repeated types, this indicates if the [packed=true] option is set. + bool is_packed; + + // For packed fields, the size of the packed data is recorded here when + // ByteSize() is called then used during serialization. + // TODO(kenton): Use atomic<int> when C++ supports it. + mutable int cached_size; + + // The descriptor for this extension, if one exists and is known. May be + // nullptr. Must not be nullptr if the descriptor for the extension does + // not live in the same pool as the descriptor for the containing type. + const FieldDescriptor* descriptor; + + // Some helper methods for operations on a single Extension. + uint8_t* InternalSerializeFieldWithCachedSizesToArray( + const MessageLite* extendee, const ExtensionSet* extension_set, + int number, uint8_t* target, io::EpsCopyOutputStream* stream) const; + uint8_t* InternalSerializeMessageSetItemWithCachedSizesToArray( + const MessageLite* extendee, const ExtensionSet* extension_set, + int number, uint8_t* target, io::EpsCopyOutputStream* stream) const; + size_t ByteSize(int number) const; + size_t MessageSetItemByteSize(int number) const; + void Clear(); + int GetSize() const; + void Free(); + size_t SpaceUsedExcludingSelfLong() const; + bool IsInitialized() const; + }; + + // The Extension struct is small enough to be passed by value, so we use it + // directly as the value type in mappings rather than use pointers. We use + // sorted maps rather than hash-maps because we expect most ExtensionSets will + // only contain a small number of extension. Also, we want AppendToList and + // deterministic serialization to order fields by field number. + + struct KeyValue { + int first; + Extension second; + + struct FirstComparator { + bool operator()(const KeyValue& lhs, const KeyValue& rhs) const { + return lhs.first < rhs.first; + } + bool operator()(const KeyValue& lhs, int key) const { + return lhs.first < key; + } + bool operator()(int key, const KeyValue& rhs) const { + return key < rhs.first; + } + }; + }; + + typedef std::map<int, Extension> LargeMap; + + // Wrapper API that switches between flat-map and LargeMap. + + // Finds a key (if present) in the ExtensionSet. + const Extension* FindOrNull(int key) const; + Extension* FindOrNull(int key); + + // Helper-functions that only inspect the LargeMap. + const Extension* FindOrNullInLargeMap(int key) const; + Extension* FindOrNullInLargeMap(int key); + + // Inserts a new (key, Extension) into the ExtensionSet (and returns true), or + // finds the already-existing Extension for that key (returns false). + // The Extension* will point to the new-or-found Extension. + std::pair<Extension*, bool> Insert(int key); + + // Grows the flat_capacity_. + // If flat_capacity_ > kMaximumFlatCapacity, converts to LargeMap. + void GrowCapacity(size_t minimum_new_capacity); + static constexpr uint16_t kMaximumFlatCapacity = 256; + bool is_large() const { return static_cast<int16_t>(flat_size_) < 0; } + + // Removes a key from the ExtensionSet. + void Erase(int key); + + size_t Size() const { + return PROTOBUF_PREDICT_FALSE(is_large()) ? map_.large->size() : flat_size_; + } + + // Similar to std::for_each. + // Each Iterator is decomposed into ->first and ->second fields, so + // that the KeyValueFunctor can be agnostic vis-a-vis KeyValue-vs-std::pair. + template <typename Iterator, typename KeyValueFunctor> + static KeyValueFunctor ForEach(Iterator begin, Iterator end, + KeyValueFunctor func) { + for (Iterator it = begin; it != end; ++it) func(it->first, it->second); + return std::move(func); + } + + // Applies a functor to the <int, Extension&> pairs in sorted order. + template <typename KeyValueFunctor> + KeyValueFunctor ForEach(KeyValueFunctor func) { + if (PROTOBUF_PREDICT_FALSE(is_large())) { + return ForEach(map_.large->begin(), map_.large->end(), std::move(func)); + } + return ForEach(flat_begin(), flat_end(), std::move(func)); + } + + // Applies a functor to the <int, const Extension&> pairs in sorted order. + template <typename KeyValueFunctor> + KeyValueFunctor ForEach(KeyValueFunctor func) const { + if (PROTOBUF_PREDICT_FALSE(is_large())) { + return ForEach(map_.large->begin(), map_.large->end(), std::move(func)); + } + return ForEach(flat_begin(), flat_end(), std::move(func)); + } + + // Merges existing Extension from other_extension + void InternalExtensionMergeFrom(const MessageLite* extendee, int number, + const Extension& other_extension, + Arena* other_arena); + + inline static bool is_packable(WireFormatLite::WireType type) { + switch (type) { + case WireFormatLite::WIRETYPE_VARINT: + case WireFormatLite::WIRETYPE_FIXED64: + case WireFormatLite::WIRETYPE_FIXED32: + return true; + case WireFormatLite::WIRETYPE_LENGTH_DELIMITED: + case WireFormatLite::WIRETYPE_START_GROUP: + case WireFormatLite::WIRETYPE_END_GROUP: + return false; + + // Do not add a default statement. Let the compiler complain when + // someone + // adds a new wire type. + } + PROTOBUF_ASSUME(false); // switch handles all possible enum values + return false; + } + + // Returns true and fills field_number and extension if extension is found. + // Note to support packed repeated field compatibility, it also fills whether + // the tag on wire is packed, which can be different from + // extension->is_packed (whether packed=true is specified). + template <typename ExtensionFinder> + bool FindExtensionInfoFromTag(uint32_t tag, ExtensionFinder* extension_finder, + int* field_number, ExtensionInfo* extension, + bool* was_packed_on_wire) { + *field_number = WireFormatLite::GetTagFieldNumber(tag); + WireFormatLite::WireType wire_type = WireFormatLite::GetTagWireType(tag); + return FindExtensionInfoFromFieldNumber(wire_type, *field_number, + extension_finder, extension, + was_packed_on_wire); + } + + // Returns true and fills extension if extension is found. + // Note to support packed repeated field compatibility, it also fills whether + // the tag on wire is packed, which can be different from + // extension->is_packed (whether packed=true is specified). + template <typename ExtensionFinder> + bool FindExtensionInfoFromFieldNumber(int wire_type, int field_number, + ExtensionFinder* extension_finder, + ExtensionInfo* extension, + bool* was_packed_on_wire) const { + if (!extension_finder->Find(field_number, extension)) { + return false; + } + + GOOGLE_DCHECK(extension->type > 0 && + extension->type <= WireFormatLite::MAX_FIELD_TYPE); + auto real_type = static_cast<WireFormatLite::FieldType>(extension->type); + + WireFormatLite::WireType expected_wire_type = + WireFormatLite::WireTypeForFieldType(real_type); + + // Check if this is a packed field. + *was_packed_on_wire = false; + if (extension->is_repeated && + wire_type == WireFormatLite::WIRETYPE_LENGTH_DELIMITED && + is_packable(expected_wire_type)) { + *was_packed_on_wire = true; + return true; + } + // Otherwise the wire type must match. + return expected_wire_type == wire_type; + } + + // Find the prototype for a LazyMessage from the extension registry. Returns + // null if the extension is not found. + const MessageLite* GetPrototypeForLazyMessage(const MessageLite* extendee, + int number) const; + + // Returns true if extension is present and lazy. + bool HasLazy(int number) const; + + // Gets the extension with the given number, creating it if it does not + // already exist. Returns true if the extension did not already exist. + bool MaybeNewExtension(int number, const FieldDescriptor* descriptor, + Extension** result); + + // Gets the repeated extension for the given descriptor, creating it if + // it does not exist. + Extension* MaybeNewRepeatedExtension(const FieldDescriptor* descriptor); + + bool FindExtension(int wire_type, uint32_t field, const MessageLite* extendee, + const internal::ParseContext* /*ctx*/, + ExtensionInfo* extension, bool* was_packed_on_wire) { + GeneratedExtensionFinder finder(extendee); + return FindExtensionInfoFromFieldNumber(wire_type, field, &finder, + extension, was_packed_on_wire); + } + inline bool FindExtension(int wire_type, uint32_t field, + const Message* extendee, + const internal::ParseContext* ctx, + ExtensionInfo* extension, bool* was_packed_on_wire); + // Used for MessageSet only + const char* ParseFieldMaybeLazily(uint64_t tag, const char* ptr, + const MessageLite* extendee, + internal::InternalMetadata* metadata, + internal::ParseContext* ctx) { + // Lite MessageSet doesn't implement lazy. + return ParseField(tag, ptr, extendee, metadata, ctx); + } + const char* ParseFieldMaybeLazily(uint64_t tag, const char* ptr, + const Message* extendee, + internal::InternalMetadata* metadata, + internal::ParseContext* ctx); + const char* ParseMessageSetItem(const char* ptr, const MessageLite* extendee, + internal::InternalMetadata* metadata, + internal::ParseContext* ctx); + const char* ParseMessageSetItem(const char* ptr, const Message* extendee, + internal::InternalMetadata* metadata, + internal::ParseContext* ctx); + + // Implemented in extension_set_inl.h to keep code out of the header file. + template <typename T> + const char* ParseFieldWithExtensionInfo(int number, bool was_packed_on_wire, + const ExtensionInfo& info, + internal::InternalMetadata* metadata, + const char* ptr, + internal::ParseContext* ctx); + template <typename Msg, typename T> + const char* ParseMessageSetItemTmpl(const char* ptr, const Msg* extendee, + internal::InternalMetadata* metadata, + internal::ParseContext* ctx); + + // Hack: RepeatedPtrFieldBase declares ExtensionSet as a friend. This + // friendship should automatically extend to ExtensionSet::Extension, but + // unfortunately some older compilers (e.g. GCC 3.4.4) do not implement this + // correctly. So, we must provide helpers for calling methods of that + // class. + + // Defined in extension_set_heavy.cc. + static inline size_t RepeatedMessage_SpaceUsedExcludingSelfLong( + RepeatedPtrFieldBase* field); + + KeyValue* flat_begin() { + assert(!is_large()); + return map_.flat; + } + const KeyValue* flat_begin() const { + assert(!is_large()); + return map_.flat; + } + KeyValue* flat_end() { + assert(!is_large()); + return map_.flat + flat_size_; + } + const KeyValue* flat_end() const { + assert(!is_large()); + return map_.flat + flat_size_; + } + + Arena* arena_; + + // Manual memory-management: + // map_.flat is an allocated array of flat_capacity_ elements. + // [map_.flat, map_.flat + flat_size_) is the currently-in-use prefix. + uint16_t flat_capacity_; + uint16_t flat_size_; // negative int16_t(flat_size_) indicates is_large() + union AllocatedData { + KeyValue* flat; + + // If flat_capacity_ > kMaximumFlatCapacity, switch to LargeMap, + // which guarantees O(n lg n) CPU but larger constant factors. + LargeMap* large; + } map_; + + static void DeleteFlatMap(const KeyValue* flat, uint16_t flat_capacity); + + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ExtensionSet); +}; + +constexpr ExtensionSet::ExtensionSet() + : arena_(nullptr), flat_capacity_(0), flat_size_(0), map_{nullptr} {} + +// These are just for convenience... +inline void ExtensionSet::SetString(int number, FieldType type, + std::string value, + const FieldDescriptor* descriptor) { + MutableString(number, type, descriptor)->assign(std::move(value)); +} +inline void ExtensionSet::SetRepeatedString(int number, int index, + std::string value) { + MutableRepeatedString(number, index)->assign(std::move(value)); +} +inline void ExtensionSet::AddString(int number, FieldType type, + std::string value, + const FieldDescriptor* descriptor) { + AddString(number, type, descriptor)->assign(std::move(value)); +} +// =================================================================== +// Glue for generated extension accessors + +// ------------------------------------------------------------------- +// Template magic + +// First we have a set of classes representing "type traits" for different +// field types. A type traits class knows how to implement basic accessors +// for extensions of a particular type given an ExtensionSet. The signature +// for a type traits class looks like this: +// +// class TypeTraits { +// public: +// typedef ? ConstType; +// typedef ? MutableType; +// // TypeTraits for singular fields and repeated fields will define the +// // symbol "Singular" or "Repeated" respectively. These two symbols will +// // be used in extension accessors to distinguish between singular +// // extensions and repeated extensions. If the TypeTraits for the passed +// // in extension doesn't have the expected symbol defined, it means the +// // user is passing a repeated extension to a singular accessor, or the +// // opposite. In that case the C++ compiler will generate an error +// // message "no matching member function" to inform the user. +// typedef ? Singular +// typedef ? Repeated +// +// static inline ConstType Get(int number, const ExtensionSet& set); +// static inline void Set(int number, ConstType value, ExtensionSet* set); +// static inline MutableType Mutable(int number, ExtensionSet* set); +// +// // Variants for repeated fields. +// static inline ConstType Get(int number, const ExtensionSet& set, +// int index); +// static inline void Set(int number, int index, +// ConstType value, ExtensionSet* set); +// static inline MutableType Mutable(int number, int index, +// ExtensionSet* set); +// static inline void Add(int number, ConstType value, ExtensionSet* set); +// static inline MutableType Add(int number, ExtensionSet* set); +// This is used by the ExtensionIdentifier constructor to register +// the extension at dynamic initialization. +// template <typename ExtendeeT> +// static void Register(int number, FieldType type, bool is_packed); +// }; +// +// Not all of these methods make sense for all field types. For example, the +// "Mutable" methods only make sense for strings and messages, and the +// repeated methods only make sense for repeated types. So, each type +// traits class implements only the set of methods from this signature that it +// actually supports. This will cause a compiler error if the user tries to +// access an extension using a method that doesn't make sense for its type. +// For example, if "foo" is an extension of type "optional int32", then if you +// try to write code like: +// my_message.MutableExtension(foo) +// you will get a compile error because PrimitiveTypeTraits<int32_t> does not +// have a "Mutable()" method. + +// ------------------------------------------------------------------- +// PrimitiveTypeTraits + +// Since the ExtensionSet has different methods for each primitive type, +// we must explicitly define the methods of the type traits class for each +// known type. +template <typename Type> +class PrimitiveTypeTraits { + public: + typedef Type ConstType; + typedef Type MutableType; + typedef PrimitiveTypeTraits<Type> Singular; + + static inline ConstType Get(int number, const ExtensionSet& set, + ConstType default_value); + + static inline const ConstType* GetPtr(int number, const ExtensionSet& set, + const ConstType& default_value); + static inline void Set(int number, FieldType field_type, ConstType value, + ExtensionSet* set); + template <typename ExtendeeT> + static void Register(int number, FieldType type, bool is_packed, + LazyEagerVerifyFnType verify_func) { + ExtensionSet::RegisterExtension(&ExtendeeT::default_instance(), number, + type, false, is_packed, verify_func); + } +}; + +template <typename Type> +class RepeatedPrimitiveTypeTraits { + public: + typedef Type ConstType; + typedef Type MutableType; + typedef RepeatedPrimitiveTypeTraits<Type> Repeated; + + typedef RepeatedField<Type> RepeatedFieldType; + + static inline Type Get(int number, const ExtensionSet& set, int index); + static inline const Type* GetPtr(int number, const ExtensionSet& set, + int index); + static inline const RepeatedField<ConstType>* GetRepeatedPtr( + int number, const ExtensionSet& set); + static inline void Set(int number, int index, Type value, ExtensionSet* set); + static inline void Add(int number, FieldType field_type, bool is_packed, + Type value, ExtensionSet* set); + + static inline const RepeatedField<ConstType>& GetRepeated( + int number, const ExtensionSet& set); + static inline RepeatedField<Type>* MutableRepeated(int number, + FieldType field_type, + bool is_packed, + ExtensionSet* set); + + static const RepeatedFieldType* GetDefaultRepeatedField(); + template <typename ExtendeeT> + static void Register(int number, FieldType type, bool is_packed, + LazyEagerVerifyFnType verify_func) { + ExtensionSet::RegisterExtension(&ExtendeeT::default_instance(), number, + type, true, is_packed, verify_func); + } +}; + +class PROTOBUF_EXPORT RepeatedPrimitiveDefaults { + private: + template <typename Type> + friend class RepeatedPrimitiveTypeTraits; + static const RepeatedPrimitiveDefaults* default_instance(); + RepeatedField<int32_t> default_repeated_field_int32_t_; + RepeatedField<int64_t> default_repeated_field_int64_t_; + RepeatedField<uint32_t> default_repeated_field_uint32_t_; + RepeatedField<uint64_t> default_repeated_field_uint64_t_; + RepeatedField<double> default_repeated_field_double_; + RepeatedField<float> default_repeated_field_float_; + RepeatedField<bool> default_repeated_field_bool_; +}; + +#define PROTOBUF_DEFINE_PRIMITIVE_TYPE(TYPE, METHOD) \ + template <> \ + inline TYPE PrimitiveTypeTraits<TYPE>::Get( \ + int number, const ExtensionSet& set, TYPE default_value) { \ + return set.Get##METHOD(number, default_value); \ + } \ + template <> \ + inline const TYPE* PrimitiveTypeTraits<TYPE>::GetPtr( \ + int number, const ExtensionSet& set, const TYPE& default_value) { \ + return &set.GetRef##METHOD(number, default_value); \ + } \ + template <> \ + inline void PrimitiveTypeTraits<TYPE>::Set(int number, FieldType field_type, \ + TYPE value, ExtensionSet* set) { \ + set->Set##METHOD(number, field_type, value, nullptr); \ + } \ + \ + template <> \ + inline TYPE RepeatedPrimitiveTypeTraits<TYPE>::Get( \ + int number, const ExtensionSet& set, int index) { \ + return set.GetRepeated##METHOD(number, index); \ + } \ + template <> \ + inline const TYPE* RepeatedPrimitiveTypeTraits<TYPE>::GetPtr( \ + int number, const ExtensionSet& set, int index) { \ + return &set.GetRefRepeated##METHOD(number, index); \ + } \ + template <> \ + inline void RepeatedPrimitiveTypeTraits<TYPE>::Set( \ + int number, int index, TYPE value, ExtensionSet* set) { \ + set->SetRepeated##METHOD(number, index, value); \ + } \ + template <> \ + inline void RepeatedPrimitiveTypeTraits<TYPE>::Add( \ + int number, FieldType field_type, bool is_packed, TYPE value, \ + ExtensionSet* set) { \ + set->Add##METHOD(number, field_type, is_packed, value, nullptr); \ + } \ + template <> \ + inline const RepeatedField<TYPE>* \ + RepeatedPrimitiveTypeTraits<TYPE>::GetDefaultRepeatedField() { \ + return &RepeatedPrimitiveDefaults::default_instance() \ + ->default_repeated_field_##TYPE##_; \ + } \ + template <> \ + inline const RepeatedField<TYPE>& \ + RepeatedPrimitiveTypeTraits<TYPE>::GetRepeated(int number, \ + const ExtensionSet& set) { \ + return *reinterpret_cast<const RepeatedField<TYPE>*>( \ + set.GetRawRepeatedField(number, GetDefaultRepeatedField())); \ + } \ + template <> \ + inline const RepeatedField<TYPE>* \ + RepeatedPrimitiveTypeTraits<TYPE>::GetRepeatedPtr(int number, \ + const ExtensionSet& set) { \ + return &GetRepeated(number, set); \ + } \ + template <> \ + inline RepeatedField<TYPE>* \ + RepeatedPrimitiveTypeTraits<TYPE>::MutableRepeated( \ + int number, FieldType field_type, bool is_packed, ExtensionSet* set) { \ + return reinterpret_cast<RepeatedField<TYPE>*>( \ + set->MutableRawRepeatedField(number, field_type, is_packed, nullptr)); \ + } + +PROTOBUF_DEFINE_PRIMITIVE_TYPE(int32_t, Int32) +PROTOBUF_DEFINE_PRIMITIVE_TYPE(int64_t, Int64) +PROTOBUF_DEFINE_PRIMITIVE_TYPE(uint32_t, UInt32) +PROTOBUF_DEFINE_PRIMITIVE_TYPE(uint64_t, UInt64) +PROTOBUF_DEFINE_PRIMITIVE_TYPE(float, Float) +PROTOBUF_DEFINE_PRIMITIVE_TYPE(double, Double) +PROTOBUF_DEFINE_PRIMITIVE_TYPE(bool, Bool) + +#undef PROTOBUF_DEFINE_PRIMITIVE_TYPE + +// ------------------------------------------------------------------- +// StringTypeTraits + +// Strings support both Set() and Mutable(). +class PROTOBUF_EXPORT StringTypeTraits { + public: + typedef const std::string& ConstType; + typedef std::string* MutableType; + typedef StringTypeTraits Singular; + + static inline const std::string& Get(int number, const ExtensionSet& set, + ConstType default_value) { + return set.GetString(number, default_value); + } + static inline const std::string* GetPtr(int number, const ExtensionSet& set, + ConstType default_value) { + return &Get(number, set, default_value); + } + static inline void Set(int number, FieldType field_type, + const std::string& value, ExtensionSet* set) { + set->SetString(number, field_type, value, nullptr); + } + static inline std::string* Mutable(int number, FieldType field_type, + ExtensionSet* set) { + return set->MutableString(number, field_type, nullptr); + } + template <typename ExtendeeT> + static void Register(int number, FieldType type, bool is_packed, + LazyEagerVerifyFnType verify_func) { + ExtensionSet::RegisterExtension(&ExtendeeT::default_instance(), number, + type, false, is_packed, verify_func); + } +}; + +class PROTOBUF_EXPORT RepeatedStringTypeTraits { + public: + typedef const std::string& ConstType; + typedef std::string* MutableType; + typedef RepeatedStringTypeTraits Repeated; + + typedef RepeatedPtrField<std::string> RepeatedFieldType; + + static inline const std::string& Get(int number, const ExtensionSet& set, + int index) { + return set.GetRepeatedString(number, index); + } + static inline const std::string* GetPtr(int number, const ExtensionSet& set, + int index) { + return &Get(number, set, index); + } + static inline const RepeatedPtrField<std::string>* GetRepeatedPtr( + int number, const ExtensionSet& set) { + return &GetRepeated(number, set); + } + static inline void Set(int number, int index, const std::string& value, + ExtensionSet* set) { + set->SetRepeatedString(number, index, value); + } + static inline std::string* Mutable(int number, int index, ExtensionSet* set) { + return set->MutableRepeatedString(number, index); + } + static inline void Add(int number, FieldType field_type, bool /*is_packed*/, + const std::string& value, ExtensionSet* set) { + set->AddString(number, field_type, value, nullptr); + } + static inline std::string* Add(int number, FieldType field_type, + ExtensionSet* set) { + return set->AddString(number, field_type, nullptr); + } + static inline const RepeatedPtrField<std::string>& GetRepeated( + int number, const ExtensionSet& set) { + return *reinterpret_cast<const RepeatedPtrField<std::string>*>( + set.GetRawRepeatedField(number, GetDefaultRepeatedField())); + } + + static inline RepeatedPtrField<std::string>* MutableRepeated( + int number, FieldType field_type, bool is_packed, ExtensionSet* set) { + return reinterpret_cast<RepeatedPtrField<std::string>*>( + set->MutableRawRepeatedField(number, field_type, is_packed, nullptr)); + } + + static const RepeatedFieldType* GetDefaultRepeatedField(); + + template <typename ExtendeeT> + static void Register(int number, FieldType type, bool is_packed, + LazyEagerVerifyFnType fn) { + ExtensionSet::RegisterExtension(&ExtendeeT::default_instance(), number, + type, true, is_packed, fn); + } + + private: + static void InitializeDefaultRepeatedFields(); + static void DestroyDefaultRepeatedFields(); +}; + +// ------------------------------------------------------------------- +// EnumTypeTraits + +// ExtensionSet represents enums using integers internally, so we have to +// static_cast around. +template <typename Type, bool IsValid(int)> +class EnumTypeTraits { + public: + typedef Type ConstType; + typedef Type MutableType; + typedef EnumTypeTraits<Type, IsValid> Singular; + + static inline ConstType Get(int number, const ExtensionSet& set, + ConstType default_value) { + return static_cast<Type>(set.GetEnum(number, default_value)); + } + static inline const ConstType* GetPtr(int number, const ExtensionSet& set, + const ConstType& default_value) { + return reinterpret_cast<const Type*>( + &set.GetRefEnum(number, default_value)); + } + static inline void Set(int number, FieldType field_type, ConstType value, + ExtensionSet* set) { + GOOGLE_DCHECK(IsValid(value)); + set->SetEnum(number, field_type, value, nullptr); + } + template <typename ExtendeeT> + static void Register(int number, FieldType type, bool is_packed, + LazyEagerVerifyFnType fn) { + ExtensionSet::RegisterEnumExtension(&ExtendeeT::default_instance(), number, + type, false, is_packed, IsValid); + } +}; + +template <typename Type, bool IsValid(int)> +class RepeatedEnumTypeTraits { + public: + typedef Type ConstType; + typedef Type MutableType; + typedef RepeatedEnumTypeTraits<Type, IsValid> Repeated; + + typedef RepeatedField<Type> RepeatedFieldType; + + static inline ConstType Get(int number, const ExtensionSet& set, int index) { + return static_cast<Type>(set.GetRepeatedEnum(number, index)); + } + static inline const ConstType* GetPtr(int number, const ExtensionSet& set, + int index) { + return reinterpret_cast<const Type*>( + &set.GetRefRepeatedEnum(number, index)); + } + static inline void Set(int number, int index, ConstType value, + ExtensionSet* set) { + GOOGLE_DCHECK(IsValid(value)); + set->SetRepeatedEnum(number, index, value); + } + static inline void Add(int number, FieldType field_type, bool is_packed, + ConstType value, ExtensionSet* set) { + GOOGLE_DCHECK(IsValid(value)); + set->AddEnum(number, field_type, is_packed, value, nullptr); + } + static inline const RepeatedField<Type>& GetRepeated( + int number, const ExtensionSet& set) { + // Hack: the `Extension` struct stores a RepeatedField<int> for enums. + // RepeatedField<int> cannot implicitly convert to RepeatedField<EnumType> + // so we need to do some casting magic. See message.h for similar + // contortions for non-extension fields. + return *reinterpret_cast<const RepeatedField<Type>*>( + set.GetRawRepeatedField(number, GetDefaultRepeatedField())); + } + static inline const RepeatedField<Type>* GetRepeatedPtr( + int number, const ExtensionSet& set) { + return &GetRepeated(number, set); + } + static inline RepeatedField<Type>* MutableRepeated(int number, + FieldType field_type, + bool is_packed, + ExtensionSet* set) { + return reinterpret_cast<RepeatedField<Type>*>( + set->MutableRawRepeatedField(number, field_type, is_packed, nullptr)); + } + + static const RepeatedFieldType* GetDefaultRepeatedField() { + // Hack: as noted above, repeated enum fields are internally stored as a + // RepeatedField<int>. We need to be able to instantiate global static + // objects to return as default (empty) repeated fields on non-existent + // extensions. We would not be able to know a-priori all of the enum types + // (values of |Type|) to instantiate all of these, so we just re-use + // int32_t's default repeated field object. + return reinterpret_cast<const RepeatedField<Type>*>( + RepeatedPrimitiveTypeTraits<int32_t>::GetDefaultRepeatedField()); + } + template <typename ExtendeeT> + static void Register(int number, FieldType type, bool is_packed, + LazyEagerVerifyFnType fn) { + ExtensionSet::RegisterEnumExtension(&ExtendeeT::default_instance(), number, + type, true, is_packed, IsValid); + } +}; + +// ------------------------------------------------------------------- +// MessageTypeTraits + +// ExtensionSet guarantees that when manipulating extensions with message +// types, the implementation used will be the compiled-in class representing +// that type. So, we can static_cast down to the exact type we expect. +template <typename Type> +class MessageTypeTraits { + public: + typedef const Type& ConstType; + typedef Type* MutableType; + typedef MessageTypeTraits<Type> Singular; + + static inline ConstType Get(int number, const ExtensionSet& set, + ConstType default_value) { + return static_cast<const Type&>(set.GetMessage(number, default_value)); + } + static inline std::nullptr_t GetPtr(int /* number */, + const ExtensionSet& /* set */, + ConstType /* default_value */) { + // Cannot be implemented because of forward declared messages? + return nullptr; + } + static inline MutableType Mutable(int number, FieldType field_type, + ExtensionSet* set) { + return static_cast<Type*>(set->MutableMessage( + number, field_type, Type::default_instance(), nullptr)); + } + static inline void SetAllocated(int number, FieldType field_type, + MutableType message, ExtensionSet* set) { + set->SetAllocatedMessage(number, field_type, nullptr, message); + } + static inline void UnsafeArenaSetAllocated(int number, FieldType field_type, + MutableType message, + ExtensionSet* set) { + set->UnsafeArenaSetAllocatedMessage(number, field_type, nullptr, message); + } + PROTOBUF_NODISCARD static inline MutableType Release( + int number, FieldType /* field_type */, ExtensionSet* set) { + return static_cast<Type*>( + set->ReleaseMessage(number, Type::default_instance())); + } + static inline MutableType UnsafeArenaRelease(int number, + FieldType /* field_type */, + ExtensionSet* set) { + return static_cast<Type*>( + set->UnsafeArenaReleaseMessage(number, Type::default_instance())); + } + template <typename ExtendeeT> + static void Register(int number, FieldType type, bool is_packed, + LazyEagerVerifyFnType fn) { + ExtensionSet::RegisterMessageExtension(&ExtendeeT::default_instance(), + number, type, false, is_packed, + &Type::default_instance(), fn); + } +}; + +// Used by WireFormatVerify to extract the verify function from the registry. +LazyEagerVerifyFnType FindExtensionLazyEagerVerifyFn( + const MessageLite* extendee, int number); + +// forward declaration. +class RepeatedMessageGenericTypeTraits; + +template <typename Type> +class RepeatedMessageTypeTraits { + public: + typedef const Type& ConstType; + typedef Type* MutableType; + typedef RepeatedMessageTypeTraits<Type> Repeated; + + typedef RepeatedPtrField<Type> RepeatedFieldType; + + static inline ConstType Get(int number, const ExtensionSet& set, int index) { + return static_cast<const Type&>(set.GetRepeatedMessage(number, index)); + } + static inline std::nullptr_t GetPtr(int /* number */, + const ExtensionSet& /* set */, + int /* index */) { + // Cannot be implemented because of forward declared messages? + return nullptr; + } + static inline std::nullptr_t GetRepeatedPtr(int /* number */, + const ExtensionSet& /* set */) { + // Cannot be implemented because of forward declared messages? + return nullptr; + } + static inline MutableType Mutable(int number, int index, ExtensionSet* set) { + return static_cast<Type*>(set->MutableRepeatedMessage(number, index)); + } + static inline MutableType Add(int number, FieldType field_type, + ExtensionSet* set) { + return static_cast<Type*>( + set->AddMessage(number, field_type, Type::default_instance(), nullptr)); + } + static inline const RepeatedPtrField<Type>& GetRepeated( + int number, const ExtensionSet& set) { + // See notes above in RepeatedEnumTypeTraits::GetRepeated(): same + // casting hack applies here, because a RepeatedPtrField<MessageLite> + // cannot naturally become a RepeatedPtrType<Type> even though Type is + // presumably a message. google::protobuf::Message goes through similar contortions + // with a reinterpret_cast<>. + return *reinterpret_cast<const RepeatedPtrField<Type>*>( + set.GetRawRepeatedField(number, GetDefaultRepeatedField())); + } + static inline RepeatedPtrField<Type>* MutableRepeated(int number, + FieldType field_type, + bool is_packed, + ExtensionSet* set) { + return reinterpret_cast<RepeatedPtrField<Type>*>( + set->MutableRawRepeatedField(number, field_type, is_packed, nullptr)); + } + + static const RepeatedFieldType* GetDefaultRepeatedField(); + template <typename ExtendeeT> + static void Register(int number, FieldType type, bool is_packed, + LazyEagerVerifyFnType fn) { + ExtensionSet::RegisterMessageExtension(&ExtendeeT::default_instance(), + number, type, true, is_packed, + &Type::default_instance(), fn); + } +}; + +template <typename Type> +inline const typename RepeatedMessageTypeTraits<Type>::RepeatedFieldType* +RepeatedMessageTypeTraits<Type>::GetDefaultRepeatedField() { + static auto instance = OnShutdownDelete(new RepeatedFieldType); + return instance; +} + +// ------------------------------------------------------------------- +// ExtensionIdentifier + +// This is the type of actual extension objects. E.g. if you have: +// extend Foo { +// optional int32 bar = 1234; +// } +// then "bar" will be defined in C++ as: +// ExtensionIdentifier<Foo, PrimitiveTypeTraits<int32_t>, 5, false> bar(1234); +// +// Note that we could, in theory, supply the field number as a template +// parameter, and thus make an instance of ExtensionIdentifier have no +// actual contents. However, if we did that, then using an extension +// identifier would not necessarily cause the compiler to output any sort +// of reference to any symbol defined in the extension's .pb.o file. Some +// linkers will actually drop object files that are not explicitly referenced, +// but that would be bad because it would cause this extension to not be +// registered at static initialization, and therefore using it would crash. + +template <typename ExtendeeType, typename TypeTraitsType, FieldType field_type, + bool is_packed> +class ExtensionIdentifier { + public: + typedef TypeTraitsType TypeTraits; + typedef ExtendeeType Extendee; + + ExtensionIdentifier(int number, typename TypeTraits::ConstType default_value, + LazyEagerVerifyFnType verify_func = nullptr) + : number_(number), default_value_(default_value) { + Register(number, verify_func); + } + inline int number() const { return number_; } + typename TypeTraits::ConstType default_value() const { + return default_value_; + } + + static void Register(int number, LazyEagerVerifyFnType verify_func) { + TypeTraits::template Register<ExtendeeType>(number, field_type, is_packed, + verify_func); + } + + typename TypeTraits::ConstType const& default_value_ref() const { + return default_value_; + } + + private: + const int number_; + typename TypeTraits::ConstType default_value_; +}; + +// ------------------------------------------------------------------- +// Generated accessors + + +// Used to retrieve a lazy extension, may return nullptr in some environments. +extern PROTOBUF_ATTRIBUTE_WEAK ExtensionSet::LazyMessageExtension* +MaybeCreateLazyExtension(Arena* arena); + +} // namespace internal + +// Call this function to ensure that this extensions's reflection is linked into +// the binary: +// +// google::protobuf::LinkExtensionReflection(Foo::my_extension); +// +// This will ensure that the following lookup will succeed: +// +// DescriptorPool::generated_pool()->FindExtensionByName("Foo.my_extension"); +// +// This is often relevant for parsing extensions in text mode. +// +// As a side-effect, it will also guarantee that anything else from the same +// .proto file will also be available for lookup in the generated pool. +// +// This function does not actually register the extension, so it does not need +// to be called before the lookup. However it does need to occur in a function +// that cannot be stripped from the binary (ie. it must be reachable from main). +// +// Best practice is to call this function as close as possible to where the +// reflection is actually needed. This function is very cheap to call, so you +// should not need to worry about its runtime overhead except in tight loops (on +// x86-64 it compiles into two "mov" instructions). +template <typename ExtendeeType, typename TypeTraitsType, + internal::FieldType field_type, bool is_packed> +void LinkExtensionReflection( + const google::protobuf::internal::ExtensionIdentifier< + ExtendeeType, TypeTraitsType, field_type, is_packed>& extension) { + internal::StrongReference(extension); +} + +} // namespace protobuf +} // namespace google + +#include <google/protobuf/port_undef.inc> + +#endif // GOOGLE_PROTOBUF_EXTENSION_SET_H__ diff --git a/toolkit/components/protobuf/src/google/protobuf/extension_set_heavy.cc b/toolkit/components/protobuf/src/google/protobuf/extension_set_heavy.cc new file mode 100644 index 0000000000..a4bb94860c --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/extension_set_heavy.cc @@ -0,0 +1,440 @@ +// 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. + +// Author: kenton@google.com (Kenton Varda) +// Based on original Protocol Buffers design by +// Sanjay Ghemawat, Jeff Dean, and others. +// +// Contains methods defined in extension_set.h which cannot be part of the +// lite library because they use descriptors or reflection. + +#include <google/protobuf/stubs/casts.h> +#include <google/protobuf/io/coded_stream.h> +#include <google/protobuf/arena.h> +#include <google/protobuf/descriptor.h> +#include <google/protobuf/descriptor.pb.h> +#include <google/protobuf/extension_set.h> +#include <google/protobuf/extension_set_inl.h> +#include <google/protobuf/message.h> +#include <google/protobuf/message_lite.h> +#include <google/protobuf/parse_context.h> +#include <google/protobuf/repeated_field.h> +#include <google/protobuf/unknown_field_set.h> +#include <google/protobuf/wire_format.h> +#include <google/protobuf/wire_format_lite.h> + + +// Must be included last. +#include <google/protobuf/port_def.inc> + +namespace google { +namespace protobuf { +namespace internal { + +// Implementation of ExtensionFinder which finds extensions in a given +// DescriptorPool, using the given MessageFactory to construct sub-objects. +// This class is implemented in extension_set_heavy.cc. +class DescriptorPoolExtensionFinder { + public: + DescriptorPoolExtensionFinder(const DescriptorPool* pool, + MessageFactory* factory, + const Descriptor* containing_type) + : pool_(pool), factory_(factory), containing_type_(containing_type) {} + + bool Find(int number, ExtensionInfo* output); + + private: + const DescriptorPool* pool_; + MessageFactory* factory_; + const Descriptor* containing_type_; +}; + +void ExtensionSet::AppendToList( + const Descriptor* containing_type, const DescriptorPool* pool, + std::vector<const FieldDescriptor*>* output) const { + ForEach([containing_type, pool, &output](int number, const Extension& ext) { + bool has = false; + if (ext.is_repeated) { + has = ext.GetSize() > 0; + } else { + has = !ext.is_cleared; + } + + if (has) { + // TODO(kenton): Looking up each field by number is somewhat unfortunate. + // Is there a better way? The problem is that descriptors are lazily- + // initialized, so they might not even be constructed until + // AppendToList() is called. + + if (ext.descriptor == nullptr) { + output->push_back(pool->FindExtensionByNumber(containing_type, number)); + } else { + output->push_back(ext.descriptor); + } + } + }); +} + +inline FieldDescriptor::Type real_type(FieldType type) { + GOOGLE_DCHECK(type > 0 && type <= FieldDescriptor::MAX_TYPE); + return static_cast<FieldDescriptor::Type>(type); +} + +inline FieldDescriptor::CppType cpp_type(FieldType type) { + return FieldDescriptor::TypeToCppType( + static_cast<FieldDescriptor::Type>(type)); +} + +inline WireFormatLite::FieldType field_type(FieldType type) { + GOOGLE_DCHECK(type > 0 && type <= WireFormatLite::MAX_FIELD_TYPE); + return static_cast<WireFormatLite::FieldType>(type); +} + +#define GOOGLE_DCHECK_TYPE(EXTENSION, LABEL, CPPTYPE) \ + GOOGLE_DCHECK_EQ((EXTENSION).is_repeated ? FieldDescriptor::LABEL_REPEATED \ + : FieldDescriptor::LABEL_OPTIONAL, \ + FieldDescriptor::LABEL_##LABEL); \ + GOOGLE_DCHECK_EQ(cpp_type((EXTENSION).type), FieldDescriptor::CPPTYPE_##CPPTYPE) + +const MessageLite& ExtensionSet::GetMessage(int number, + const Descriptor* message_type, + MessageFactory* factory) const { + const Extension* extension = FindOrNull(number); + if (extension == nullptr || extension->is_cleared) { + // Not present. Return the default value. + return *factory->GetPrototype(message_type); + } else { + GOOGLE_DCHECK_TYPE(*extension, OPTIONAL, MESSAGE); + if (extension->is_lazy) { + return extension->lazymessage_value->GetMessage( + *factory->GetPrototype(message_type), arena_); + } else { + return *extension->message_value; + } + } +} + +MessageLite* ExtensionSet::MutableMessage(const FieldDescriptor* descriptor, + MessageFactory* factory) { + Extension* extension; + if (MaybeNewExtension(descriptor->number(), descriptor, &extension)) { + extension->type = descriptor->type(); + GOOGLE_DCHECK_EQ(cpp_type(extension->type), FieldDescriptor::CPPTYPE_MESSAGE); + extension->is_repeated = false; + extension->is_packed = false; + const MessageLite* prototype = + factory->GetPrototype(descriptor->message_type()); + extension->is_lazy = false; + extension->message_value = prototype->New(arena_); + extension->is_cleared = false; + return extension->message_value; + } else { + GOOGLE_DCHECK_TYPE(*extension, OPTIONAL, MESSAGE); + extension->is_cleared = false; + if (extension->is_lazy) { + return extension->lazymessage_value->MutableMessage( + *factory->GetPrototype(descriptor->message_type()), arena_); + } else { + return extension->message_value; + } + } +} + +MessageLite* ExtensionSet::ReleaseMessage(const FieldDescriptor* descriptor, + MessageFactory* factory) { + Extension* extension = FindOrNull(descriptor->number()); + if (extension == nullptr) { + // Not present. Return nullptr. + return nullptr; + } else { + GOOGLE_DCHECK_TYPE(*extension, OPTIONAL, MESSAGE); + MessageLite* ret = nullptr; + if (extension->is_lazy) { + ret = extension->lazymessage_value->ReleaseMessage( + *factory->GetPrototype(descriptor->message_type()), arena_); + if (arena_ == nullptr) { + delete extension->lazymessage_value; + } + } else { + if (arena_ != nullptr) { + ret = extension->message_value->New(); + ret->CheckTypeAndMergeFrom(*extension->message_value); + } else { + ret = extension->message_value; + } + } + Erase(descriptor->number()); + return ret; + } +} + +MessageLite* ExtensionSet::UnsafeArenaReleaseMessage( + const FieldDescriptor* descriptor, MessageFactory* factory) { + Extension* extension = FindOrNull(descriptor->number()); + if (extension == nullptr) { + // Not present. Return nullptr. + return nullptr; + } else { + GOOGLE_DCHECK_TYPE(*extension, OPTIONAL, MESSAGE); + MessageLite* ret = nullptr; + if (extension->is_lazy) { + ret = extension->lazymessage_value->UnsafeArenaReleaseMessage( + *factory->GetPrototype(descriptor->message_type()), arena_); + if (arena_ == nullptr) { + delete extension->lazymessage_value; + } + } else { + ret = extension->message_value; + } + Erase(descriptor->number()); + return ret; + } +} + +ExtensionSet::Extension* ExtensionSet::MaybeNewRepeatedExtension( + const FieldDescriptor* descriptor) { + Extension* extension; + if (MaybeNewExtension(descriptor->number(), descriptor, &extension)) { + extension->type = descriptor->type(); + GOOGLE_DCHECK_EQ(cpp_type(extension->type), FieldDescriptor::CPPTYPE_MESSAGE); + extension->is_repeated = true; + extension->repeated_message_value = + Arena::CreateMessage<RepeatedPtrField<MessageLite> >(arena_); + } else { + GOOGLE_DCHECK_TYPE(*extension, REPEATED, MESSAGE); + } + return extension; +} + +MessageLite* ExtensionSet::AddMessage(const FieldDescriptor* descriptor, + MessageFactory* factory) { + Extension* extension = MaybeNewRepeatedExtension(descriptor); + + // RepeatedPtrField<Message> does not know how to Add() since it cannot + // allocate an abstract object, so we have to be tricky. + MessageLite* result = + reinterpret_cast<internal::RepeatedPtrFieldBase*>( + extension->repeated_message_value) + ->AddFromCleared<GenericTypeHandler<MessageLite> >(); + if (result == nullptr) { + const MessageLite* prototype; + if (extension->repeated_message_value->empty()) { + prototype = factory->GetPrototype(descriptor->message_type()); + GOOGLE_CHECK(prototype != nullptr); + } else { + prototype = &extension->repeated_message_value->Get(0); + } + result = prototype->New(arena_); + extension->repeated_message_value->AddAllocated(result); + } + return result; +} + +void ExtensionSet::AddAllocatedMessage(const FieldDescriptor* descriptor, + MessageLite* new_entry) { + Extension* extension = MaybeNewRepeatedExtension(descriptor); + + extension->repeated_message_value->AddAllocated(new_entry); +} + +void ExtensionSet::UnsafeArenaAddAllocatedMessage( + const FieldDescriptor* descriptor, MessageLite* new_entry) { + Extension* extension = MaybeNewRepeatedExtension(descriptor); + + extension->repeated_message_value->UnsafeArenaAddAllocated(new_entry); +} + +static bool ValidateEnumUsingDescriptor(const void* arg, int number) { + return reinterpret_cast<const EnumDescriptor*>(arg)->FindValueByNumber( + number) != nullptr; +} + +bool DescriptorPoolExtensionFinder::Find(int number, ExtensionInfo* output) { + const FieldDescriptor* extension = + pool_->FindExtensionByNumber(containing_type_, number); + if (extension == nullptr) { + return false; + } else { + output->type = extension->type(); + output->is_repeated = extension->is_repeated(); + output->is_packed = extension->options().packed(); + output->descriptor = extension; + if (extension->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { + output->message_info.prototype = + factory_->GetPrototype(extension->message_type()); + GOOGLE_CHECK(output->message_info.prototype != nullptr) + << "Extension factory's GetPrototype() returned nullptr; extension: " + << extension->full_name(); + } else if (extension->cpp_type() == FieldDescriptor::CPPTYPE_ENUM) { + output->enum_validity_check.func = ValidateEnumUsingDescriptor; + output->enum_validity_check.arg = extension->enum_type(); + } + + return true; + } +} + + +bool ExtensionSet::FindExtension(int wire_type, uint32_t field, + const Message* containing_type, + const internal::ParseContext* ctx, + ExtensionInfo* extension, + bool* was_packed_on_wire) { + if (ctx->data().pool == nullptr) { + GeneratedExtensionFinder finder(containing_type); + if (!FindExtensionInfoFromFieldNumber(wire_type, field, &finder, extension, + was_packed_on_wire)) { + return false; + } + } else { + DescriptorPoolExtensionFinder finder(ctx->data().pool, ctx->data().factory, + containing_type->GetDescriptor()); + if (!FindExtensionInfoFromFieldNumber(wire_type, field, &finder, extension, + was_packed_on_wire)) { + return false; + } + } + return true; +} + +const char* ExtensionSet::ParseField(uint64_t tag, const char* ptr, + const Message* containing_type, + internal::InternalMetadata* metadata, + internal::ParseContext* ctx) { + int number = tag >> 3; + bool was_packed_on_wire; + ExtensionInfo extension; + if (!FindExtension(tag & 7, number, containing_type, ctx, &extension, + &was_packed_on_wire)) { + return UnknownFieldParse( + tag, metadata->mutable_unknown_fields<UnknownFieldSet>(), ptr, ctx); + } + return ParseFieldWithExtensionInfo<UnknownFieldSet>( + number, was_packed_on_wire, extension, metadata, ptr, ctx); +} + +const char* ExtensionSet::ParseFieldMaybeLazily( + uint64_t tag, const char* ptr, const Message* containing_type, + internal::InternalMetadata* metadata, internal::ParseContext* ctx) { + return ParseField(tag, ptr, containing_type, metadata, ctx); +} + +const char* ExtensionSet::ParseMessageSetItem( + const char* ptr, const Message* containing_type, + internal::InternalMetadata* metadata, internal::ParseContext* ctx) { + return ParseMessageSetItemTmpl<Message, UnknownFieldSet>(ptr, containing_type, + metadata, ctx); +} + +int ExtensionSet::SpaceUsedExcludingSelf() const { + return internal::FromIntSize(SpaceUsedExcludingSelfLong()); +} + +size_t ExtensionSet::SpaceUsedExcludingSelfLong() const { + size_t total_size = + (is_large() ? map_.large->size() : flat_capacity_) * sizeof(KeyValue); + ForEach([&total_size](int /* number */, const Extension& ext) { + total_size += ext.SpaceUsedExcludingSelfLong(); + }); + return total_size; +} + +inline size_t ExtensionSet::RepeatedMessage_SpaceUsedExcludingSelfLong( + RepeatedPtrFieldBase* field) { + return field->SpaceUsedExcludingSelfLong<GenericTypeHandler<Message> >(); +} + +size_t ExtensionSet::Extension::SpaceUsedExcludingSelfLong() const { + size_t total_size = 0; + if (is_repeated) { + switch (cpp_type(type)) { +#define HANDLE_TYPE(UPPERCASE, LOWERCASE) \ + case FieldDescriptor::CPPTYPE_##UPPERCASE: \ + total_size += sizeof(*repeated_##LOWERCASE##_value) + \ + repeated_##LOWERCASE##_value->SpaceUsedExcludingSelfLong(); \ + break + + HANDLE_TYPE(INT32, int32_t); + HANDLE_TYPE(INT64, int64_t); + HANDLE_TYPE(UINT32, uint32_t); + HANDLE_TYPE(UINT64, uint64_t); + HANDLE_TYPE(FLOAT, float); + HANDLE_TYPE(DOUBLE, double); + HANDLE_TYPE(BOOL, bool); + HANDLE_TYPE(ENUM, enum); + HANDLE_TYPE(STRING, string); +#undef HANDLE_TYPE + + case FieldDescriptor::CPPTYPE_MESSAGE: + // repeated_message_value is actually a RepeatedPtrField<MessageLite>, + // but MessageLite has no SpaceUsedLong(), so we must directly call + // RepeatedPtrFieldBase::SpaceUsedExcludingSelfLong() with a different + // type handler. + total_size += sizeof(*repeated_message_value) + + RepeatedMessage_SpaceUsedExcludingSelfLong( + reinterpret_cast<internal::RepeatedPtrFieldBase*>( + repeated_message_value)); + break; + } + } else { + switch (cpp_type(type)) { + case FieldDescriptor::CPPTYPE_STRING: + total_size += sizeof(*string_value) + + StringSpaceUsedExcludingSelfLong(*string_value); + break; + case FieldDescriptor::CPPTYPE_MESSAGE: + if (is_lazy) { + total_size += lazymessage_value->SpaceUsedLong(); + } else { + total_size += down_cast<Message*>(message_value)->SpaceUsedLong(); + } + break; + default: + // No extra storage costs for primitive types. + break; + } + } + return total_size; +} + +uint8_t* ExtensionSet::SerializeMessageSetWithCachedSizesToArray( + const MessageLite* extendee, uint8_t* target) const { + io::EpsCopyOutputStream stream( + target, MessageSetByteSize(), + io::CodedOutputStream::IsDefaultSerializationDeterministic()); + return InternalSerializeMessageSetWithCachedSizesToArray(extendee, target, + &stream); +} + +} // namespace internal +} // namespace protobuf +} // namespace google + +#include <google/protobuf/port_undef.inc> diff --git a/toolkit/components/protobuf/src/google/protobuf/extension_set_inl.h b/toolkit/components/protobuf/src/google/protobuf/extension_set_inl.h new file mode 100644 index 0000000000..e4e711721d --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/extension_set_inl.h @@ -0,0 +1,285 @@ +// 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. + +#ifndef GOOGLE_PROTOBUF_EXTENSION_SET_INL_H__ +#define GOOGLE_PROTOBUF_EXTENSION_SET_INL_H__ + +#include <google/protobuf/extension_set.h> +#include <google/protobuf/metadata_lite.h> +#include <google/protobuf/parse_context.h> + +namespace google { +namespace protobuf { +namespace internal { + +template <typename T> +const char* ExtensionSet::ParseFieldWithExtensionInfo( + int number, bool was_packed_on_wire, const ExtensionInfo& extension, + InternalMetadata* metadata, const char* ptr, internal::ParseContext* ctx) { + if (was_packed_on_wire) { + switch (extension.type) { +#define HANDLE_TYPE(UPPERCASE, CPP_CAMELCASE) \ + case WireFormatLite::TYPE_##UPPERCASE: \ + return internal::Packed##CPP_CAMELCASE##Parser( \ + MutableRawRepeatedField(number, extension.type, extension.is_packed, \ + extension.descriptor), \ + ptr, ctx); + HANDLE_TYPE(INT32, Int32); + HANDLE_TYPE(INT64, Int64); + HANDLE_TYPE(UINT32, UInt32); + HANDLE_TYPE(UINT64, UInt64); + HANDLE_TYPE(SINT32, SInt32); + HANDLE_TYPE(SINT64, SInt64); + HANDLE_TYPE(FIXED32, Fixed32); + HANDLE_TYPE(FIXED64, Fixed64); + HANDLE_TYPE(SFIXED32, SFixed32); + HANDLE_TYPE(SFIXED64, SFixed64); + HANDLE_TYPE(FLOAT, Float); + HANDLE_TYPE(DOUBLE, Double); + HANDLE_TYPE(BOOL, Bool); +#undef HANDLE_TYPE + + case WireFormatLite::TYPE_ENUM: + return internal::PackedEnumParserArg<T>( + MutableRawRepeatedField(number, extension.type, extension.is_packed, + extension.descriptor), + ptr, ctx, extension.enum_validity_check.func, + extension.enum_validity_check.arg, metadata, number); + case WireFormatLite::TYPE_STRING: + case WireFormatLite::TYPE_BYTES: + case WireFormatLite::TYPE_GROUP: + case WireFormatLite::TYPE_MESSAGE: + GOOGLE_LOG(FATAL) << "Non-primitive types can't be packed."; + break; + } + } else { + switch (extension.type) { +#define HANDLE_VARINT_TYPE(UPPERCASE, CPP_CAMELCASE) \ + case WireFormatLite::TYPE_##UPPERCASE: { \ + uint64_t value; \ + ptr = VarintParse(ptr, &value); \ + GOOGLE_PROTOBUF_PARSER_ASSERT(ptr); \ + if (extension.is_repeated) { \ + Add##CPP_CAMELCASE(number, WireFormatLite::TYPE_##UPPERCASE, \ + extension.is_packed, value, extension.descriptor); \ + } else { \ + Set##CPP_CAMELCASE(number, WireFormatLite::TYPE_##UPPERCASE, value, \ + extension.descriptor); \ + } \ + } break + + HANDLE_VARINT_TYPE(INT32, Int32); + HANDLE_VARINT_TYPE(INT64, Int64); + HANDLE_VARINT_TYPE(UINT32, UInt32); + HANDLE_VARINT_TYPE(UINT64, UInt64); + HANDLE_VARINT_TYPE(BOOL, Bool); +#undef HANDLE_VARINT_TYPE +#define HANDLE_SVARINT_TYPE(UPPERCASE, CPP_CAMELCASE, SIZE) \ + case WireFormatLite::TYPE_##UPPERCASE: { \ + uint64_t val; \ + ptr = VarintParse(ptr, &val); \ + GOOGLE_PROTOBUF_PARSER_ASSERT(ptr); \ + auto value = WireFormatLite::ZigZagDecode##SIZE(val); \ + if (extension.is_repeated) { \ + Add##CPP_CAMELCASE(number, WireFormatLite::TYPE_##UPPERCASE, \ + extension.is_packed, value, extension.descriptor); \ + } else { \ + Set##CPP_CAMELCASE(number, WireFormatLite::TYPE_##UPPERCASE, value, \ + extension.descriptor); \ + } \ + } break + + HANDLE_SVARINT_TYPE(SINT32, Int32, 32); + HANDLE_SVARINT_TYPE(SINT64, Int64, 64); +#undef HANDLE_SVARINT_TYPE +#define HANDLE_FIXED_TYPE(UPPERCASE, CPP_CAMELCASE, CPPTYPE) \ + case WireFormatLite::TYPE_##UPPERCASE: { \ + auto value = UnalignedLoad<CPPTYPE>(ptr); \ + ptr += sizeof(CPPTYPE); \ + if (extension.is_repeated) { \ + Add##CPP_CAMELCASE(number, WireFormatLite::TYPE_##UPPERCASE, \ + extension.is_packed, value, extension.descriptor); \ + } else { \ + Set##CPP_CAMELCASE(number, WireFormatLite::TYPE_##UPPERCASE, value, \ + extension.descriptor); \ + } \ + } break + + HANDLE_FIXED_TYPE(FIXED32, UInt32, uint32_t); + HANDLE_FIXED_TYPE(FIXED64, UInt64, uint64_t); + HANDLE_FIXED_TYPE(SFIXED32, Int32, int32_t); + HANDLE_FIXED_TYPE(SFIXED64, Int64, int64_t); + HANDLE_FIXED_TYPE(FLOAT, Float, float); + HANDLE_FIXED_TYPE(DOUBLE, Double, double); +#undef HANDLE_FIXED_TYPE + + case WireFormatLite::TYPE_ENUM: { + uint64_t val; + ptr = VarintParse(ptr, &val); + GOOGLE_PROTOBUF_PARSER_ASSERT(ptr); + int value = val; + + if (!extension.enum_validity_check.func( + extension.enum_validity_check.arg, value)) { + WriteVarint(number, val, metadata->mutable_unknown_fields<T>()); + } else if (extension.is_repeated) { + AddEnum(number, WireFormatLite::TYPE_ENUM, extension.is_packed, value, + extension.descriptor); + } else { + SetEnum(number, WireFormatLite::TYPE_ENUM, value, + extension.descriptor); + } + break; + } + + case WireFormatLite::TYPE_BYTES: + case WireFormatLite::TYPE_STRING: { + std::string* value = + extension.is_repeated + ? AddString(number, WireFormatLite::TYPE_STRING, + extension.descriptor) + : MutableString(number, WireFormatLite::TYPE_STRING, + extension.descriptor); + int size = ReadSize(&ptr); + GOOGLE_PROTOBUF_PARSER_ASSERT(ptr); + return ctx->ReadString(ptr, size, value); + } + + case WireFormatLite::TYPE_GROUP: { + MessageLite* value = + extension.is_repeated + ? AddMessage(number, WireFormatLite::TYPE_GROUP, + *extension.message_info.prototype, + extension.descriptor) + : MutableMessage(number, WireFormatLite::TYPE_GROUP, + *extension.message_info.prototype, + extension.descriptor); + uint32_t tag = (number << 3) + WireFormatLite::WIRETYPE_START_GROUP; + return ctx->ParseGroup(value, ptr, tag); + } + + case WireFormatLite::TYPE_MESSAGE: { + MessageLite* value = + extension.is_repeated + ? AddMessage(number, WireFormatLite::TYPE_MESSAGE, + *extension.message_info.prototype, + extension.descriptor) + : MutableMessage(number, WireFormatLite::TYPE_MESSAGE, + *extension.message_info.prototype, + extension.descriptor); + return ctx->ParseMessage(value, ptr); + } + } + } + return ptr; +} + +template <typename Msg, typename T> +const char* ExtensionSet::ParseMessageSetItemTmpl( + const char* ptr, const Msg* extendee, internal::InternalMetadata* metadata, + internal::ParseContext* ctx) { + std::string payload; + uint32_t type_id; + enum class State { kNoTag, kHasType, kHasPayload, kDone }; + State state = State::kNoTag; + + while (!ctx->Done(&ptr)) { + uint32_t tag = static_cast<uint8_t>(*ptr++); + if (tag == WireFormatLite::kMessageSetTypeIdTag) { + uint64_t tmp; + ptr = ParseBigVarint(ptr, &tmp); + GOOGLE_PROTOBUF_PARSER_ASSERT(ptr); + if (state == State::kNoTag) { + type_id = tmp; + state = State::kHasType; + } else if (state == State::kHasPayload) { + type_id = tmp; + ExtensionInfo extension; + bool was_packed_on_wire; + if (!FindExtension(2, type_id, extendee, ctx, &extension, + &was_packed_on_wire)) { + WriteLengthDelimited(type_id, payload, + metadata->mutable_unknown_fields<T>()); + } else { + MessageLite* value = + extension.is_repeated + ? AddMessage(type_id, WireFormatLite::TYPE_MESSAGE, + *extension.message_info.prototype, + extension.descriptor) + : MutableMessage(type_id, WireFormatLite::TYPE_MESSAGE, + *extension.message_info.prototype, + extension.descriptor); + + const char* p; + // We can't use regular parse from string as we have to track + // proper recursion depth and descriptor pools. + ParseContext tmp_ctx(ctx->depth(), false, &p, payload); + tmp_ctx.data().pool = ctx->data().pool; + tmp_ctx.data().factory = ctx->data().factory; + GOOGLE_PROTOBUF_PARSER_ASSERT(value->_InternalParse(p, &tmp_ctx) && + tmp_ctx.EndedAtLimit()); + } + state = State::kDone; + } + } else if (tag == WireFormatLite::kMessageSetMessageTag) { + if (state == State::kHasType) { + ptr = ParseFieldMaybeLazily(static_cast<uint64_t>(type_id) * 8 + 2, ptr, + extendee, metadata, ctx); + GOOGLE_PROTOBUF_PARSER_ASSERT(ptr != nullptr); + state = State::kDone; + } else { + std::string tmp; + int32_t size = ReadSize(&ptr); + GOOGLE_PROTOBUF_PARSER_ASSERT(ptr); + ptr = ctx->ReadString(ptr, size, &tmp); + GOOGLE_PROTOBUF_PARSER_ASSERT(ptr); + if (state == State::kNoTag) { + payload = std::move(tmp); + state = State::kHasPayload; + } + } + } else { + ptr = ReadTag(ptr - 1, &tag); + if (tag == 0 || (tag & 7) == 4) { + ctx->SetLastTag(tag); + return ptr; + } + ptr = ParseField(tag, ptr, extendee, metadata, ctx); + GOOGLE_PROTOBUF_PARSER_ASSERT(ptr); + } + } + return ptr; +} + +} // namespace internal +} // namespace protobuf +} // namespace google + +#endif // GOOGLE_PROTOBUF_EXTENSION_SET_INL_H__ diff --git a/toolkit/components/protobuf/src/google/protobuf/field_access_listener.h b/toolkit/components/protobuf/src/google/protobuf/field_access_listener.h new file mode 100644 index 0000000000..47422e63c1 --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/field_access_listener.h @@ -0,0 +1,172 @@ +// 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. + +#ifndef GOOGLE_PROTOBUF_FIELD_ACCESS_LISTENER_H__ +#define GOOGLE_PROTOBUF_FIELD_ACCESS_LISTENER_H__ + +#include <cstddef> + +#include <google/protobuf/stubs/common.h> +#include <google/protobuf/message_lite.h> + + +namespace google { +namespace protobuf { + +// A default/no-op implementation of message hooks. +// +// See go/statically-dispatched-message-hooks for details. +template <typename Proto> +struct NoOpAccessListener { + // Number of fields are provided at compile time for the trackers to be able + // to have stack allocated bitmaps for the fields. This is useful for + // performance critical trackers. This is also to avoid cyclic dependencies + // if the number of fields is needed. + static constexpr int kFields = Proto::_kInternalFieldNumber; + // Default constructor is called during the static global initialization of + // the program. + // We provide a pointer to extract the name of the proto not to get cyclic + // dependencies on GetDescriptor() and OnGetMetadata() calls. If you want + // to differentiate the protos during the runtime before the start of the + // program, use this functor to get its name. We either way need it for + // LITE_RUNTIME protos as they don't have descriptors at all. + explicit NoOpAccessListener(StringPiece (*name_extractor)()) {} + // called repeatedly during serialization/deserialization/ByteSize of + // Reflection as: + // AccessListener<MessageT>::OnSerialize(this); + static void OnSerialize(const MessageLite* msg) {} + static void OnDeserialize(const MessageLite* msg) {} + static void OnByteSize(const MessageLite* msg) {} + static void OnMergeFrom(const MessageLite* to, const MessageLite* from) {} + + // NOTE: This function can be called pre-main. Make sure it does not make + // the state of the listener invalid. + static void OnGetMetadata() {} + + // called from accessors as: + // AccessListener<MessageT>::On$operation(this, &field_storage_); + // If you need to override this with type, in your hook implementation + // introduce + // template <int kFieldNum, typename T> + // static void On$operation(const MessageLite* msg, + // const T* field) {} + // And overloads for std::nullptr_t for incomplete types such as Messages, + // Maps. Extract them using reflection if you need. Consequently, second + // argument can be null pointer. + // For an example, see proto_hooks/testing/memory_test_field_listener.h + // And argument template deduction will deduce the type itself without + // changing the generated code. + + // add_<field>(f) + template <int kFieldNum> + static void OnAdd(const MessageLite* msg, const void* field) {} + + // add_<field>() + template <int kFieldNum> + static void OnAddMutable(const MessageLite* msg, const void* field) {} + + // <field>() and <repeated_field>(i) + template <int kFieldNum> + static void OnGet(const MessageLite* msg, const void* field) {} + + // clear_<field>() + template <int kFieldNum> + static void OnClear(const MessageLite* msg, const void* field) {} + + // has_<field>() + template <int kFieldNum> + static void OnHas(const MessageLite* msg, const void* field) {} + + // <repeated_field>() + template <int kFieldNum> + static void OnList(const MessageLite* msg, const void* field) {} + + // mutable_<field>() + template <int kFieldNum> + static void OnMutable(const MessageLite* msg, const void* field) {} + + // mutable_<repeated_field>() + template <int kFieldNum> + static void OnMutableList(const MessageLite* msg, const void* field) {} + + // release_<field>() + template <int kFieldNum> + static void OnRelease(const MessageLite* msg, const void* field) {} + + // set_<field>() and set_<repeated_field>(i) + template <int kFieldNum> + static void OnSet(const MessageLite* msg, const void* field) {} + + // <repeated_field>_size() + template <int kFieldNum> + static void OnSize(const MessageLite* msg, const void* field) {} + + static void OnHasExtension(const MessageLite* msg, int extension_tag, + const void* field) {} + // TODO(b/190614678): Support clear in the proto compiler. + static void OnClearExtension(const MessageLite* msg, int extension_tag, + const void* field) {} + static void OnExtensionSize(const MessageLite* msg, int extension_tag, + const void* field) {} + static void OnGetExtension(const MessageLite* msg, int extension_tag, + const void* field) {} + static void OnMutableExtension(const MessageLite* msg, int extension_tag, + const void* field) {} + static void OnSetExtension(const MessageLite* msg, int extension_tag, + const void* field) {} + static void OnReleaseExtension(const MessageLite* msg, int extension_tag, + const void* field) {} + static void OnAddExtension(const MessageLite* msg, int extension_tag, + const void* field) {} + static void OnAddMutableExtension(const MessageLite* msg, int extension_tag, + const void* field) {} + static void OnListExtension(const MessageLite* msg, int extension_tag, + const void* field) {} + static void OnMutableListExtension(const MessageLite* msg, int extension_tag, + const void* field) {} +}; + +} // namespace protobuf +} // namespace google + +#ifndef REPLACE_PROTO_LISTENER_IMPL +namespace google { +namespace protobuf { +template <class T> +using AccessListener = NoOpAccessListener<T>; +} // namespace protobuf +} // namespace google +#else +// You can put your implementations of hooks/listeners here. +// All hooks are subject to approval by protobuf-team@. + +#endif // !REPLACE_PROTO_LISTENER_IMPL + +#endif // GOOGLE_PROTOBUF_FIELD_ACCESS_LISTENER_H__ diff --git a/toolkit/components/protobuf/src/google/protobuf/field_mask.pb.cc b/toolkit/components/protobuf/src/google/protobuf/field_mask.pb.cc new file mode 100644 index 0000000000..7860bfbfed --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/field_mask.pb.cc @@ -0,0 +1,284 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: google/protobuf/field_mask.proto + +#include <google/protobuf/field_mask.pb.h> + +#include <algorithm> + +#include <google/protobuf/io/coded_stream.h> +#include <google/protobuf/extension_set.h> +#include <google/protobuf/wire_format_lite.h> +#include <google/protobuf/descriptor.h> +#include <google/protobuf/generated_message_reflection.h> +#include <google/protobuf/reflection_ops.h> +#include <google/protobuf/wire_format.h> +// @@protoc_insertion_point(includes) +#include <google/protobuf/port_def.inc> + +PROTOBUF_PRAGMA_INIT_SEG + +namespace _pb = ::PROTOBUF_NAMESPACE_ID; +namespace _pbi = _pb::internal; + +PROTOBUF_NAMESPACE_OPEN +PROTOBUF_CONSTEXPR FieldMask::FieldMask( + ::_pbi::ConstantInitialized): _impl_{ + /*decltype(_impl_.paths_)*/{} + , /*decltype(_impl_._cached_size_)*/{}} {} +struct FieldMaskDefaultTypeInternal { + PROTOBUF_CONSTEXPR FieldMaskDefaultTypeInternal() + : _instance(::_pbi::ConstantInitialized{}) {} + ~FieldMaskDefaultTypeInternal() {} + union { + FieldMask _instance; + }; +}; +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 FieldMaskDefaultTypeInternal _FieldMask_default_instance_; +PROTOBUF_NAMESPACE_CLOSE +static ::_pb::Metadata file_level_metadata_google_2fprotobuf_2ffield_5fmask_2eproto[1]; +static constexpr ::_pb::EnumDescriptor const** file_level_enum_descriptors_google_2fprotobuf_2ffield_5fmask_2eproto = nullptr; +static constexpr ::_pb::ServiceDescriptor const** file_level_service_descriptors_google_2fprotobuf_2ffield_5fmask_2eproto = nullptr; + +const uint32_t TableStruct_google_2fprotobuf_2ffield_5fmask_2eproto::offsets[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = { + ~0u, // no _has_bits_ + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::FieldMask, _internal_metadata_), + ~0u, // no _extensions_ + ~0u, // no _oneof_case_ + ~0u, // no _weak_field_map_ + ~0u, // no _inlined_string_donated_ + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::FieldMask, _impl_.paths_), +}; +static const ::_pbi::MigrationSchema schemas[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = { + { 0, -1, -1, sizeof(::PROTOBUF_NAMESPACE_ID::FieldMask)}, +}; + +static const ::_pb::Message* const file_default_instances[] = { + &::PROTOBUF_NAMESPACE_ID::_FieldMask_default_instance_._instance, +}; + +const char descriptor_table_protodef_google_2fprotobuf_2ffield_5fmask_2eproto[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = + "\n google/protobuf/field_mask.proto\022\017goog" + "le.protobuf\"\032\n\tFieldMask\022\r\n\005paths\030\001 \003(\tB" + "\205\001\n\023com.google.protobufB\016FieldMaskProtoP" + "\001Z2google.golang.org/protobuf/types/know" + "n/fieldmaskpb\370\001\001\242\002\003GPB\252\002\036Google.Protobuf" + ".WellKnownTypesb\006proto3" + ; +static ::_pbi::once_flag descriptor_table_google_2fprotobuf_2ffield_5fmask_2eproto_once; +const ::_pbi::DescriptorTable descriptor_table_google_2fprotobuf_2ffield_5fmask_2eproto = { + false, false, 223, descriptor_table_protodef_google_2fprotobuf_2ffield_5fmask_2eproto, + "google/protobuf/field_mask.proto", + &descriptor_table_google_2fprotobuf_2ffield_5fmask_2eproto_once, nullptr, 0, 1, + schemas, file_default_instances, TableStruct_google_2fprotobuf_2ffield_5fmask_2eproto::offsets, + file_level_metadata_google_2fprotobuf_2ffield_5fmask_2eproto, file_level_enum_descriptors_google_2fprotobuf_2ffield_5fmask_2eproto, + file_level_service_descriptors_google_2fprotobuf_2ffield_5fmask_2eproto, +}; +PROTOBUF_ATTRIBUTE_WEAK const ::_pbi::DescriptorTable* descriptor_table_google_2fprotobuf_2ffield_5fmask_2eproto_getter() { + return &descriptor_table_google_2fprotobuf_2ffield_5fmask_2eproto; +} + +// Force running AddDescriptors() at dynamic initialization time. +PROTOBUF_ATTRIBUTE_INIT_PRIORITY2 static ::_pbi::AddDescriptorsRunner dynamic_init_dummy_google_2fprotobuf_2ffield_5fmask_2eproto(&descriptor_table_google_2fprotobuf_2ffield_5fmask_2eproto); +PROTOBUF_NAMESPACE_OPEN + +// =================================================================== + +class FieldMask::_Internal { + public: +}; + +FieldMask::FieldMask(::PROTOBUF_NAMESPACE_ID::Arena* arena, + bool is_message_owned) + : ::PROTOBUF_NAMESPACE_ID::Message(arena, is_message_owned) { + SharedCtor(arena, is_message_owned); + // @@protoc_insertion_point(arena_constructor:google.protobuf.FieldMask) +} +FieldMask::FieldMask(const FieldMask& from) + : ::PROTOBUF_NAMESPACE_ID::Message() { + FieldMask* const _this = this; (void)_this; + new (&_impl_) Impl_{ + decltype(_impl_.paths_){from._impl_.paths_} + , /*decltype(_impl_._cached_size_)*/{}}; + + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); + // @@protoc_insertion_point(copy_constructor:google.protobuf.FieldMask) +} + +inline void FieldMask::SharedCtor( + ::_pb::Arena* arena, bool is_message_owned) { + (void)arena; + (void)is_message_owned; + new (&_impl_) Impl_{ + decltype(_impl_.paths_){arena} + , /*decltype(_impl_._cached_size_)*/{} + }; +} + +FieldMask::~FieldMask() { + // @@protoc_insertion_point(destructor:google.protobuf.FieldMask) + if (auto *arena = _internal_metadata_.DeleteReturnArena<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>()) { + (void)arena; + return; + } + SharedDtor(); +} + +inline void FieldMask::SharedDtor() { + GOOGLE_DCHECK(GetArenaForAllocation() == nullptr); + _impl_.paths_.~RepeatedPtrField(); +} + +void FieldMask::SetCachedSize(int size) const { + _impl_._cached_size_.Set(size); +} + +void FieldMask::Clear() { +// @@protoc_insertion_point(message_clear_start:google.protobuf.FieldMask) + uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + _impl_.paths_.Clear(); + _internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); +} + +const char* FieldMask::_InternalParse(const char* ptr, ::_pbi::ParseContext* ctx) { +#define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure + while (!ctx->Done(&ptr)) { + uint32_t tag; + ptr = ::_pbi::ReadTag(ptr, &tag); + switch (tag >> 3) { + // repeated string paths = 1; + case 1: + if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 10)) { + ptr -= 1; + do { + ptr += 1; + auto str = _internal_add_paths(); + ptr = ::_pbi::InlineGreedyStringParser(str, ptr, ctx); + CHK_(ptr); + CHK_(::_pbi::VerifyUTF8(str, "google.protobuf.FieldMask.paths")); + if (!ctx->DataAvailable(ptr)) break; + } while (::PROTOBUF_NAMESPACE_ID::internal::ExpectTag<10>(ptr)); + } else + goto handle_unusual; + continue; + default: + goto handle_unusual; + } // switch + handle_unusual: + if ((tag == 0) || ((tag & 7) == 4)) { + CHK_(ptr); + ctx->SetLastTag(tag); + goto message_done; + } + ptr = UnknownFieldParse( + tag, + _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(), + ptr, ctx); + CHK_(ptr != nullptr); + } // while +message_done: + return ptr; +failure: + ptr = nullptr; + goto message_done; +#undef CHK_ +} + +uint8_t* FieldMask::_InternalSerialize( + uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const { + // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.FieldMask) + uint32_t cached_has_bits = 0; + (void) cached_has_bits; + + // repeated string paths = 1; + for (int i = 0, n = this->_internal_paths_size(); i < n; i++) { + const auto& s = this->_internal_paths(i); + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::VerifyUtf8String( + s.data(), static_cast<int>(s.length()), + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::SERIALIZE, + "google.protobuf.FieldMask.paths"); + target = stream->WriteString(1, s, target); + } + + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + target = ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( + _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.FieldMask) + return target; +} + +size_t FieldMask::ByteSizeLong() const { +// @@protoc_insertion_point(message_byte_size_start:google.protobuf.FieldMask) + size_t total_size = 0; + + uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + // repeated string paths = 1; + total_size += 1 * + ::PROTOBUF_NAMESPACE_ID::internal::FromIntSize(_impl_.paths_.size()); + for (int i = 0, n = _impl_.paths_.size(); i < n; i++) { + total_size += ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize( + _impl_.paths_.Get(i)); + } + + return MaybeComputeUnknownFieldsSize(total_size, &_impl_._cached_size_); +} + +const ::PROTOBUF_NAMESPACE_ID::Message::ClassData FieldMask::_class_data_ = { + ::PROTOBUF_NAMESPACE_ID::Message::CopyWithSourceCheck, + FieldMask::MergeImpl +}; +const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*FieldMask::GetClassData() const { return &_class_data_; } + + +void FieldMask::MergeImpl(::PROTOBUF_NAMESPACE_ID::Message& to_msg, const ::PROTOBUF_NAMESPACE_ID::Message& from_msg) { + auto* const _this = static_cast<FieldMask*>(&to_msg); + auto& from = static_cast<const FieldMask&>(from_msg); + // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.FieldMask) + GOOGLE_DCHECK_NE(&from, _this); + uint32_t cached_has_bits = 0; + (void) cached_has_bits; + + _this->_impl_.paths_.MergeFrom(from._impl_.paths_); + _this->_internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); +} + +void FieldMask::CopyFrom(const FieldMask& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.FieldMask) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool FieldMask::IsInitialized() const { + return true; +} + +void FieldMask::InternalSwap(FieldMask* other) { + using std::swap; + _internal_metadata_.InternalSwap(&other->_internal_metadata_); + _impl_.paths_.InternalSwap(&other->_impl_.paths_); +} + +::PROTOBUF_NAMESPACE_ID::Metadata FieldMask::GetMetadata() const { + return ::_pbi::AssignDescriptors( + &descriptor_table_google_2fprotobuf_2ffield_5fmask_2eproto_getter, &descriptor_table_google_2fprotobuf_2ffield_5fmask_2eproto_once, + file_level_metadata_google_2fprotobuf_2ffield_5fmask_2eproto[0]); +} + +// @@protoc_insertion_point(namespace_scope) +PROTOBUF_NAMESPACE_CLOSE +PROTOBUF_NAMESPACE_OPEN +template<> PROTOBUF_NOINLINE ::PROTOBUF_NAMESPACE_ID::FieldMask* +Arena::CreateMaybeMessage< ::PROTOBUF_NAMESPACE_ID::FieldMask >(Arena* arena) { + return Arena::CreateMessageInternal< ::PROTOBUF_NAMESPACE_ID::FieldMask >(arena); +} +PROTOBUF_NAMESPACE_CLOSE + +// @@protoc_insertion_point(global_scope) +#include <google/protobuf/port_undef.inc> diff --git a/toolkit/components/protobuf/src/google/protobuf/field_mask.pb.h b/toolkit/components/protobuf/src/google/protobuf/field_mask.pb.h new file mode 100644 index 0000000000..ecc6edee9a --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/field_mask.pb.h @@ -0,0 +1,317 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: google/protobuf/field_mask.proto + +#ifndef GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2ffield_5fmask_2eproto +#define GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2ffield_5fmask_2eproto + +#include <limits> +#include <string> + +#include <google/protobuf/port_def.inc> +#if PROTOBUF_VERSION < 3021000 +#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 3021006 < 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. +#endif + +#include <google/protobuf/port_undef.inc> +#include <google/protobuf/io/coded_stream.h> +#include <google/protobuf/arena.h> +#include <google/protobuf/arenastring.h> +#include <google/protobuf/generated_message_util.h> +#include <google/protobuf/metadata_lite.h> +#include <google/protobuf/generated_message_reflection.h> +#include <google/protobuf/message.h> +#include <google/protobuf/repeated_field.h> // IWYU pragma: export +#include <google/protobuf/extension_set.h> // IWYU pragma: export +#include <google/protobuf/unknown_field_set.h> +// @@protoc_insertion_point(includes) +#include <google/protobuf/port_def.inc> +#define PROTOBUF_INTERNAL_EXPORT_google_2fprotobuf_2ffield_5fmask_2eproto PROTOBUF_EXPORT +PROTOBUF_NAMESPACE_OPEN +namespace internal { +class AnyMetadata; +} // namespace internal +PROTOBUF_NAMESPACE_CLOSE + +// Internal implementation detail -- do not use these members. +struct PROTOBUF_EXPORT TableStruct_google_2fprotobuf_2ffield_5fmask_2eproto { + static const uint32_t offsets[]; +}; +PROTOBUF_EXPORT extern const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable descriptor_table_google_2fprotobuf_2ffield_5fmask_2eproto; +PROTOBUF_NAMESPACE_OPEN +class FieldMask; +struct FieldMaskDefaultTypeInternal; +PROTOBUF_EXPORT extern FieldMaskDefaultTypeInternal _FieldMask_default_instance_; +PROTOBUF_NAMESPACE_CLOSE +PROTOBUF_NAMESPACE_OPEN +template<> PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::FieldMask* Arena::CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::FieldMask>(Arena*); +PROTOBUF_NAMESPACE_CLOSE +PROTOBUF_NAMESPACE_OPEN + +// =================================================================== + +class PROTOBUF_EXPORT FieldMask final : + public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.FieldMask) */ { + public: + inline FieldMask() : FieldMask(nullptr) {} + ~FieldMask() override; + explicit PROTOBUF_CONSTEXPR FieldMask(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized); + + FieldMask(const FieldMask& from); + FieldMask(FieldMask&& from) noexcept + : FieldMask() { + *this = ::std::move(from); + } + + inline FieldMask& operator=(const FieldMask& from) { + CopyFrom(from); + return *this; + } + inline FieldMask& operator=(FieldMask&& from) noexcept { + if (this == &from) return *this; + if (GetOwningArena() == from.GetOwningArena() + #ifdef PROTOBUF_FORCE_COPY_IN_MOVE + && GetOwningArena() != nullptr + #endif // !PROTOBUF_FORCE_COPY_IN_MOVE + ) { + InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* descriptor() { + return GetDescriptor(); + } + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() { + return default_instance().GetMetadata().descriptor; + } + static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() { + return default_instance().GetMetadata().reflection; + } + static const FieldMask& default_instance() { + return *internal_default_instance(); + } + static inline const FieldMask* internal_default_instance() { + return reinterpret_cast<const FieldMask*>( + &_FieldMask_default_instance_); + } + static constexpr int kIndexInFileMessages = + 0; + + friend void swap(FieldMask& a, FieldMask& b) { + a.Swap(&b); + } + inline void Swap(FieldMask* other) { + if (other == this) return; + #ifdef PROTOBUF_FORCE_COPY_IN_SWAP + if (GetOwningArena() != nullptr && + GetOwningArena() == other->GetOwningArena()) { + #else // PROTOBUF_FORCE_COPY_IN_SWAP + if (GetOwningArena() == other->GetOwningArena()) { + #endif // !PROTOBUF_FORCE_COPY_IN_SWAP + InternalSwap(other); + } else { + ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(FieldMask* other) { + if (other == this) return; + GOOGLE_DCHECK(GetOwningArena() == other->GetOwningArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + FieldMask* New(::PROTOBUF_NAMESPACE_ID::Arena* arena = nullptr) const final { + return CreateMaybeMessage<FieldMask>(arena); + } + using ::PROTOBUF_NAMESPACE_ID::Message::CopyFrom; + void CopyFrom(const FieldMask& from); + using ::PROTOBUF_NAMESPACE_ID::Message::MergeFrom; + void MergeFrom( const FieldMask& from) { + FieldMask::MergeImpl(*this, from); + } + private: + static void MergeImpl(::PROTOBUF_NAMESPACE_ID::Message& to_msg, const ::PROTOBUF_NAMESPACE_ID::Message& from_msg); + public: + PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + bool IsInitialized() const final; + + size_t ByteSizeLong() const final; + const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final; + uint8_t* _InternalSerialize( + uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final; + int GetCachedSize() const final { return _impl_._cached_size_.Get(); } + + private: + void SharedCtor(::PROTOBUF_NAMESPACE_ID::Arena* arena, bool is_message_owned); + void SharedDtor(); + void SetCachedSize(int size) const final; + void InternalSwap(FieldMask* other); + + private: + friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata; + static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() { + return "google.protobuf.FieldMask"; + } + protected: + explicit FieldMask(::PROTOBUF_NAMESPACE_ID::Arena* arena, + bool is_message_owned = false); + public: + + static const ClassData _class_data_; + const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*GetClassData() const final; + + ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final; + + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + + enum : int { + kPathsFieldNumber = 1, + }; + // repeated string paths = 1; + int paths_size() const; + private: + int _internal_paths_size() const; + public: + void clear_paths(); + const std::string& paths(int index) const; + std::string* mutable_paths(int index); + void set_paths(int index, const std::string& value); + void set_paths(int index, std::string&& value); + void set_paths(int index, const char* value); + void set_paths(int index, const char* value, size_t size); + std::string* add_paths(); + void add_paths(const std::string& value); + void add_paths(std::string&& value); + void add_paths(const char* value); + void add_paths(const char* value, size_t size); + const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField<std::string>& paths() const; + ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField<std::string>* mutable_paths(); + private: + const std::string& _internal_paths(int index) const; + std::string* _internal_add_paths(); + public: + + // @@protoc_insertion_point(class_scope:google.protobuf.FieldMask) + private: + class _Internal; + + template <typename T> friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper; + typedef void InternalArenaConstructable_; + typedef void DestructorSkippable_; + struct Impl_ { + ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField<std::string> paths_; + mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_; + }; + union { Impl_ _impl_; }; + friend struct ::TableStruct_google_2fprotobuf_2ffield_5fmask_2eproto; +}; +// =================================================================== + + +// =================================================================== + +#ifdef __GNUC__ + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wstrict-aliasing" +#endif // __GNUC__ +// FieldMask + +// repeated string paths = 1; +inline int FieldMask::_internal_paths_size() const { + return _impl_.paths_.size(); +} +inline int FieldMask::paths_size() const { + return _internal_paths_size(); +} +inline void FieldMask::clear_paths() { + _impl_.paths_.Clear(); +} +inline std::string* FieldMask::add_paths() { + std::string* _s = _internal_add_paths(); + // @@protoc_insertion_point(field_add_mutable:google.protobuf.FieldMask.paths) + return _s; +} +inline const std::string& FieldMask::_internal_paths(int index) const { + return _impl_.paths_.Get(index); +} +inline const std::string& FieldMask::paths(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.FieldMask.paths) + return _internal_paths(index); +} +inline std::string* FieldMask::mutable_paths(int index) { + // @@protoc_insertion_point(field_mutable:google.protobuf.FieldMask.paths) + return _impl_.paths_.Mutable(index); +} +inline void FieldMask::set_paths(int index, const std::string& value) { + _impl_.paths_.Mutable(index)->assign(value); + // @@protoc_insertion_point(field_set:google.protobuf.FieldMask.paths) +} +inline void FieldMask::set_paths(int index, std::string&& value) { + _impl_.paths_.Mutable(index)->assign(std::move(value)); + // @@protoc_insertion_point(field_set:google.protobuf.FieldMask.paths) +} +inline void FieldMask::set_paths(int index, const char* value) { + GOOGLE_DCHECK(value != nullptr); + _impl_.paths_.Mutable(index)->assign(value); + // @@protoc_insertion_point(field_set_char:google.protobuf.FieldMask.paths) +} +inline void FieldMask::set_paths(int index, const char* value, size_t size) { + _impl_.paths_.Mutable(index)->assign( + reinterpret_cast<const char*>(value), size); + // @@protoc_insertion_point(field_set_pointer:google.protobuf.FieldMask.paths) +} +inline std::string* FieldMask::_internal_add_paths() { + return _impl_.paths_.Add(); +} +inline void FieldMask::add_paths(const std::string& value) { + _impl_.paths_.Add()->assign(value); + // @@protoc_insertion_point(field_add:google.protobuf.FieldMask.paths) +} +inline void FieldMask::add_paths(std::string&& value) { + _impl_.paths_.Add(std::move(value)); + // @@protoc_insertion_point(field_add:google.protobuf.FieldMask.paths) +} +inline void FieldMask::add_paths(const char* value) { + GOOGLE_DCHECK(value != nullptr); + _impl_.paths_.Add()->assign(value); + // @@protoc_insertion_point(field_add_char:google.protobuf.FieldMask.paths) +} +inline void FieldMask::add_paths(const char* value, size_t size) { + _impl_.paths_.Add()->assign(reinterpret_cast<const char*>(value), size); + // @@protoc_insertion_point(field_add_pointer:google.protobuf.FieldMask.paths) +} +inline const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField<std::string>& +FieldMask::paths() const { + // @@protoc_insertion_point(field_list:google.protobuf.FieldMask.paths) + return _impl_.paths_; +} +inline ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField<std::string>* +FieldMask::mutable_paths() { + // @@protoc_insertion_point(field_mutable_list:google.protobuf.FieldMask.paths) + return &_impl_.paths_; +} + +#ifdef __GNUC__ + #pragma GCC diagnostic pop +#endif // __GNUC__ + +// @@protoc_insertion_point(namespace_scope) + +PROTOBUF_NAMESPACE_CLOSE + +// @@protoc_insertion_point(global_scope) + +#include <google/protobuf/port_undef.inc> +#endif // GOOGLE_PROTOBUF_INCLUDED_GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2ffield_5fmask_2eproto diff --git a/toolkit/components/protobuf/src/google/protobuf/field_mask.proto b/toolkit/components/protobuf/src/google/protobuf/field_mask.proto new file mode 100644 index 0000000000..6b5104f188 --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/field_mask.proto @@ -0,0 +1,245 @@ +// 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. + +syntax = "proto3"; + +package google.protobuf; + +option csharp_namespace = "Google.Protobuf.WellKnownTypes"; +option java_package = "com.google.protobuf"; +option java_outer_classname = "FieldMaskProto"; +option java_multiple_files = true; +option objc_class_prefix = "GPB"; +option go_package = "google.golang.org/protobuf/types/known/fieldmaskpb"; +option cc_enable_arenas = true; + +// `FieldMask` represents a set of symbolic field paths, for example: +// +// paths: "f.a" +// paths: "f.b.d" +// +// Here `f` represents a field in some root message, `a` and `b` +// fields in the message found in `f`, and `d` a field found in the +// message in `f.b`. +// +// Field masks are used to specify a subset of fields that should be +// returned by a get operation or modified by an update operation. +// Field masks also have a custom JSON encoding (see below). +// +// # Field Masks in Projections +// +// When used in the context of a projection, a response message or +// sub-message is filtered by the API to only contain those fields as +// specified in the mask. For example, if the mask in the previous +// example is applied to a response message as follows: +// +// f { +// a : 22 +// b { +// d : 1 +// x : 2 +// } +// y : 13 +// } +// z: 8 +// +// The result will not contain specific values for fields x,y and z +// (their value will be set to the default, and omitted in proto text +// output): +// +// +// f { +// a : 22 +// b { +// d : 1 +// } +// } +// +// A repeated field is not allowed except at the last position of a +// paths string. +// +// If a FieldMask object is not present in a get operation, the +// operation applies to all fields (as if a FieldMask of all fields +// had been specified). +// +// Note that a field mask does not necessarily apply to the +// top-level response message. In case of a REST get operation, the +// field mask applies directly to the response, but in case of a REST +// list operation, the mask instead applies to each individual message +// in the returned resource list. In case of a REST custom method, +// other definitions may be used. Where the mask applies will be +// clearly documented together with its declaration in the API. In +// any case, the effect on the returned resource/resources is required +// behavior for APIs. +// +// # Field Masks in Update Operations +// +// A field mask in update operations specifies which fields of the +// targeted resource are going to be updated. The API is required +// to only change the values of the fields as specified in the mask +// and leave the others untouched. If a resource is passed in to +// describe the updated values, the API ignores the values of all +// fields not covered by the mask. +// +// If a repeated field is specified for an update operation, new values will +// be appended to the existing repeated field in the target resource. Note that +// a repeated field is only allowed in the last position of a `paths` string. +// +// If a sub-message is specified in the last position of the field mask for an +// update operation, then new value will be merged into the existing sub-message +// in the target resource. +// +// For example, given the target message: +// +// f { +// b { +// d: 1 +// x: 2 +// } +// c: [1] +// } +// +// And an update message: +// +// f { +// b { +// d: 10 +// } +// c: [2] +// } +// +// then if the field mask is: +// +// paths: ["f.b", "f.c"] +// +// then the result will be: +// +// f { +// b { +// d: 10 +// x: 2 +// } +// c: [1, 2] +// } +// +// An implementation may provide options to override this default behavior for +// repeated and message fields. +// +// In order to reset a field's value to the default, the field must +// be in the mask and set to the default value in the provided resource. +// Hence, in order to reset all fields of a resource, provide a default +// instance of the resource and set all fields in the mask, or do +// not provide a mask as described below. +// +// If a field mask is not present on update, the operation applies to +// all fields (as if a field mask of all fields has been specified). +// Note that in the presence of schema evolution, this may mean that +// fields the client does not know and has therefore not filled into +// the request will be reset to their default. If this is unwanted +// behavior, a specific service may require a client to always specify +// a field mask, producing an error if not. +// +// As with get operations, the location of the resource which +// describes the updated values in the request message depends on the +// operation kind. In any case, the effect of the field mask is +// required to be honored by the API. +// +// ## Considerations for HTTP REST +// +// The HTTP kind of an update operation which uses a field mask must +// be set to PATCH instead of PUT in order to satisfy HTTP semantics +// (PUT must only be used for full updates). +// +// # JSON Encoding of Field Masks +// +// In JSON, a field mask is encoded as a single string where paths are +// separated by a comma. Fields name in each path are converted +// to/from lower-camel naming conventions. +// +// As an example, consider the following message declarations: +// +// message Profile { +// User user = 1; +// Photo photo = 2; +// } +// message User { +// string display_name = 1; +// string address = 2; +// } +// +// In proto a field mask for `Profile` may look as such: +// +// mask { +// paths: "user.display_name" +// paths: "photo" +// } +// +// In JSON, the same mask is represented as below: +// +// { +// mask: "user.displayName,photo" +// } +// +// # Field Masks and Oneof Fields +// +// Field masks treat fields in oneofs just as regular fields. Consider the +// following message: +// +// message SampleMessage { +// oneof test_oneof { +// string name = 4; +// SubMessage sub_message = 9; +// } +// } +// +// The field mask can be: +// +// mask { +// paths: "name" +// } +// +// Or: +// +// mask { +// paths: "sub_message" +// } +// +// Note that oneof type names ("test_oneof" in this case) cannot be used in +// paths. +// +// ## Field Mask Verification +// +// The implementation of any API method which has a FieldMask type field in the +// request should verify the included field paths, and return an +// `INVALID_ARGUMENT` error if any path is unmappable. +message FieldMask { + // The set of field mask paths. + repeated string paths = 1; +} diff --git a/toolkit/components/protobuf/src/google/protobuf/generated_enum_reflection.h b/toolkit/components/protobuf/src/google/protobuf/generated_enum_reflection.h new file mode 100644 index 0000000000..b96a9c61f9 --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/generated_enum_reflection.h @@ -0,0 +1,100 @@ +// 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. + +// Author: jasonh@google.com (Jason Hsueh) +// +// This header is logically internal, but is made public because it is used +// from protocol-compiler-generated code, which may reside in other components. +// It provides reflection support for generated enums, and is included in +// generated .pb.h files and should have minimal dependencies. The methods are +// implemented in generated_message_reflection.cc. + +#ifndef GOOGLE_PROTOBUF_GENERATED_ENUM_REFLECTION_H__ +#define GOOGLE_PROTOBUF_GENERATED_ENUM_REFLECTION_H__ + + +#include <string> + +#include <google/protobuf/port.h> +#include <google/protobuf/stubs/strutil.h> +#include <google/protobuf/generated_enum_util.h> + +#ifdef SWIG +#error "You cannot SWIG proto headers" +#endif + +// Must be included last. +#include <google/protobuf/port_def.inc> + +namespace google { +namespace protobuf { +class EnumDescriptor; +} // namespace protobuf +} // namespace google + +namespace google { +namespace protobuf { + +// Returns the EnumDescriptor for enum type E, which must be a +// proto-declared enum type. Code generated by the protocol compiler +// will include specializations of this template for each enum type declared. +template <typename E> +const EnumDescriptor* GetEnumDescriptor(); + +namespace internal { + +// Helper for EnumType_Parse functions: try to parse the string 'name' as +// an enum name of the given type, returning true and filling in value on +// success, or returning false and leaving value unchanged on failure. +PROTOBUF_EXPORT bool ParseNamedEnum(const EnumDescriptor* descriptor, + ConstStringParam name, int* value); + +template <typename EnumType> +bool ParseNamedEnum(const EnumDescriptor* descriptor, ConstStringParam name, + EnumType* value) { + int tmp; + if (!ParseNamedEnum(descriptor, name, &tmp)) return false; + *value = static_cast<EnumType>(tmp); + return true; +} + +// Just a wrapper around printing the name of a value. The main point of this +// function is not to be inlined, so that you can do this without including +// descriptor.h. +PROTOBUF_EXPORT const std::string& NameOfEnum(const EnumDescriptor* descriptor, + int value); + +} // namespace internal +} // namespace protobuf +} // namespace google + +#include <google/protobuf/port_undef.inc> + +#endif // GOOGLE_PROTOBUF_GENERATED_ENUM_REFLECTION_H__ diff --git a/toolkit/components/protobuf/src/google/protobuf/generated_enum_util.cc b/toolkit/components/protobuf/src/google/protobuf/generated_enum_util.cc new file mode 100644 index 0000000000..df7583e999 --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/generated_enum_util.cc @@ -0,0 +1,95 @@ +// 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. + +#include <google/protobuf/generated_enum_util.h> + +#include <algorithm> + +#include <google/protobuf/generated_message_util.h> + +namespace google { +namespace protobuf { +namespace internal { +namespace { + +bool EnumCompareByName(const EnumEntry& a, const EnumEntry& b) { + return StringPiece(a.name) < StringPiece(b.name); +} + +// Gets the numeric value of the EnumEntry at the given index, but returns a +// special value for the index -1. This gives a way to use std::lower_bound on a +// sorted array of indices while searching for value that we associate with -1. +int GetValue(const EnumEntry* enums, int i, int target) { + if (i == -1) { + return target; + } else { + return enums[i].value; + } +} + +} // namespace + +bool LookUpEnumValue(const EnumEntry* enums, size_t size, + StringPiece name, int* value) { + EnumEntry target{name, 0}; + auto it = std::lower_bound(enums, enums + size, target, EnumCompareByName); + if (it != enums + size && it->name == name) { + *value = it->value; + return true; + } + return false; +} + +int LookUpEnumName(const EnumEntry* enums, const int* sorted_indices, + size_t size, int value) { + auto comparator = [enums, value](int a, int b) { + return GetValue(enums, a, value) < GetValue(enums, b, value); + }; + auto it = + std::lower_bound(sorted_indices, sorted_indices + size, -1, comparator); + if (it != sorted_indices + size && enums[*it].value == value) { + return it - sorted_indices; + } + return -1; +} + +bool InitializeEnumStrings( + const EnumEntry* enums, const int* sorted_indices, size_t size, + internal::ExplicitlyConstructed<std::string>* enum_strings) { + for (size_t i = 0; i < size; ++i) { + enum_strings[i].Construct(enums[sorted_indices[i]].name); + internal::OnShutdownDestroyString(enum_strings[i].get_mutable()); + } + return true; +} + +} // namespace internal +} // namespace protobuf +} // namespace google diff --git a/toolkit/components/protobuf/src/google/protobuf/generated_enum_util.h b/toolkit/components/protobuf/src/google/protobuf/generated_enum_util.h new file mode 100644 index 0000000000..5d10ac010e --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/generated_enum_util.h @@ -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. + +#ifndef GOOGLE_PROTOBUF_GENERATED_ENUM_UTIL_H__ +#define GOOGLE_PROTOBUF_GENERATED_ENUM_UTIL_H__ + + +#include <type_traits> + +#include <google/protobuf/stubs/strutil.h> +#include <google/protobuf/message_lite.h> + +// Must be included last. +#include <google/protobuf/port_def.inc> + +#ifdef SWIG +#error "You cannot SWIG proto headers" +#endif + +namespace google { +namespace protobuf { + +// This type trait can be used to cause templates to only match proto2 enum +// types. +template <typename T> +struct is_proto_enum : ::std::false_type {}; + +namespace internal { + +// The table entry format for storing enum name-to-value mapping used with lite +// protos. This struct and the following related functions should only be used +// by protobuf generated code. +struct EnumEntry { + StringPiece name; + int value; +}; + +// Looks up a numeric enum value given the string name. +PROTOBUF_EXPORT bool LookUpEnumValue(const EnumEntry* enums, size_t size, + StringPiece name, int* value); + +// Looks up an enum name given the numeric value. +PROTOBUF_EXPORT int LookUpEnumName(const EnumEntry* enums, + const int* sorted_indices, size_t size, + int value); + +// Initializes the list of enum names in std::string form. +PROTOBUF_EXPORT bool InitializeEnumStrings( + const EnumEntry* enums, const int* sorted_indices, size_t size, + internal::ExplicitlyConstructed<std::string>* enum_strings); + +} // namespace internal +} // namespace protobuf +} // namespace google + +#include <google/protobuf/port_undef.inc> + +#endif // GOOGLE_PROTOBUF_GENERATED_ENUM_UTIL_H__ diff --git a/toolkit/components/protobuf/src/google/protobuf/generated_message_bases.cc b/toolkit/components/protobuf/src/google/protobuf/generated_message_bases.cc new file mode 100644 index 0000000000..306a38eef3 --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/generated_message_bases.cc @@ -0,0 +1,124 @@ +// 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. + +#include <google/protobuf/generated_message_bases.h> + +#include <google/protobuf/io/coded_stream.h> +#include <google/protobuf/io/zero_copy_stream_impl.h> +#include <google/protobuf/parse_context.h> +#include <google/protobuf/unknown_field_set.h> +#include <google/protobuf/wire_format.h> +#include <google/protobuf/wire_format_lite.h> + +// Must be last: +#include <google/protobuf/port_def.inc> + +namespace google { +namespace protobuf { +namespace internal { + +// ============================================================================= +// ZeroFieldsBase + +void ZeroFieldsBase::Clear() { + _internal_metadata_.Clear<UnknownFieldSet>(); // +} + +ZeroFieldsBase::~ZeroFieldsBase() { + (void)_internal_metadata_.DeleteReturnArena<UnknownFieldSet>(); +} + +size_t ZeroFieldsBase::ByteSizeLong() const { + return MaybeComputeUnknownFieldsSize(0, &_cached_size_); +} + +const char* ZeroFieldsBase::_InternalParse(const char* ptr, + internal::ParseContext* ctx) { +#define CHK_(x) \ + if (PROTOBUF_PREDICT_FALSE(!(x))) { \ + goto failure; \ + } + + while (!ctx->Done(&ptr)) { + uint32_t tag; + ptr = internal::ReadTag(ptr, &tag); + if ((tag == 0) || ((tag & 7) == 4)) { + CHK_(ptr); + ctx->SetLastTag(tag); + goto message_done; + } + ptr = UnknownFieldParse( + tag, _internal_metadata_.mutable_unknown_fields<UnknownFieldSet>(), ptr, + ctx); + CHK_(ptr); + } // while +message_done: + return ptr; +failure: + ptr = nullptr; + goto message_done; +#undef CHK_ +} + +::uint8_t* ZeroFieldsBase::_InternalSerialize( + ::uint8_t* target, io::EpsCopyOutputStream* stream) const { + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + target = internal::WireFormat::InternalSerializeUnknownFieldsToArray( + _internal_metadata_.unknown_fields<UnknownFieldSet>( + UnknownFieldSet::default_instance), + target, stream); + } + return target; +} + +void ZeroFieldsBase::MergeImpl(Message& to_param, const Message& from_param) { + auto* to = static_cast<ZeroFieldsBase*>(&to_param); + const auto* from = static_cast<const ZeroFieldsBase*>(&from_param); + GOOGLE_DCHECK_NE(from, to); + to->_internal_metadata_.MergeFrom<UnknownFieldSet>(from->_internal_metadata_); +} + +void ZeroFieldsBase::CopyImpl(Message& to_param, const Message& from_param) { + auto* to = static_cast<ZeroFieldsBase*>(&to_param); + const auto* from = static_cast<const ZeroFieldsBase*>(&from_param); + if (from == to) return; + to->_internal_metadata_.Clear<UnknownFieldSet>(); + to->_internal_metadata_.MergeFrom<UnknownFieldSet>(from->_internal_metadata_); +} + +void ZeroFieldsBase::InternalSwap(ZeroFieldsBase* other) { + _internal_metadata_.Swap<UnknownFieldSet>(&other->_internal_metadata_); +} + +} // namespace internal +} // namespace protobuf +} // namespace google + +#include <google/protobuf/port_undef.inc> diff --git a/toolkit/components/protobuf/src/google/protobuf/generated_message_bases.h b/toolkit/components/protobuf/src/google/protobuf/generated_message_bases.h new file mode 100644 index 0000000000..b295218a70 --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/generated_message_bases.h @@ -0,0 +1,87 @@ +// 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. + +// This file contains helpers for generated code. +// +// Nothing in this file should be directly referenced by users of protobufs. + +#ifndef GOOGLE_PROTOBUF_GENERATED_MESSAGE_BASES_H__ +#define GOOGLE_PROTOBUF_GENERATED_MESSAGE_BASES_H__ + +#include <google/protobuf/io/zero_copy_stream_impl.h> +#include <google/protobuf/arena.h> +#include <google/protobuf/generated_message_util.h> +#include <google/protobuf/message.h> +#include <google/protobuf/parse_context.h> + +// Must come last: +#include <google/protobuf/port_def.inc> + +namespace google { +namespace protobuf { +namespace internal { + +// To save code size, protos without any fields are derived from ZeroFieldsBase +// rather than Message. +class PROTOBUF_EXPORT ZeroFieldsBase : public Message { + public: + PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + bool IsInitialized() const final { return true; } + size_t ByteSizeLong() const final; + int GetCachedSize() const final { return _cached_size_.Get(); } + const char* _InternalParse(const char* ptr, + internal::ParseContext* ctx) final; + ::uint8_t* _InternalSerialize(::uint8_t* target, + io::EpsCopyOutputStream* stream) const final; + + protected: + constexpr ZeroFieldsBase() {} + explicit ZeroFieldsBase(Arena* arena, bool is_message_owned) + : Message(arena, is_message_owned) {} + ZeroFieldsBase(const ZeroFieldsBase&) = delete; + ZeroFieldsBase& operator=(const ZeroFieldsBase&) = delete; + ~ZeroFieldsBase() override; + + void SetCachedSize(int size) const final { _cached_size_.Set(size); } + + static void MergeImpl(Message& to, const Message& from); + static void CopyImpl(Message& to, const Message& from); + void InternalSwap(ZeroFieldsBase* other); + + mutable internal::CachedSize _cached_size_; +}; + +} // namespace internal +} // namespace protobuf +} // namespace google + +#include <google/protobuf/port_undef.inc> + +#endif // GOOGLE_PROTOBUF_GENERATED_MESSAGE_BASES_H__ diff --git a/toolkit/components/protobuf/src/google/protobuf/generated_message_reflection.cc b/toolkit/components/protobuf/src/google/protobuf/generated_message_reflection.cc new file mode 100644 index 0000000000..2a807e066b --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/generated_message_reflection.cc @@ -0,0 +1,3168 @@ +// 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. + +// Author: kenton@google.com (Kenton Varda) +// Based on original Protocol Buffers design by +// Sanjay Ghemawat, Jeff Dean, and others. + +#include <google/protobuf/generated_message_reflection.h> + +#include <algorithm> +#include <set> + +#include <google/protobuf/stubs/logging.h> +#include <google/protobuf/stubs/common.h> +#include <google/protobuf/stubs/mutex.h> +#include <google/protobuf/stubs/casts.h> +#include <google/protobuf/stubs/strutil.h> +#include <google/protobuf/descriptor.h> +#include <google/protobuf/descriptor.pb.h> +#include <google/protobuf/extension_set.h> +#include <google/protobuf/generated_message_util.h> +#include <google/protobuf/inlined_string_field.h> +#include <google/protobuf/map_field.h> +#include <google/protobuf/map_field_inl.h> +#include <google/protobuf/repeated_field.h> +#include <google/protobuf/unknown_field_set.h> + + +// clang-format off +#include <google/protobuf/port_def.inc> +// clang-format on + +#define GOOGLE_PROTOBUF_HAS_ONEOF + +using google::protobuf::internal::ArenaStringPtr; +using google::protobuf::internal::DescriptorTable; +using google::protobuf::internal::ExtensionSet; +using google::protobuf::internal::GenericTypeHandler; +using google::protobuf::internal::GetEmptyString; +using google::protobuf::internal::InlinedStringField; +using google::protobuf::internal::InternalMetadata; +using google::protobuf::internal::LazyField; +using google::protobuf::internal::MapFieldBase; +using google::protobuf::internal::MigrationSchema; +using google::protobuf::internal::OnShutdownDelete; +using google::protobuf::internal::ReflectionSchema; +using google::protobuf::internal::RepeatedPtrFieldBase; +using google::protobuf::internal::StringSpaceUsedExcludingSelfLong; +using google::protobuf::internal::WrappedMutex; + +namespace google { +namespace protobuf { + +namespace { +bool IsMapFieldInApi(const FieldDescriptor* field) { return field->is_map(); } + +#ifdef PROTOBUF_FORCE_COPY_IN_RELEASE +Message* MaybeForceCopy(Arena* arena, Message* msg) { + if (arena != nullptr || msg == nullptr) return msg; + + Message* copy = msg->New(); + copy->MergeFrom(*msg); + delete msg; + return copy; +} +#endif // PROTOBUF_FORCE_COPY_IN_RELEASE +} // anonymous namespace + +namespace internal { + +bool ParseNamedEnum(const EnumDescriptor* descriptor, ConstStringParam name, + int* value) { + const EnumValueDescriptor* d = descriptor->FindValueByName(name); + if (d == nullptr) return false; + *value = d->number(); + return true; +} + +const std::string& NameOfEnum(const EnumDescriptor* descriptor, int value) { + const EnumValueDescriptor* d = descriptor->FindValueByNumber(value); + return (d == nullptr ? GetEmptyString() : d->name()); +} + +} // namespace internal + +// =================================================================== +// Helpers for reporting usage errors (e.g. trying to use GetInt32() on +// a string field). + +namespace { + +using internal::GetConstPointerAtOffset; +using internal::GetConstRefAtOffset; +using internal::GetPointerAtOffset; + +void ReportReflectionUsageError(const Descriptor* descriptor, + const FieldDescriptor* field, + const char* method, const char* description) { + GOOGLE_LOG(FATAL) << "Protocol Buffer reflection usage error:\n" + " Method : google::protobuf::Reflection::" + << method + << "\n" + " Message type: " + << descriptor->full_name() + << "\n" + " Field : " + << field->full_name() + << "\n" + " Problem : " + << description; +} + +const char* cpptype_names_[FieldDescriptor::MAX_CPPTYPE + 1] = { + "INVALID_CPPTYPE", "CPPTYPE_INT32", "CPPTYPE_INT64", "CPPTYPE_UINT32", + "CPPTYPE_UINT64", "CPPTYPE_DOUBLE", "CPPTYPE_FLOAT", "CPPTYPE_BOOL", + "CPPTYPE_ENUM", "CPPTYPE_STRING", "CPPTYPE_MESSAGE"}; + +static void ReportReflectionUsageTypeError( + const Descriptor* descriptor, const FieldDescriptor* field, + const char* method, FieldDescriptor::CppType expected_type) { + GOOGLE_LOG(FATAL) + << "Protocol Buffer reflection usage error:\n" + " Method : google::protobuf::Reflection::" + << method + << "\n" + " Message type: " + << descriptor->full_name() + << "\n" + " Field : " + << field->full_name() + << "\n" + " Problem : Field is not the right type for this message:\n" + " Expected : " + << cpptype_names_[expected_type] + << "\n" + " Field type: " + << cpptype_names_[field->cpp_type()]; +} + +static void ReportReflectionUsageEnumTypeError( + const Descriptor* descriptor, const FieldDescriptor* field, + const char* method, const EnumValueDescriptor* value) { + GOOGLE_LOG(FATAL) << "Protocol Buffer reflection usage error:\n" + " Method : google::protobuf::Reflection::" + << method + << "\n" + " Message type: " + << descriptor->full_name() + << "\n" + " Field : " + << field->full_name() + << "\n" + " Problem : Enum value did not match field type:\n" + " Expected : " + << field->enum_type()->full_name() + << "\n" + " Actual : " + << value->full_name(); +} + +inline void CheckInvalidAccess(const internal::ReflectionSchema& schema, + const FieldDescriptor* field) { + GOOGLE_CHECK(!schema.IsFieldStripped(field)) + << "invalid access to a stripped field " << field->full_name(); +} + +#define USAGE_CHECK(CONDITION, METHOD, ERROR_DESCRIPTION) \ + if (!(CONDITION)) \ + ReportReflectionUsageError(descriptor_, field, #METHOD, ERROR_DESCRIPTION) +#define USAGE_CHECK_EQ(A, B, METHOD, ERROR_DESCRIPTION) \ + USAGE_CHECK((A) == (B), METHOD, ERROR_DESCRIPTION) +#define USAGE_CHECK_NE(A, B, METHOD, ERROR_DESCRIPTION) \ + USAGE_CHECK((A) != (B), METHOD, ERROR_DESCRIPTION) + +#define USAGE_CHECK_TYPE(METHOD, CPPTYPE) \ + if (field->cpp_type() != FieldDescriptor::CPPTYPE_##CPPTYPE) \ + ReportReflectionUsageTypeError(descriptor_, field, #METHOD, \ + FieldDescriptor::CPPTYPE_##CPPTYPE) + +#define USAGE_CHECK_ENUM_VALUE(METHOD) \ + if (value->type() != field->enum_type()) \ + ReportReflectionUsageEnumTypeError(descriptor_, field, #METHOD, value) + +#define USAGE_CHECK_MESSAGE_TYPE(METHOD) \ + USAGE_CHECK_EQ(field->containing_type(), descriptor_, METHOD, \ + "Field does not match message type."); +#define USAGE_CHECK_SINGULAR(METHOD) \ + USAGE_CHECK_NE(field->label(), FieldDescriptor::LABEL_REPEATED, METHOD, \ + "Field is repeated; the method requires a singular field.") +#define USAGE_CHECK_REPEATED(METHOD) \ + USAGE_CHECK_EQ(field->label(), FieldDescriptor::LABEL_REPEATED, METHOD, \ + "Field is singular; the method requires a repeated field.") + +#define USAGE_CHECK_ALL(METHOD, LABEL, CPPTYPE) \ + USAGE_CHECK_MESSAGE_TYPE(METHOD); \ + USAGE_CHECK_##LABEL(METHOD); \ + USAGE_CHECK_TYPE(METHOD, CPPTYPE) + +} // namespace + +// =================================================================== + +Reflection::Reflection(const Descriptor* descriptor, + const internal::ReflectionSchema& schema, + const DescriptorPool* pool, MessageFactory* factory) + : descriptor_(descriptor), + schema_(schema), + descriptor_pool_( + (pool == nullptr) ? DescriptorPool::internal_generated_pool() : pool), + message_factory_(factory), + last_non_weak_field_index_(-1) { + last_non_weak_field_index_ = descriptor_->field_count() - 1; +} + +const UnknownFieldSet& Reflection::GetUnknownFields( + const Message& message) const { + return GetInternalMetadata(message).unknown_fields<UnknownFieldSet>( + UnknownFieldSet::default_instance); +} + +UnknownFieldSet* Reflection::MutableUnknownFields(Message* message) const { + return MutableInternalMetadata(message) + ->mutable_unknown_fields<UnknownFieldSet>(); +} + +bool Reflection::IsLazyExtension(const Message& message, + const FieldDescriptor* field) const { + return field->is_extension() && + GetExtensionSet(message).HasLazy(field->number()); +} + +bool Reflection::IsLazilyVerifiedLazyField(const FieldDescriptor* field) const { + if (field->options().unverified_lazy()) return true; + + // Message fields with [lazy=true] will be eagerly verified + // (go/verified-lazy). + return field->options().lazy() && !IsEagerlyVerifiedLazyField(field); +} + +bool Reflection::IsEagerlyVerifiedLazyField( + const FieldDescriptor* field) const { + return (field->type() == FieldDescriptor::TYPE_MESSAGE && + schema_.IsEagerlyVerifiedLazyField(field)); +} + +bool Reflection::IsInlined(const FieldDescriptor* field) const { + return schema_.IsFieldInlined(field); +} + +size_t Reflection::SpaceUsedLong(const Message& message) const { + // object_size_ already includes the in-memory representation of each field + // in the message, so we only need to account for additional memory used by + // the fields. + size_t total_size = schema_.GetObjectSize(); + + total_size += GetUnknownFields(message).SpaceUsedExcludingSelfLong(); + + // If this message owns an arena, add any unused space that's been allocated. + auto* arena = Arena::InternalGetArenaForAllocation(&message); + if (arena != nullptr && Arena::InternalGetOwningArena(&message) == nullptr && + arena->InternalIsMessageOwnedArena()) { + total_size += arena->SpaceAllocated() - arena->SpaceUsed(); + } + + if (schema_.HasExtensionSet()) { + total_size += GetExtensionSet(message).SpaceUsedExcludingSelfLong(); + } + for (int i = 0; i <= last_non_weak_field_index_; i++) { + const FieldDescriptor* field = descriptor_->field(i); + if (field->is_repeated()) { + switch (field->cpp_type()) { +#define HANDLE_TYPE(UPPERCASE, LOWERCASE) \ + case FieldDescriptor::CPPTYPE_##UPPERCASE: \ + total_size += GetRaw<RepeatedField<LOWERCASE> >(message, field) \ + .SpaceUsedExcludingSelfLong(); \ + break + + HANDLE_TYPE(INT32, int32_t); + HANDLE_TYPE(INT64, int64_t); + HANDLE_TYPE(UINT32, uint32_t); + HANDLE_TYPE(UINT64, uint64_t); + HANDLE_TYPE(DOUBLE, double); + HANDLE_TYPE(FLOAT, float); + HANDLE_TYPE(BOOL, bool); + HANDLE_TYPE(ENUM, int); +#undef HANDLE_TYPE + + case FieldDescriptor::CPPTYPE_STRING: + switch (field->options().ctype()) { + default: // TODO(kenton): Support other string reps. + case FieldOptions::STRING: + total_size += + GetRaw<RepeatedPtrField<std::string> >(message, field) + .SpaceUsedExcludingSelfLong(); + break; + } + break; + + case FieldDescriptor::CPPTYPE_MESSAGE: + if (IsMapFieldInApi(field)) { + total_size += GetRaw<internal::MapFieldBase>(message, field) + .SpaceUsedExcludingSelfLong(); + } else { + // We don't know which subclass of RepeatedPtrFieldBase the type is, + // so we use RepeatedPtrFieldBase directly. + total_size += + GetRaw<RepeatedPtrFieldBase>(message, field) + .SpaceUsedExcludingSelfLong<GenericTypeHandler<Message> >(); + } + + break; + } + } else { + if (schema_.InRealOneof(field) && !HasOneofField(message, field)) { + continue; + } + switch (field->cpp_type()) { + case FieldDescriptor::CPPTYPE_INT32: + case FieldDescriptor::CPPTYPE_INT64: + case FieldDescriptor::CPPTYPE_UINT32: + case FieldDescriptor::CPPTYPE_UINT64: + case FieldDescriptor::CPPTYPE_DOUBLE: + case FieldDescriptor::CPPTYPE_FLOAT: + case FieldDescriptor::CPPTYPE_BOOL: + case FieldDescriptor::CPPTYPE_ENUM: + // Field is inline, so we've already counted it. + break; + + case FieldDescriptor::CPPTYPE_STRING: { + switch (field->options().ctype()) { + default: // TODO(kenton): Support other string reps. + case FieldOptions::STRING: + if (IsInlined(field)) { + const std::string* ptr = + &GetField<InlinedStringField>(message, field).GetNoArena(); + total_size += StringSpaceUsedExcludingSelfLong(*ptr); + } else { + // Initially, the string points to the default value stored + // in the prototype. Only count the string if it has been + // changed from the default value. + // Except oneof fields, those never point to a default instance, + // and there is no default instance to point to. + const auto& str = GetField<ArenaStringPtr>(message, field); + if (!str.IsDefault() || schema_.InRealOneof(field)) { + // string fields are represented by just a pointer, so also + // include sizeof(string) as well. + total_size += sizeof(std::string) + + StringSpaceUsedExcludingSelfLong(str.Get()); + } + } + break; + } + break; + } + + case FieldDescriptor::CPPTYPE_MESSAGE: + if (schema_.IsDefaultInstance(message)) { + // For singular fields, the prototype just stores a pointer to the + // external type's prototype, so there is no extra memory usage. + } else { + const Message* sub_message = GetRaw<const Message*>(message, field); + if (sub_message != nullptr) { + total_size += sub_message->SpaceUsedLong(); + } + } + break; + } + } + } + return total_size; +} + +namespace { + +template <bool unsafe_shallow_swap> +struct OneofFieldMover { + template <typename FromType, typename ToType> + void operator()(const FieldDescriptor* field, FromType* from, ToType* to) { + switch (field->cpp_type()) { + case FieldDescriptor::CPPTYPE_INT32: + to->SetInt32(from->GetInt32()); + break; + case FieldDescriptor::CPPTYPE_INT64: + to->SetInt64(from->GetInt64()); + break; + case FieldDescriptor::CPPTYPE_UINT32: + to->SetUint32(from->GetUint32()); + break; + case FieldDescriptor::CPPTYPE_UINT64: + to->SetUint64(from->GetUint64()); + break; + case FieldDescriptor::CPPTYPE_FLOAT: + to->SetFloat(from->GetFloat()); + break; + case FieldDescriptor::CPPTYPE_DOUBLE: + to->SetDouble(from->GetDouble()); + break; + case FieldDescriptor::CPPTYPE_BOOL: + to->SetBool(from->GetBool()); + break; + case FieldDescriptor::CPPTYPE_ENUM: + to->SetEnum(from->GetEnum()); + break; + case FieldDescriptor::CPPTYPE_MESSAGE: + if (!unsafe_shallow_swap) { + to->SetMessage(from->GetMessage()); + } else { + to->UnsafeSetMessage(from->UnsafeGetMessage()); + } + break; + case FieldDescriptor::CPPTYPE_STRING: + if (!unsafe_shallow_swap) { + to->SetString(from->GetString()); + break; + } + switch (field->options().ctype()) { + default: + case FieldOptions::STRING: { + to->SetArenaStringPtr(from->GetArenaStringPtr()); + break; + } + } + break; + default: + GOOGLE_LOG(FATAL) << "unimplemented type: " << field->cpp_type(); + } + if (unsafe_shallow_swap) { + // Not clearing oneof case after move may cause unwanted "ClearOneof" + // where the residual message or string value is deleted and causes + // use-after-free (only for unsafe swap). + from->ClearOneofCase(); + } + } +}; + +} // namespace + +namespace internal { + +class SwapFieldHelper { + public: + template <bool unsafe_shallow_swap> + static void SwapRepeatedStringField(const Reflection* r, Message* lhs, + Message* rhs, + const FieldDescriptor* field); + + template <bool unsafe_shallow_swap> + static void SwapInlinedStrings(const Reflection* r, Message* lhs, + Message* rhs, const FieldDescriptor* field); + + template <bool unsafe_shallow_swap> + static void SwapNonInlinedStrings(const Reflection* r, Message* lhs, + Message* rhs, const FieldDescriptor* field); + + template <bool unsafe_shallow_swap> + static void SwapStringField(const Reflection* r, Message* lhs, Message* rhs, + const FieldDescriptor* field); + + static void SwapArenaStringPtr(ArenaStringPtr* lhs, Arena* lhs_arena, + ArenaStringPtr* rhs, Arena* rhs_arena); + + template <bool unsafe_shallow_swap> + static void SwapRepeatedMessageField(const Reflection* r, Message* lhs, + Message* rhs, + const FieldDescriptor* field); + + template <bool unsafe_shallow_swap> + static void SwapMessageField(const Reflection* r, Message* lhs, Message* rhs, + const FieldDescriptor* field); + + static void SwapMessage(const Reflection* r, Message* lhs, Arena* lhs_arena, + Message* rhs, Arena* rhs_arena, + const FieldDescriptor* field); + + static void SwapNonMessageNonStringField(const Reflection* r, Message* lhs, + Message* rhs, + const FieldDescriptor* field); +}; + +template <bool unsafe_shallow_swap> +void SwapFieldHelper::SwapRepeatedStringField(const Reflection* r, Message* lhs, + Message* rhs, + const FieldDescriptor* field) { + switch (field->options().ctype()) { + default: + case FieldOptions::STRING: { + auto* lhs_string = r->MutableRaw<RepeatedPtrFieldBase>(lhs, field); + auto* rhs_string = r->MutableRaw<RepeatedPtrFieldBase>(rhs, field); + if (unsafe_shallow_swap) { + lhs_string->InternalSwap(rhs_string); + } else { + lhs_string->Swap<GenericTypeHandler<std::string>>(rhs_string); + } + break; + } + } +} + +template <bool unsafe_shallow_swap> +void SwapFieldHelper::SwapInlinedStrings(const Reflection* r, Message* lhs, + Message* rhs, + const FieldDescriptor* field) { + // Inlined string field. + Arena* lhs_arena = lhs->GetArenaForAllocation(); + Arena* rhs_arena = rhs->GetArenaForAllocation(); + auto* lhs_string = r->MutableRaw<InlinedStringField>(lhs, field); + auto* rhs_string = r->MutableRaw<InlinedStringField>(rhs, field); + uint32_t index = r->schema_.InlinedStringIndex(field); + GOOGLE_DCHECK_GT(index, 0); + uint32_t* lhs_array = r->MutableInlinedStringDonatedArray(lhs); + uint32_t* rhs_array = r->MutableInlinedStringDonatedArray(rhs); + uint32_t* lhs_state = &lhs_array[index / 32]; + uint32_t* rhs_state = &rhs_array[index / 32]; + bool lhs_arena_dtor_registered = (lhs_array[0] & 0x1u) == 0; + bool rhs_arena_dtor_registered = (rhs_array[0] & 0x1u) == 0; + const uint32_t mask = ~(static_cast<uint32_t>(1) << (index % 32)); + if (unsafe_shallow_swap || lhs_arena == rhs_arena) { + InlinedStringField::InternalSwap(lhs_string, lhs_arena, + lhs_arena_dtor_registered, lhs, rhs_string, + rhs_arena, rhs_arena_dtor_registered, rhs); + } else { + const std::string temp = lhs_string->Get(); + lhs_string->Set(rhs_string->Get(), lhs_arena, + r->IsInlinedStringDonated(*lhs, field), lhs_state, mask, + lhs); + rhs_string->Set(temp, rhs_arena, r->IsInlinedStringDonated(*rhs, field), + rhs_state, mask, rhs); + } +} + +template <bool unsafe_shallow_swap> +void SwapFieldHelper::SwapNonInlinedStrings(const Reflection* r, Message* lhs, + Message* rhs, + const FieldDescriptor* field) { + ArenaStringPtr* lhs_string = r->MutableRaw<ArenaStringPtr>(lhs, field); + ArenaStringPtr* rhs_string = r->MutableRaw<ArenaStringPtr>(rhs, field); + if (unsafe_shallow_swap) { + ArenaStringPtr::UnsafeShallowSwap(lhs_string, rhs_string); + } else { + SwapFieldHelper::SwapArenaStringPtr( + lhs_string, lhs->GetArenaForAllocation(), // + rhs_string, rhs->GetArenaForAllocation()); + } +} + +template <bool unsafe_shallow_swap> +void SwapFieldHelper::SwapStringField(const Reflection* r, Message* lhs, + Message* rhs, + const FieldDescriptor* field) { + switch (field->options().ctype()) { + default: + case FieldOptions::STRING: { + if (r->IsInlined(field)) { + SwapFieldHelper::SwapInlinedStrings<unsafe_shallow_swap>(r, lhs, rhs, + field); + } else { + SwapFieldHelper::SwapNonInlinedStrings<unsafe_shallow_swap>(r, lhs, rhs, + field); + } + break; + } + } +} + +void SwapFieldHelper::SwapArenaStringPtr(ArenaStringPtr* lhs, Arena* lhs_arena, + ArenaStringPtr* rhs, + Arena* rhs_arena) { + if (lhs_arena == rhs_arena) { + ArenaStringPtr::InternalSwap(lhs, lhs_arena, rhs, rhs_arena); + } else if (lhs->IsDefault() && rhs->IsDefault()) { + // Nothing to do. + } else if (lhs->IsDefault()) { + lhs->Set(rhs->Get(), lhs_arena); + // rhs needs to be destroyed before overwritten. + rhs->Destroy(); + rhs->InitDefault(); + } else if (rhs->IsDefault()) { + rhs->Set(lhs->Get(), rhs_arena); + // lhs needs to be destroyed before overwritten. + lhs->Destroy(); + lhs->InitDefault(); + } else { + std::string temp = lhs->Get(); + lhs->Set(rhs->Get(), lhs_arena); + rhs->Set(std::move(temp), rhs_arena); + } +} + +template <bool unsafe_shallow_swap> +void SwapFieldHelper::SwapRepeatedMessageField(const Reflection* r, + Message* lhs, Message* rhs, + const FieldDescriptor* field) { + if (IsMapFieldInApi(field)) { + auto* lhs_map = r->MutableRaw<MapFieldBase>(lhs, field); + auto* rhs_map = r->MutableRaw<MapFieldBase>(rhs, field); + if (unsafe_shallow_swap) { + lhs_map->UnsafeShallowSwap(rhs_map); + } else { + lhs_map->Swap(rhs_map); + } + } else { + auto* lhs_rm = r->MutableRaw<RepeatedPtrFieldBase>(lhs, field); + auto* rhs_rm = r->MutableRaw<RepeatedPtrFieldBase>(rhs, field); + if (unsafe_shallow_swap) { + lhs_rm->InternalSwap(rhs_rm); + } else { + lhs_rm->Swap<GenericTypeHandler<Message>>(rhs_rm); + } + } +} + +template <bool unsafe_shallow_swap> +void SwapFieldHelper::SwapMessageField(const Reflection* r, Message* lhs, + Message* rhs, + const FieldDescriptor* field) { + if (unsafe_shallow_swap) { + std::swap(*r->MutableRaw<Message*>(lhs, field), + *r->MutableRaw<Message*>(rhs, field)); + } else { + SwapMessage(r, lhs, lhs->GetArenaForAllocation(), rhs, + rhs->GetArenaForAllocation(), field); + } +} + +void SwapFieldHelper::SwapMessage(const Reflection* r, Message* lhs, + Arena* lhs_arena, Message* rhs, + Arena* rhs_arena, + const FieldDescriptor* field) { + Message** lhs_sub = r->MutableRaw<Message*>(lhs, field); + Message** rhs_sub = r->MutableRaw<Message*>(rhs, field); + + if (*lhs_sub == *rhs_sub) return; + +#ifdef PROTOBUF_FORCE_COPY_IN_SWAP + if (lhs_arena != nullptr && lhs_arena == rhs_arena) { +#else // PROTOBUF_FORCE_COPY_IN_SWAP + if (lhs_arena == rhs_arena) { +#endif // !PROTOBUF_FORCE_COPY_IN_SWAP + std::swap(*lhs_sub, *rhs_sub); + return; + } + + if (*lhs_sub != nullptr && *rhs_sub != nullptr) { + (*lhs_sub)->GetReflection()->Swap(*lhs_sub, *rhs_sub); + } else if (*lhs_sub == nullptr && r->HasBit(*rhs, field)) { + *lhs_sub = (*rhs_sub)->New(lhs_arena); + (*lhs_sub)->CopyFrom(**rhs_sub); + r->ClearField(rhs, field); + // Ensures has bit is unchanged after ClearField. + r->SetBit(rhs, field); + } else if (*rhs_sub == nullptr && r->HasBit(*lhs, field)) { + *rhs_sub = (*lhs_sub)->New(rhs_arena); + (*rhs_sub)->CopyFrom(**lhs_sub); + r->ClearField(lhs, field); + // Ensures has bit is unchanged after ClearField. + r->SetBit(lhs, field); + } +} + +void SwapFieldHelper::SwapNonMessageNonStringField( + const Reflection* r, Message* lhs, Message* rhs, + const FieldDescriptor* field) { + switch (field->cpp_type()) { +#define SWAP_VALUES(CPPTYPE, TYPE) \ + case FieldDescriptor::CPPTYPE_##CPPTYPE: \ + std::swap(*r->MutableRaw<TYPE>(lhs, field), \ + *r->MutableRaw<TYPE>(rhs, field)); \ + break; + + SWAP_VALUES(INT32, int32_t); + SWAP_VALUES(INT64, int64_t); + SWAP_VALUES(UINT32, uint32_t); + SWAP_VALUES(UINT64, uint64_t); + SWAP_VALUES(FLOAT, float); + SWAP_VALUES(DOUBLE, double); + SWAP_VALUES(BOOL, bool); + SWAP_VALUES(ENUM, int); +#undef SWAP_VALUES + default: + GOOGLE_LOG(FATAL) << "Unimplemented type: " << field->cpp_type(); + } +} + +} // namespace internal + +void Reflection::SwapField(Message* message1, Message* message2, + const FieldDescriptor* field) const { + if (field->is_repeated()) { + switch (field->cpp_type()) { +#define SWAP_ARRAYS(CPPTYPE, TYPE) \ + case FieldDescriptor::CPPTYPE_##CPPTYPE: \ + MutableRaw<RepeatedField<TYPE> >(message1, field) \ + ->Swap(MutableRaw<RepeatedField<TYPE> >(message2, field)); \ + break; + + SWAP_ARRAYS(INT32, int32_t); + SWAP_ARRAYS(INT64, int64_t); + SWAP_ARRAYS(UINT32, uint32_t); + SWAP_ARRAYS(UINT64, uint64_t); + SWAP_ARRAYS(FLOAT, float); + SWAP_ARRAYS(DOUBLE, double); + SWAP_ARRAYS(BOOL, bool); + SWAP_ARRAYS(ENUM, int); +#undef SWAP_ARRAYS + + case FieldDescriptor::CPPTYPE_STRING: + internal::SwapFieldHelper::SwapRepeatedStringField<false>( + this, message1, message2, field); + break; + case FieldDescriptor::CPPTYPE_MESSAGE: + internal::SwapFieldHelper::SwapRepeatedMessageField<false>( + this, message1, message2, field); + break; + + default: + GOOGLE_LOG(FATAL) << "Unimplemented type: " << field->cpp_type(); + } + } else { + switch (field->cpp_type()) { + case FieldDescriptor::CPPTYPE_MESSAGE: + internal::SwapFieldHelper::SwapMessageField<false>(this, message1, + message2, field); + break; + + case FieldDescriptor::CPPTYPE_STRING: + internal::SwapFieldHelper::SwapStringField<false>(this, message1, + message2, field); + break; + default: + internal::SwapFieldHelper::SwapNonMessageNonStringField( + this, message1, message2, field); + } + } +} + +void Reflection::UnsafeShallowSwapField(Message* message1, Message* message2, + const FieldDescriptor* field) const { + if (!field->is_repeated()) { + if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { + internal::SwapFieldHelper::SwapMessageField<true>(this, message1, + message2, field); + } else if (field->cpp_type() == FieldDescriptor::CPPTYPE_STRING) { + internal::SwapFieldHelper::SwapStringField<true>(this, message1, message2, + field); + } else { + internal::SwapFieldHelper::SwapNonMessageNonStringField(this, message1, + message2, field); + } + return; + } + + switch (field->cpp_type()) { +#define SHALLOW_SWAP_ARRAYS(CPPTYPE, TYPE) \ + case FieldDescriptor::CPPTYPE_##CPPTYPE: \ + MutableRaw<RepeatedField<TYPE>>(message1, field) \ + ->InternalSwap(MutableRaw<RepeatedField<TYPE>>(message2, field)); \ + break; + + SHALLOW_SWAP_ARRAYS(INT32, int32_t); + SHALLOW_SWAP_ARRAYS(INT64, int64_t); + SHALLOW_SWAP_ARRAYS(UINT32, uint32_t); + SHALLOW_SWAP_ARRAYS(UINT64, uint64_t); + SHALLOW_SWAP_ARRAYS(FLOAT, float); + SHALLOW_SWAP_ARRAYS(DOUBLE, double); + SHALLOW_SWAP_ARRAYS(BOOL, bool); + SHALLOW_SWAP_ARRAYS(ENUM, int); +#undef SHALLOW_SWAP_ARRAYS + + case FieldDescriptor::CPPTYPE_STRING: + internal::SwapFieldHelper::SwapRepeatedStringField<true>(this, message1, + message2, field); + break; + case FieldDescriptor::CPPTYPE_MESSAGE: + internal::SwapFieldHelper::SwapRepeatedMessageField<true>( + this, message1, message2, field); + break; + + default: + GOOGLE_LOG(FATAL) << "Unimplemented type: " << field->cpp_type(); + } +} + +// Swaps oneof field between lhs and rhs. If unsafe_shallow_swap is true, it +// directly swaps oneof values; otherwise, it may involve copy/delete. Note that +// two messages may have different oneof cases. So, it has to be done in three +// steps (i.e. lhs -> temp, rhs -> lhs, temp -> rhs). +template <bool unsafe_shallow_swap> +void Reflection::SwapOneofField(Message* lhs, Message* rhs, + const OneofDescriptor* oneof_descriptor) const { + // Wraps a local variable to temporarily store oneof value. + struct LocalVarWrapper { +#define LOCAL_VAR_ACCESSOR(type, var, name) \ + type Get##name() const { return oneof_val.type_##var; } \ + void Set##name(type v) { oneof_val.type_##var = v; } + + LOCAL_VAR_ACCESSOR(int32_t, int32, Int32); + LOCAL_VAR_ACCESSOR(int64_t, int64, Int64); + LOCAL_VAR_ACCESSOR(uint32_t, uint32, Uint32); + LOCAL_VAR_ACCESSOR(uint64_t, uint64, Uint64); + LOCAL_VAR_ACCESSOR(float, float, Float); + LOCAL_VAR_ACCESSOR(double, double, Double); + LOCAL_VAR_ACCESSOR(bool, bool, Bool); + LOCAL_VAR_ACCESSOR(int, enum, Enum); + LOCAL_VAR_ACCESSOR(Message*, message, Message); + LOCAL_VAR_ACCESSOR(ArenaStringPtr, arena_string_ptr, ArenaStringPtr); + const std::string& GetString() const { return string_val; } + void SetString(const std::string& v) { string_val = v; } + Message* UnsafeGetMessage() const { return GetMessage(); } + void UnsafeSetMessage(Message* v) { SetMessage(v); } + void ClearOneofCase() {} + + union { + int32_t type_int32; + int64_t type_int64; + uint32_t type_uint32; + uint64_t type_uint64; + float type_float; + double type_double; + bool type_bool; + int type_enum; + Message* type_message; + internal::ArenaStringPtr type_arena_string_ptr; + } oneof_val; + + // std::string cannot be in union. + std::string string_val; + }; + + // Wraps a message pointer to read and write a field. + struct MessageWrapper { +#define MESSAGE_FIELD_ACCESSOR(type, var, name) \ + type Get##name() const { \ + return reflection->GetField<type>(*message, field); \ + } \ + void Set##name(type v) { reflection->SetField<type>(message, field, v); } + + MESSAGE_FIELD_ACCESSOR(int32_t, int32, Int32); + MESSAGE_FIELD_ACCESSOR(int64_t, int64, Int64); + MESSAGE_FIELD_ACCESSOR(uint32_t, uint32, Uint32); + MESSAGE_FIELD_ACCESSOR(uint64_t, uint64, Uint64); + MESSAGE_FIELD_ACCESSOR(float, float, Float); + MESSAGE_FIELD_ACCESSOR(double, double, Double); + MESSAGE_FIELD_ACCESSOR(bool, bool, Bool); + MESSAGE_FIELD_ACCESSOR(int, enum, Enum); + MESSAGE_FIELD_ACCESSOR(ArenaStringPtr, arena_string_ptr, ArenaStringPtr); + std::string GetString() const { + return reflection->GetString(*message, field); + } + void SetString(const std::string& v) { + reflection->SetString(message, field, v); + } + Message* GetMessage() const { + return reflection->ReleaseMessage(message, field); + } + void SetMessage(Message* v) { + reflection->SetAllocatedMessage(message, v, field); + } + Message* UnsafeGetMessage() const { + return reflection->UnsafeArenaReleaseMessage(message, field); + } + void UnsafeSetMessage(Message* v) { + reflection->UnsafeArenaSetAllocatedMessage(message, v, field); + } + void ClearOneofCase() { + *reflection->MutableOneofCase(message, field->containing_oneof()) = 0; + } + + const Reflection* reflection; + Message* message; + const FieldDescriptor* field; + }; + + GOOGLE_DCHECK(!oneof_descriptor->is_synthetic()); + uint32_t oneof_case_lhs = GetOneofCase(*lhs, oneof_descriptor); + uint32_t oneof_case_rhs = GetOneofCase(*rhs, oneof_descriptor); + + LocalVarWrapper temp; + MessageWrapper lhs_wrapper, rhs_wrapper; + const FieldDescriptor* field_lhs = nullptr; + OneofFieldMover<unsafe_shallow_swap> mover; + // lhs --> temp + if (oneof_case_lhs > 0) { + field_lhs = descriptor_->FindFieldByNumber(oneof_case_lhs); + lhs_wrapper = {this, lhs, field_lhs}; + mover(field_lhs, &lhs_wrapper, &temp); + } + // rhs --> lhs + if (oneof_case_rhs > 0) { + const FieldDescriptor* f = descriptor_->FindFieldByNumber(oneof_case_rhs); + lhs_wrapper = {this, lhs, f}; + rhs_wrapper = {this, rhs, f}; + mover(f, &rhs_wrapper, &lhs_wrapper); + } else if (!unsafe_shallow_swap) { + ClearOneof(lhs, oneof_descriptor); + } + // temp --> rhs + if (oneof_case_lhs > 0) { + rhs_wrapper = {this, rhs, field_lhs}; + mover(field_lhs, &temp, &rhs_wrapper); + } else if (!unsafe_shallow_swap) { + ClearOneof(rhs, oneof_descriptor); + } + + if (unsafe_shallow_swap) { + *MutableOneofCase(lhs, oneof_descriptor) = oneof_case_rhs; + *MutableOneofCase(rhs, oneof_descriptor) = oneof_case_lhs; + } +} + +void Reflection::Swap(Message* message1, Message* message2) const { + if (message1 == message2) return; + + // TODO(kenton): Other Reflection methods should probably check this too. + GOOGLE_CHECK_EQ(message1->GetReflection(), this) + << "First argument to Swap() (of type \"" + << message1->GetDescriptor()->full_name() + << "\") is not compatible with this reflection object (which is for type " + "\"" + << descriptor_->full_name() + << "\"). Note that the exact same class is required; not just the same " + "descriptor."; + GOOGLE_CHECK_EQ(message2->GetReflection(), this) + << "Second argument to Swap() (of type \"" + << message2->GetDescriptor()->full_name() + << "\") is not compatible with this reflection object (which is for type " + "\"" + << descriptor_->full_name() + << "\"). Note that the exact same class is required; not just the same " + "descriptor."; + + // Check that both messages are in the same arena (or both on the heap). We + // need to copy all data if not, due to ownership semantics. +#ifdef PROTOBUF_FORCE_COPY_IN_SWAP + if (message1->GetOwningArena() == nullptr || + message1->GetOwningArena() != message2->GetOwningArena()) { +#else // PROTOBUF_FORCE_COPY_IN_SWAP + if (message1->GetOwningArena() != message2->GetOwningArena()) { +#endif // !PROTOBUF_FORCE_COPY_IN_SWAP + // One of the two is guaranteed to have an arena. Switch things around + // to guarantee that message1 has an arena. + Arena* arena = message1->GetOwningArena(); + if (arena == nullptr) { + arena = message2->GetOwningArena(); + std::swap(message1, message2); // Swapping names for pointers! + } + + Message* temp = message1->New(arena); + temp->MergeFrom(*message2); + message2->CopyFrom(*message1); +#ifdef PROTOBUF_FORCE_COPY_IN_SWAP + message1->CopyFrom(*temp); + if (arena == nullptr) delete temp; +#else // PROTOBUF_FORCE_COPY_IN_SWAP + Swap(message1, temp); +#endif // !PROTOBUF_FORCE_COPY_IN_SWAP + return; + } + + GOOGLE_DCHECK_EQ(message1->GetOwningArena(), message2->GetOwningArena()); + + UnsafeArenaSwap(message1, message2); +} + +template <bool unsafe_shallow_swap> +void Reflection::SwapFieldsImpl( + Message* message1, Message* message2, + const std::vector<const FieldDescriptor*>& fields) const { + if (message1 == message2) return; + + // TODO(kenton): Other Reflection methods should probably check this too. + GOOGLE_CHECK_EQ(message1->GetReflection(), this) + << "First argument to SwapFields() (of type \"" + << message1->GetDescriptor()->full_name() + << "\") is not compatible with this reflection object (which is for type " + "\"" + << descriptor_->full_name() + << "\"). Note that the exact same class is required; not just the same " + "descriptor."; + GOOGLE_CHECK_EQ(message2->GetReflection(), this) + << "Second argument to SwapFields() (of type \"" + << message2->GetDescriptor()->full_name() + << "\") is not compatible with this reflection object (which is for type " + "\"" + << descriptor_->full_name() + << "\"). Note that the exact same class is required; not just the same " + "descriptor."; + + std::set<int> swapped_oneof; + + GOOGLE_DCHECK(!unsafe_shallow_swap || message1->GetArenaForAllocation() == + message2->GetArenaForAllocation()); + + const Message* prototype = + message_factory_->GetPrototype(message1->GetDescriptor()); + for (const auto* field : fields) { + CheckInvalidAccess(schema_, field); + if (field->is_extension()) { + if (unsafe_shallow_swap) { + MutableExtensionSet(message1)->UnsafeShallowSwapExtension( + MutableExtensionSet(message2), field->number()); + } else { + MutableExtensionSet(message1)->SwapExtension( + prototype, MutableExtensionSet(message2), field->number()); + } + } else { + if (schema_.InRealOneof(field)) { + int oneof_index = field->containing_oneof()->index(); + // Only swap the oneof field once. + if (swapped_oneof.find(oneof_index) != swapped_oneof.end()) { + continue; + } + swapped_oneof.insert(oneof_index); + SwapOneofField<unsafe_shallow_swap>(message1, message2, + field->containing_oneof()); + } else { + // Swap field. + if (unsafe_shallow_swap) { + UnsafeShallowSwapField(message1, message2, field); + } else { + SwapField(message1, message2, field); + } + // Swap has bit for non-repeated fields. We have already checked for + // oneof already. This has to be done after SwapField, because SwapField + // may depend on the information in has bits. + if (!field->is_repeated()) { + SwapBit(message1, message2, field); + if (field->options().ctype() == FieldOptions::STRING && + IsInlined(field)) { + GOOGLE_DCHECK(!unsafe_shallow_swap || + message1->GetArenaForAllocation() == + message2->GetArenaForAllocation()); + SwapInlinedStringDonated(message1, message2, field); + } + } + } + } + } +} + +void Reflection::SwapFields( + Message* message1, Message* message2, + const std::vector<const FieldDescriptor*>& fields) const { + SwapFieldsImpl<false>(message1, message2, fields); +} + +void Reflection::UnsafeShallowSwapFields( + Message* message1, Message* message2, + const std::vector<const FieldDescriptor*>& fields) const { + SwapFieldsImpl<true>(message1, message2, fields); +} + +void Reflection::UnsafeArenaSwapFields( + Message* lhs, Message* rhs, + const std::vector<const FieldDescriptor*>& fields) const { + GOOGLE_DCHECK_EQ(lhs->GetArenaForAllocation(), rhs->GetArenaForAllocation()); + UnsafeShallowSwapFields(lhs, rhs, fields); +} + +// ------------------------------------------------------------------- + +bool Reflection::HasField(const Message& message, + const FieldDescriptor* field) const { + USAGE_CHECK_MESSAGE_TYPE(HasField); + USAGE_CHECK_SINGULAR(HasField); + CheckInvalidAccess(schema_, field); + + if (field->is_extension()) { + return GetExtensionSet(message).Has(field->number()); + } else { + if (schema_.InRealOneof(field)) { + return HasOneofField(message, field); + } else { + return HasBit(message, field); + } + } +} + +void Reflection::UnsafeArenaSwap(Message* lhs, Message* rhs) const { + if (lhs == rhs) return; + + MutableInternalMetadata(lhs)->InternalSwap(MutableInternalMetadata(rhs)); + + for (int i = 0; i <= last_non_weak_field_index_; i++) { + const FieldDescriptor* field = descriptor_->field(i); + if (schema_.InRealOneof(field)) continue; + if (schema_.IsFieldStripped(field)) continue; + UnsafeShallowSwapField(lhs, rhs, field); + } + const int oneof_decl_count = descriptor_->oneof_decl_count(); + for (int i = 0; i < oneof_decl_count; i++) { + const OneofDescriptor* oneof = descriptor_->oneof_decl(i); + if (!oneof->is_synthetic()) { + SwapOneofField<true>(lhs, rhs, oneof); + } + } + + // Swapping bits need to happen after swapping fields, because the latter may + // depend on the has bit information. + if (schema_.HasHasbits()) { + uint32_t* lhs_has_bits = MutableHasBits(lhs); + uint32_t* rhs_has_bits = MutableHasBits(rhs); + + int fields_with_has_bits = 0; + for (int i = 0; i < descriptor_->field_count(); i++) { + const FieldDescriptor* field = descriptor_->field(i); + if (field->is_repeated() || schema_.InRealOneof(field)) { + continue; + } + fields_with_has_bits++; + } + + int has_bits_size = (fields_with_has_bits + 31) / 32; + + for (int i = 0; i < has_bits_size; i++) { + std::swap(lhs_has_bits[i], rhs_has_bits[i]); + } + } + + if (schema_.HasInlinedString()) { + uint32_t* lhs_donated_array = MutableInlinedStringDonatedArray(lhs); + uint32_t* rhs_donated_array = MutableInlinedStringDonatedArray(rhs); + int inlined_string_count = 0; + for (int i = 0; i < descriptor_->field_count(); i++) { + const FieldDescriptor* field = descriptor_->field(i); + if (field->is_extension() || field->is_repeated() || + schema_.InRealOneof(field) || + field->options().ctype() != FieldOptions::STRING || + !IsInlined(field)) { + continue; + } + inlined_string_count++; + } + + int donated_array_size = inlined_string_count == 0 + ? 0 + // One extra bit for the arena dtor tracking. + : (inlined_string_count + 1 + 31) / 32; + GOOGLE_CHECK_EQ((lhs_donated_array[0] & 0x1u) == 0, + (rhs_donated_array[0] & 0x1u) == 0); + for (int i = 0; i < donated_array_size; i++) { + std::swap(lhs_donated_array[i], rhs_donated_array[i]); + } + } + + if (schema_.HasExtensionSet()) { + MutableExtensionSet(lhs)->InternalSwap(MutableExtensionSet(rhs)); + } +} + +int Reflection::FieldSize(const Message& message, + const FieldDescriptor* field) const { + USAGE_CHECK_MESSAGE_TYPE(FieldSize); + USAGE_CHECK_REPEATED(FieldSize); + CheckInvalidAccess(schema_, field); + + if (field->is_extension()) { + return GetExtensionSet(message).ExtensionSize(field->number()); + } else { + switch (field->cpp_type()) { +#define HANDLE_TYPE(UPPERCASE, LOWERCASE) \ + case FieldDescriptor::CPPTYPE_##UPPERCASE: \ + return GetRaw<RepeatedField<LOWERCASE> >(message, field).size() + + HANDLE_TYPE(INT32, int32_t); + HANDLE_TYPE(INT64, int64_t); + HANDLE_TYPE(UINT32, uint32_t); + HANDLE_TYPE(UINT64, uint64_t); + HANDLE_TYPE(DOUBLE, double); + HANDLE_TYPE(FLOAT, float); + HANDLE_TYPE(BOOL, bool); + HANDLE_TYPE(ENUM, int); +#undef HANDLE_TYPE + + case FieldDescriptor::CPPTYPE_STRING: + case FieldDescriptor::CPPTYPE_MESSAGE: + if (IsMapFieldInApi(field)) { + const internal::MapFieldBase& map = + GetRaw<MapFieldBase>(message, field); + if (map.IsRepeatedFieldValid()) { + return map.GetRepeatedField().size(); + } else { + // No need to materialize the repeated field if it is out of sync: + // its size will be the same as the map's size. + return map.size(); + } + } else { + return GetRaw<RepeatedPtrFieldBase>(message, field).size(); + } + } + + GOOGLE_LOG(FATAL) << "Can't get here."; + return 0; + } +} + +void Reflection::ClearField(Message* message, + const FieldDescriptor* field) const { + USAGE_CHECK_MESSAGE_TYPE(ClearField); + CheckInvalidAccess(schema_, field); + + if (field->is_extension()) { + MutableExtensionSet(message)->ClearExtension(field->number()); + } else if (!field->is_repeated()) { + if (schema_.InRealOneof(field)) { + ClearOneofField(message, field); + return; + } + if (HasBit(*message, field)) { + ClearBit(message, field); + + // We need to set the field back to its default value. + switch (field->cpp_type()) { +#define CLEAR_TYPE(CPPTYPE, TYPE) \ + case FieldDescriptor::CPPTYPE_##CPPTYPE: \ + *MutableRaw<TYPE>(message, field) = field->default_value_##TYPE(); \ + break; + + CLEAR_TYPE(INT32, int32_t); + CLEAR_TYPE(INT64, int64_t); + CLEAR_TYPE(UINT32, uint32_t); + CLEAR_TYPE(UINT64, uint64_t); + CLEAR_TYPE(FLOAT, float); + CLEAR_TYPE(DOUBLE, double); + CLEAR_TYPE(BOOL, bool); +#undef CLEAR_TYPE + + case FieldDescriptor::CPPTYPE_ENUM: + *MutableRaw<int>(message, field) = + field->default_value_enum()->number(); + break; + + case FieldDescriptor::CPPTYPE_STRING: { + switch (field->options().ctype()) { + default: // TODO(kenton): Support other string reps. + case FieldOptions::STRING: + if (IsInlined(field)) { + // Currently, string with default value can't be inlined. So we + // don't have to handle default value here. + MutableRaw<InlinedStringField>(message, field)->ClearToEmpty(); + } else { + auto* str = MutableRaw<ArenaStringPtr>(message, field); + str->Destroy(); + str->InitDefault(); + } + break; + } + break; + } + + case FieldDescriptor::CPPTYPE_MESSAGE: + if (schema_.HasBitIndex(field) == static_cast<uint32_t>(-1)) { + // Proto3 does not have has-bits and we need to set a message field + // to nullptr in order to indicate its un-presence. + if (message->GetArenaForAllocation() == nullptr) { + delete *MutableRaw<Message*>(message, field); + } + *MutableRaw<Message*>(message, field) = nullptr; + } else { + (*MutableRaw<Message*>(message, field))->Clear(); + } + break; + } + } + } else { + switch (field->cpp_type()) { +#define HANDLE_TYPE(UPPERCASE, LOWERCASE) \ + case FieldDescriptor::CPPTYPE_##UPPERCASE: \ + MutableRaw<RepeatedField<LOWERCASE> >(message, field)->Clear(); \ + break + + HANDLE_TYPE(INT32, int32_t); + HANDLE_TYPE(INT64, int64_t); + HANDLE_TYPE(UINT32, uint32_t); + HANDLE_TYPE(UINT64, uint64_t); + HANDLE_TYPE(DOUBLE, double); + HANDLE_TYPE(FLOAT, float); + HANDLE_TYPE(BOOL, bool); + HANDLE_TYPE(ENUM, int); +#undef HANDLE_TYPE + + case FieldDescriptor::CPPTYPE_STRING: { + switch (field->options().ctype()) { + default: // TODO(kenton): Support other string reps. + case FieldOptions::STRING: + MutableRaw<RepeatedPtrField<std::string> >(message, field)->Clear(); + break; + } + break; + } + + case FieldDescriptor::CPPTYPE_MESSAGE: { + if (IsMapFieldInApi(field)) { + MutableRaw<MapFieldBase>(message, field)->Clear(); + } else { + // We don't know which subclass of RepeatedPtrFieldBase the type is, + // so we use RepeatedPtrFieldBase directly. + MutableRaw<RepeatedPtrFieldBase>(message, field) + ->Clear<GenericTypeHandler<Message> >(); + } + break; + } + } + } +} + +void Reflection::RemoveLast(Message* message, + const FieldDescriptor* field) const { + USAGE_CHECK_MESSAGE_TYPE(RemoveLast); + USAGE_CHECK_REPEATED(RemoveLast); + CheckInvalidAccess(schema_, field); + + if (field->is_extension()) { + MutableExtensionSet(message)->RemoveLast(field->number()); + } else { + switch (field->cpp_type()) { +#define HANDLE_TYPE(UPPERCASE, LOWERCASE) \ + case FieldDescriptor::CPPTYPE_##UPPERCASE: \ + MutableRaw<RepeatedField<LOWERCASE> >(message, field)->RemoveLast(); \ + break + + HANDLE_TYPE(INT32, int32_t); + HANDLE_TYPE(INT64, int64_t); + HANDLE_TYPE(UINT32, uint32_t); + HANDLE_TYPE(UINT64, uint64_t); + HANDLE_TYPE(DOUBLE, double); + HANDLE_TYPE(FLOAT, float); + HANDLE_TYPE(BOOL, bool); + HANDLE_TYPE(ENUM, int); +#undef HANDLE_TYPE + + case FieldDescriptor::CPPTYPE_STRING: + switch (field->options().ctype()) { + default: // TODO(kenton): Support other string reps. + case FieldOptions::STRING: + MutableRaw<RepeatedPtrField<std::string> >(message, field) + ->RemoveLast(); + break; + } + break; + + case FieldDescriptor::CPPTYPE_MESSAGE: + if (IsMapFieldInApi(field)) { + MutableRaw<MapFieldBase>(message, field) + ->MutableRepeatedField() + ->RemoveLast<GenericTypeHandler<Message> >(); + } else { + MutableRaw<RepeatedPtrFieldBase>(message, field) + ->RemoveLast<GenericTypeHandler<Message> >(); + } + break; + } + } +} + +Message* Reflection::ReleaseLast(Message* message, + const FieldDescriptor* field) const { + USAGE_CHECK_ALL(ReleaseLast, REPEATED, MESSAGE); + CheckInvalidAccess(schema_, field); + + Message* released; + if (field->is_extension()) { + released = static_cast<Message*>( + MutableExtensionSet(message)->ReleaseLast(field->number())); + } else { + if (IsMapFieldInApi(field)) { + released = MutableRaw<MapFieldBase>(message, field) + ->MutableRepeatedField() + ->ReleaseLast<GenericTypeHandler<Message>>(); + } else { + released = MutableRaw<RepeatedPtrFieldBase>(message, field) + ->ReleaseLast<GenericTypeHandler<Message>>(); + } + } +#ifdef PROTOBUF_FORCE_COPY_IN_RELEASE + return MaybeForceCopy(message->GetArenaForAllocation(), released); +#else // PROTOBUF_FORCE_COPY_IN_RELEASE + return released; +#endif // !PROTOBUF_FORCE_COPY_IN_RELEASE +} + +Message* Reflection::UnsafeArenaReleaseLast( + Message* message, const FieldDescriptor* field) const { + USAGE_CHECK_ALL(UnsafeArenaReleaseLast, REPEATED, MESSAGE); + CheckInvalidAccess(schema_, field); + + if (field->is_extension()) { + return static_cast<Message*>( + MutableExtensionSet(message)->UnsafeArenaReleaseLast(field->number())); + } else { + if (IsMapFieldInApi(field)) { + return MutableRaw<MapFieldBase>(message, field) + ->MutableRepeatedField() + ->UnsafeArenaReleaseLast<GenericTypeHandler<Message>>(); + } else { + return MutableRaw<RepeatedPtrFieldBase>(message, field) + ->UnsafeArenaReleaseLast<GenericTypeHandler<Message>>(); + } + } +} + +void Reflection::SwapElements(Message* message, const FieldDescriptor* field, + int index1, int index2) const { + USAGE_CHECK_MESSAGE_TYPE(Swap); + USAGE_CHECK_REPEATED(Swap); + CheckInvalidAccess(schema_, field); + + if (field->is_extension()) { + MutableExtensionSet(message)->SwapElements(field->number(), index1, index2); + } else { + switch (field->cpp_type()) { +#define HANDLE_TYPE(UPPERCASE, LOWERCASE) \ + case FieldDescriptor::CPPTYPE_##UPPERCASE: \ + MutableRaw<RepeatedField<LOWERCASE> >(message, field) \ + ->SwapElements(index1, index2); \ + break + + HANDLE_TYPE(INT32, int32_t); + HANDLE_TYPE(INT64, int64_t); + HANDLE_TYPE(UINT32, uint32_t); + HANDLE_TYPE(UINT64, uint64_t); + HANDLE_TYPE(DOUBLE, double); + HANDLE_TYPE(FLOAT, float); + HANDLE_TYPE(BOOL, bool); + HANDLE_TYPE(ENUM, int); +#undef HANDLE_TYPE + + case FieldDescriptor::CPPTYPE_STRING: + case FieldDescriptor::CPPTYPE_MESSAGE: + if (IsMapFieldInApi(field)) { + MutableRaw<MapFieldBase>(message, field) + ->MutableRepeatedField() + ->SwapElements(index1, index2); + } else { + MutableRaw<RepeatedPtrFieldBase>(message, field) + ->SwapElements(index1, index2); + } + break; + } + } +} + +namespace { +// Comparison functor for sorting FieldDescriptors by field number. +struct FieldNumberSorter { + bool operator()(const FieldDescriptor* left, + const FieldDescriptor* right) const { + return left->number() < right->number(); + } +}; + +bool IsIndexInHasBitSet(const uint32_t* has_bit_set, uint32_t has_bit_index) { + GOOGLE_DCHECK_NE(has_bit_index, ~0u); + return ((has_bit_set[has_bit_index / 32] >> (has_bit_index % 32)) & + static_cast<uint32_t>(1)) != 0; +} + +bool CreateUnknownEnumValues(const FileDescriptor* file) { + return file->syntax() == FileDescriptor::SYNTAX_PROTO3; +} +} // namespace + +namespace internal { +bool CreateUnknownEnumValues(const FieldDescriptor* field) { + bool open_enum = false; + return field->file()->syntax() == FileDescriptor::SYNTAX_PROTO3 || open_enum; +} +} // namespace internal +using internal::CreateUnknownEnumValues; + +void Reflection::ListFieldsMayFailOnStripped( + const Message& message, bool should_fail, + std::vector<const FieldDescriptor*>* output) const { + output->clear(); + + // Optimization: The default instance never has any fields set. + if (schema_.IsDefaultInstance(message)) return; + + // Optimization: Avoid calling GetHasBits() and HasOneofField() many times + // within the field loop. We allow this violation of ReflectionSchema + // encapsulation because this function takes a noticeable about of CPU + // fleetwide and properly allowing this optimization through public interfaces + // seems more trouble than it is worth. + const uint32_t* const has_bits = + schema_.HasHasbits() ? GetHasBits(message) : nullptr; + const uint32_t* const has_bits_indices = schema_.has_bit_indices_; + output->reserve(descriptor_->field_count()); + const int last_non_weak_field_index = last_non_weak_field_index_; + for (int i = 0; i <= last_non_weak_field_index; i++) { + const FieldDescriptor* field = descriptor_->field(i); + if (!should_fail && schema_.IsFieldStripped(field)) { + continue; + } + if (field->is_repeated()) { + if (FieldSize(message, field) > 0) { + output->push_back(field); + } + } else { + const OneofDescriptor* containing_oneof = field->containing_oneof(); + if (schema_.InRealOneof(field)) { + const uint32_t* const oneof_case_array = + GetConstPointerAtOffset<uint32_t>(&message, + schema_.oneof_case_offset_); + // Equivalent to: HasOneofField(message, field) + if (static_cast<int64_t>(oneof_case_array[containing_oneof->index()]) == + field->number()) { + output->push_back(field); + } + } else if (has_bits && has_bits_indices[i] != static_cast<uint32_t>(-1)) { + CheckInvalidAccess(schema_, field); + // Equivalent to: HasBit(message, field) + if (IsIndexInHasBitSet(has_bits, has_bits_indices[i])) { + output->push_back(field); + } + } else if (HasBit(message, field)) { // Fall back on proto3-style HasBit. + output->push_back(field); + } + } + } + if (schema_.HasExtensionSet()) { + GetExtensionSet(message).AppendToList(descriptor_, descriptor_pool_, + output); + } + + // ListFields() must sort output by field number. + std::sort(output->begin(), output->end(), FieldNumberSorter()); +} + +void Reflection::ListFields(const Message& message, + std::vector<const FieldDescriptor*>* output) const { + ListFieldsMayFailOnStripped(message, true, output); +} + +void Reflection::ListFieldsOmitStripped( + const Message& message, std::vector<const FieldDescriptor*>* output) const { + ListFieldsMayFailOnStripped(message, false, output); +} + +// ------------------------------------------------------------------- + +#undef DEFINE_PRIMITIVE_ACCESSORS +#define DEFINE_PRIMITIVE_ACCESSORS(TYPENAME, TYPE, PASSTYPE, CPPTYPE) \ + PASSTYPE Reflection::Get##TYPENAME(const Message& message, \ + const FieldDescriptor* field) const { \ + USAGE_CHECK_ALL(Get##TYPENAME, SINGULAR, CPPTYPE); \ + if (field->is_extension()) { \ + return GetExtensionSet(message).Get##TYPENAME( \ + field->number(), field->default_value_##PASSTYPE()); \ + } else if (schema_.InRealOneof(field) && !HasOneofField(message, field)) { \ + return field->default_value_##PASSTYPE(); \ + } else { \ + return GetField<TYPE>(message, field); \ + } \ + } \ + \ + void Reflection::Set##TYPENAME( \ + Message* message, const FieldDescriptor* field, PASSTYPE value) const { \ + USAGE_CHECK_ALL(Set##TYPENAME, SINGULAR, CPPTYPE); \ + if (field->is_extension()) { \ + return MutableExtensionSet(message)->Set##TYPENAME( \ + field->number(), field->type(), value, field); \ + } else { \ + SetField<TYPE>(message, field, value); \ + } \ + } \ + \ + PASSTYPE Reflection::GetRepeated##TYPENAME( \ + const Message& message, const FieldDescriptor* field, int index) const { \ + USAGE_CHECK_ALL(GetRepeated##TYPENAME, REPEATED, CPPTYPE); \ + if (field->is_extension()) { \ + return GetExtensionSet(message).GetRepeated##TYPENAME(field->number(), \ + index); \ + } else { \ + return GetRepeatedField<TYPE>(message, field, index); \ + } \ + } \ + \ + void Reflection::SetRepeated##TYPENAME(Message* message, \ + const FieldDescriptor* field, \ + int index, PASSTYPE value) const { \ + USAGE_CHECK_ALL(SetRepeated##TYPENAME, REPEATED, CPPTYPE); \ + if (field->is_extension()) { \ + MutableExtensionSet(message)->SetRepeated##TYPENAME(field->number(), \ + index, value); \ + } else { \ + SetRepeatedField<TYPE>(message, field, index, value); \ + } \ + } \ + \ + void Reflection::Add##TYPENAME( \ + Message* message, const FieldDescriptor* field, PASSTYPE value) const { \ + USAGE_CHECK_ALL(Add##TYPENAME, REPEATED, CPPTYPE); \ + if (field->is_extension()) { \ + MutableExtensionSet(message)->Add##TYPENAME( \ + field->number(), field->type(), field->options().packed(), value, \ + field); \ + } else { \ + AddField<TYPE>(message, field, value); \ + } \ + } + +DEFINE_PRIMITIVE_ACCESSORS(Int32, int32_t, int32_t, INT32) +DEFINE_PRIMITIVE_ACCESSORS(Int64, int64_t, int64_t, INT64) +DEFINE_PRIMITIVE_ACCESSORS(UInt32, uint32_t, uint32_t, UINT32) +DEFINE_PRIMITIVE_ACCESSORS(UInt64, uint64_t, uint64_t, UINT64) +DEFINE_PRIMITIVE_ACCESSORS(Float, float, float, FLOAT) +DEFINE_PRIMITIVE_ACCESSORS(Double, double, double, DOUBLE) +DEFINE_PRIMITIVE_ACCESSORS(Bool, bool, bool, BOOL) +#undef DEFINE_PRIMITIVE_ACCESSORS + +// ------------------------------------------------------------------- + +std::string Reflection::GetString(const Message& message, + const FieldDescriptor* field) const { + USAGE_CHECK_ALL(GetString, SINGULAR, STRING); + if (field->is_extension()) { + return GetExtensionSet(message).GetString(field->number(), + field->default_value_string()); + } else { + if (schema_.InRealOneof(field) && !HasOneofField(message, field)) { + return field->default_value_string(); + } + switch (field->options().ctype()) { + default: // TODO(kenton): Support other string reps. + case FieldOptions::STRING: + if (IsInlined(field)) { + return GetField<InlinedStringField>(message, field).GetNoArena(); + } else { + const auto& str = GetField<ArenaStringPtr>(message, field); + return str.IsDefault() ? field->default_value_string() : str.Get(); + } + } + } +} + +const std::string& Reflection::GetStringReference(const Message& message, + const FieldDescriptor* field, + std::string* scratch) const { + (void)scratch; // Parameter is used by Google-internal code. + USAGE_CHECK_ALL(GetStringReference, SINGULAR, STRING); + if (field->is_extension()) { + return GetExtensionSet(message).GetString(field->number(), + field->default_value_string()); + } else { + if (schema_.InRealOneof(field) && !HasOneofField(message, field)) { + return field->default_value_string(); + } + switch (field->options().ctype()) { + default: // TODO(kenton): Support other string reps. + case FieldOptions::STRING: + if (IsInlined(field)) { + return GetField<InlinedStringField>(message, field).GetNoArena(); + } else { + const auto& str = GetField<ArenaStringPtr>(message, field); + return str.IsDefault() ? field->default_value_string() : str.Get(); + } + } + } +} + + +void Reflection::SetString(Message* message, const FieldDescriptor* field, + std::string value) const { + USAGE_CHECK_ALL(SetString, SINGULAR, STRING); + if (field->is_extension()) { + return MutableExtensionSet(message)->SetString( + field->number(), field->type(), std::move(value), field); + } else { + switch (field->options().ctype()) { + default: // TODO(kenton): Support other string reps. + case FieldOptions::STRING: { + if (IsInlined(field)) { + const uint32_t index = schema_.InlinedStringIndex(field); + GOOGLE_DCHECK_GT(index, 0); + uint32_t* states = + &MutableInlinedStringDonatedArray(message)[index / 32]; + uint32_t mask = ~(static_cast<uint32_t>(1) << (index % 32)); + MutableField<InlinedStringField>(message, field) + ->Set(value, message->GetArenaForAllocation(), + IsInlinedStringDonated(*message, field), states, mask, + message); + break; + } + + // Oneof string fields are never set as a default instance. + // We just need to pass some arbitrary default string to make it work. + // This allows us to not have the real default accessible from + // reflection. + if (schema_.InRealOneof(field) && !HasOneofField(*message, field)) { + ClearOneof(message, field->containing_oneof()); + MutableField<ArenaStringPtr>(message, field)->InitDefault(); + } + MutableField<ArenaStringPtr>(message, field) + ->Set(std::move(value), message->GetArenaForAllocation()); + break; + } + } + } +} + + +std::string Reflection::GetRepeatedString(const Message& message, + const FieldDescriptor* field, + int index) const { + USAGE_CHECK_ALL(GetRepeatedString, REPEATED, STRING); + if (field->is_extension()) { + return GetExtensionSet(message).GetRepeatedString(field->number(), index); + } else { + switch (field->options().ctype()) { + default: // TODO(kenton): Support other string reps. + case FieldOptions::STRING: + return GetRepeatedPtrField<std::string>(message, field, index); + } + } +} + +const std::string& Reflection::GetRepeatedStringReference( + const Message& message, const FieldDescriptor* field, int index, + std::string* scratch) const { + (void)scratch; // Parameter is used by Google-internal code. + USAGE_CHECK_ALL(GetRepeatedStringReference, REPEATED, STRING); + if (field->is_extension()) { + return GetExtensionSet(message).GetRepeatedString(field->number(), index); + } else { + switch (field->options().ctype()) { + default: // TODO(kenton): Support other string reps. + case FieldOptions::STRING: + return GetRepeatedPtrField<std::string>(message, field, index); + } + } +} + + +void Reflection::SetRepeatedString(Message* message, + const FieldDescriptor* field, int index, + std::string value) const { + USAGE_CHECK_ALL(SetRepeatedString, REPEATED, STRING); + if (field->is_extension()) { + MutableExtensionSet(message)->SetRepeatedString(field->number(), index, + std::move(value)); + } else { + switch (field->options().ctype()) { + default: // TODO(kenton): Support other string reps. + case FieldOptions::STRING: + MutableRepeatedField<std::string>(message, field, index) + ->assign(std::move(value)); + break; + } + } +} + + +void Reflection::AddString(Message* message, const FieldDescriptor* field, + std::string value) const { + USAGE_CHECK_ALL(AddString, REPEATED, STRING); + if (field->is_extension()) { + MutableExtensionSet(message)->AddString(field->number(), field->type(), + std::move(value), field); + } else { + switch (field->options().ctype()) { + default: // TODO(kenton): Support other string reps. + case FieldOptions::STRING: + AddField<std::string>(message, field)->assign(std::move(value)); + break; + } + } +} + + +// ------------------------------------------------------------------- + +const EnumValueDescriptor* Reflection::GetEnum( + const Message& message, const FieldDescriptor* field) const { + // Usage checked by GetEnumValue. + int value = GetEnumValue(message, field); + return field->enum_type()->FindValueByNumberCreatingIfUnknown(value); +} + +int Reflection::GetEnumValue(const Message& message, + const FieldDescriptor* field) const { + USAGE_CHECK_ALL(GetEnumValue, SINGULAR, ENUM); + + int32_t value; + if (field->is_extension()) { + value = GetExtensionSet(message).GetEnum( + field->number(), field->default_value_enum()->number()); + } else if (schema_.InRealOneof(field) && !HasOneofField(message, field)) { + value = field->default_value_enum()->number(); + } else { + value = GetField<int>(message, field); + } + return value; +} + +void Reflection::SetEnum(Message* message, const FieldDescriptor* field, + const EnumValueDescriptor* value) const { + // Usage checked by SetEnumValue. + USAGE_CHECK_ENUM_VALUE(SetEnum); + SetEnumValueInternal(message, field, value->number()); +} + +void Reflection::SetEnumValue(Message* message, const FieldDescriptor* field, + int value) const { + USAGE_CHECK_ALL(SetEnumValue, SINGULAR, ENUM); + if (!CreateUnknownEnumValues(field)) { + // Check that the value is valid if we don't support direct storage of + // unknown enum values. + const EnumValueDescriptor* value_desc = + field->enum_type()->FindValueByNumber(value); + if (value_desc == nullptr) { + MutableUnknownFields(message)->AddVarint(field->number(), value); + return; + } + } + SetEnumValueInternal(message, field, value); +} + +void Reflection::SetEnumValueInternal(Message* message, + const FieldDescriptor* field, + int value) const { + if (field->is_extension()) { + MutableExtensionSet(message)->SetEnum(field->number(), field->type(), value, + field); + } else { + SetField<int>(message, field, value); + } +} + +const EnumValueDescriptor* Reflection::GetRepeatedEnum( + const Message& message, const FieldDescriptor* field, int index) const { + // Usage checked by GetRepeatedEnumValue. + int value = GetRepeatedEnumValue(message, field, index); + return field->enum_type()->FindValueByNumberCreatingIfUnknown(value); +} + +int Reflection::GetRepeatedEnumValue(const Message& message, + const FieldDescriptor* field, + int index) const { + USAGE_CHECK_ALL(GetRepeatedEnumValue, REPEATED, ENUM); + + int value; + if (field->is_extension()) { + value = GetExtensionSet(message).GetRepeatedEnum(field->number(), index); + } else { + value = GetRepeatedField<int>(message, field, index); + } + return value; +} + +void Reflection::SetRepeatedEnum(Message* message, const FieldDescriptor* field, + int index, + const EnumValueDescriptor* value) const { + // Usage checked by SetRepeatedEnumValue. + USAGE_CHECK_ENUM_VALUE(SetRepeatedEnum); + SetRepeatedEnumValueInternal(message, field, index, value->number()); +} + +void Reflection::SetRepeatedEnumValue(Message* message, + const FieldDescriptor* field, int index, + int value) const { + USAGE_CHECK_ALL(SetRepeatedEnum, REPEATED, ENUM); + if (!CreateUnknownEnumValues(field)) { + // Check that the value is valid if we don't support direct storage of + // unknown enum values. + const EnumValueDescriptor* value_desc = + field->enum_type()->FindValueByNumber(value); + if (value_desc == nullptr) { + MutableUnknownFields(message)->AddVarint(field->number(), value); + return; + } + } + SetRepeatedEnumValueInternal(message, field, index, value); +} + +void Reflection::SetRepeatedEnumValueInternal(Message* message, + const FieldDescriptor* field, + int index, int value) const { + if (field->is_extension()) { + MutableExtensionSet(message)->SetRepeatedEnum(field->number(), index, + value); + } else { + SetRepeatedField<int>(message, field, index, value); + } +} + +void Reflection::AddEnum(Message* message, const FieldDescriptor* field, + const EnumValueDescriptor* value) const { + // Usage checked by AddEnumValue. + USAGE_CHECK_ENUM_VALUE(AddEnum); + AddEnumValueInternal(message, field, value->number()); +} + +void Reflection::AddEnumValue(Message* message, const FieldDescriptor* field, + int value) const { + USAGE_CHECK_ALL(AddEnum, REPEATED, ENUM); + if (!CreateUnknownEnumValues(field)) { + // Check that the value is valid if we don't support direct storage of + // unknown enum values. + const EnumValueDescriptor* value_desc = + field->enum_type()->FindValueByNumber(value); + if (value_desc == nullptr) { + MutableUnknownFields(message)->AddVarint(field->number(), value); + return; + } + } + AddEnumValueInternal(message, field, value); +} + +void Reflection::AddEnumValueInternal(Message* message, + const FieldDescriptor* field, + int value) const { + if (field->is_extension()) { + MutableExtensionSet(message)->AddEnum(field->number(), field->type(), + field->options().packed(), value, + field); + } else { + AddField<int>(message, field, value); + } +} + +// ------------------------------------------------------------------- + +const Message* Reflection::GetDefaultMessageInstance( + const FieldDescriptor* field) const { + // If we are using the generated factory, we cache the prototype in the field + // descriptor for faster access. + // The default instances of generated messages are not cross-linked, which + // means they contain null pointers on their message fields and can't be used + // to get the default of submessages. + if (message_factory_ == MessageFactory::generated_factory()) { + auto& ptr = field->default_generated_instance_; + auto* res = ptr.load(std::memory_order_acquire); + if (res == nullptr) { + // First time asking for this field's default. Load it and cache it. + res = message_factory_->GetPrototype(field->message_type()); + ptr.store(res, std::memory_order_release); + } + return res; + } + + // For other factories, we try the default's object field. + // In particular, the DynamicMessageFactory will cross link the default + // instances to allow for this. But only do this for real fields. + // This is an optimization to avoid going to GetPrototype() below, as that + // requires a lock and a map lookup. + if (!field->is_extension() && !field->options().weak() && + !IsLazyField(field) && !schema_.InRealOneof(field)) { + auto* res = DefaultRaw<const Message*>(field); + if (res != nullptr) { + return res; + } + } + // Otherwise, just go to the factory. + return message_factory_->GetPrototype(field->message_type()); +} + +const Message& Reflection::GetMessage(const Message& message, + const FieldDescriptor* field, + MessageFactory* factory) const { + USAGE_CHECK_ALL(GetMessage, SINGULAR, MESSAGE); + CheckInvalidAccess(schema_, field); + + if (factory == nullptr) factory = message_factory_; + + if (field->is_extension()) { + return static_cast<const Message&>(GetExtensionSet(message).GetMessage( + field->number(), field->message_type(), factory)); + } else { + if (schema_.InRealOneof(field) && !HasOneofField(message, field)) { + return *GetDefaultMessageInstance(field); + } + const Message* result = GetRaw<const Message*>(message, field); + if (result == nullptr) { + result = GetDefaultMessageInstance(field); + } + return *result; + } +} + +Message* Reflection::MutableMessage(Message* message, + const FieldDescriptor* field, + MessageFactory* factory) const { + USAGE_CHECK_ALL(MutableMessage, SINGULAR, MESSAGE); + CheckInvalidAccess(schema_, field); + + if (factory == nullptr) factory = message_factory_; + + if (field->is_extension()) { + return static_cast<Message*>( + MutableExtensionSet(message)->MutableMessage(field, factory)); + } else { + Message* result; + + Message** result_holder = MutableRaw<Message*>(message, field); + + if (schema_.InRealOneof(field)) { + if (!HasOneofField(*message, field)) { + ClearOneof(message, field->containing_oneof()); + result_holder = MutableField<Message*>(message, field); + const Message* default_message = GetDefaultMessageInstance(field); + *result_holder = default_message->New(message->GetArenaForAllocation()); + } + } else { + SetBit(message, field); + } + + if (*result_holder == nullptr) { + const Message* default_message = GetDefaultMessageInstance(field); + *result_holder = default_message->New(message->GetArenaForAllocation()); + } + result = *result_holder; + return result; + } +} + +void Reflection::UnsafeArenaSetAllocatedMessage( + Message* message, Message* sub_message, + const FieldDescriptor* field) const { + USAGE_CHECK_ALL(SetAllocatedMessage, SINGULAR, MESSAGE); + CheckInvalidAccess(schema_, field); + + + if (field->is_extension()) { + MutableExtensionSet(message)->UnsafeArenaSetAllocatedMessage( + field->number(), field->type(), field, sub_message); + } else { + if (schema_.InRealOneof(field)) { + if (sub_message == nullptr) { + ClearOneof(message, field->containing_oneof()); + return; + } + ClearOneof(message, field->containing_oneof()); + *MutableRaw<Message*>(message, field) = sub_message; + SetOneofCase(message, field); + return; + } + + if (sub_message == nullptr) { + ClearBit(message, field); + } else { + SetBit(message, field); + } + Message** sub_message_holder = MutableRaw<Message*>(message, field); + if (message->GetArenaForAllocation() == nullptr) { + delete *sub_message_holder; + } + *sub_message_holder = sub_message; + } +} + +void Reflection::SetAllocatedMessage(Message* message, Message* sub_message, + const FieldDescriptor* field) const { + GOOGLE_DCHECK(sub_message == nullptr || sub_message->GetOwningArena() == nullptr || + sub_message->GetOwningArena() == message->GetArenaForAllocation()); + CheckInvalidAccess(schema_, field); + + // If message and sub-message are in different memory ownership domains + // (different arenas, or one is on heap and one is not), then we may need to + // do a copy. + if (sub_message != nullptr && + sub_message->GetOwningArena() != message->GetArenaForAllocation()) { + if (sub_message->GetOwningArena() == nullptr && + message->GetArenaForAllocation() != nullptr) { + // Case 1: parent is on an arena and child is heap-allocated. We can add + // the child to the arena's Own() list to free on arena destruction, then + // set our pointer. + message->GetArenaForAllocation()->Own(sub_message); + UnsafeArenaSetAllocatedMessage(message, sub_message, field); + } else { + // Case 2: all other cases. We need to make a copy. MutableMessage() will + // either get the existing message object, or instantiate a new one as + // appropriate w.r.t. our arena. + Message* sub_message_copy = MutableMessage(message, field); + sub_message_copy->CopyFrom(*sub_message); + } + } else { + // Same memory ownership domains. + UnsafeArenaSetAllocatedMessage(message, sub_message, field); + } +} + +Message* Reflection::UnsafeArenaReleaseMessage(Message* message, + const FieldDescriptor* field, + MessageFactory* factory) const { + USAGE_CHECK_ALL(ReleaseMessage, SINGULAR, MESSAGE); + CheckInvalidAccess(schema_, field); + + if (factory == nullptr) factory = message_factory_; + + if (field->is_extension()) { + return static_cast<Message*>( + MutableExtensionSet(message)->UnsafeArenaReleaseMessage(field, + factory)); + } else { + if (!(field->is_repeated() || schema_.InRealOneof(field))) { + ClearBit(message, field); + } + if (schema_.InRealOneof(field)) { + if (HasOneofField(*message, field)) { + *MutableOneofCase(message, field->containing_oneof()) = 0; + } else { + return nullptr; + } + } + Message** result = MutableRaw<Message*>(message, field); + Message* ret = *result; + *result = nullptr; + return ret; + } +} + +Message* Reflection::ReleaseMessage(Message* message, + const FieldDescriptor* field, + MessageFactory* factory) const { + CheckInvalidAccess(schema_, field); + + Message* released = UnsafeArenaReleaseMessage(message, field, factory); +#ifdef PROTOBUF_FORCE_COPY_IN_RELEASE + released = MaybeForceCopy(message->GetArenaForAllocation(), released); +#endif // PROTOBUF_FORCE_COPY_IN_RELEASE + if (message->GetArenaForAllocation() != nullptr && released != nullptr) { + Message* copy_from_arena = released->New(); + copy_from_arena->CopyFrom(*released); + released = copy_from_arena; + } + return released; +} + +const Message& Reflection::GetRepeatedMessage(const Message& message, + const FieldDescriptor* field, + int index) const { + USAGE_CHECK_ALL(GetRepeatedMessage, REPEATED, MESSAGE); + CheckInvalidAccess(schema_, field); + + if (field->is_extension()) { + return static_cast<const Message&>( + GetExtensionSet(message).GetRepeatedMessage(field->number(), index)); + } else { + if (IsMapFieldInApi(field)) { + return GetRaw<MapFieldBase>(message, field) + .GetRepeatedField() + .Get<GenericTypeHandler<Message> >(index); + } else { + return GetRaw<RepeatedPtrFieldBase>(message, field) + .Get<GenericTypeHandler<Message> >(index); + } + } +} + +Message* Reflection::MutableRepeatedMessage(Message* message, + const FieldDescriptor* field, + int index) const { + USAGE_CHECK_ALL(MutableRepeatedMessage, REPEATED, MESSAGE); + CheckInvalidAccess(schema_, field); + + if (field->is_extension()) { + return static_cast<Message*>( + MutableExtensionSet(message)->MutableRepeatedMessage(field->number(), + index)); + } else { + if (IsMapFieldInApi(field)) { + return MutableRaw<MapFieldBase>(message, field) + ->MutableRepeatedField() + ->Mutable<GenericTypeHandler<Message> >(index); + } else { + return MutableRaw<RepeatedPtrFieldBase>(message, field) + ->Mutable<GenericTypeHandler<Message> >(index); + } + } +} + +Message* Reflection::AddMessage(Message* message, const FieldDescriptor* field, + MessageFactory* factory) const { + USAGE_CHECK_ALL(AddMessage, REPEATED, MESSAGE); + CheckInvalidAccess(schema_, field); + + if (factory == nullptr) factory = message_factory_; + + if (field->is_extension()) { + return static_cast<Message*>( + MutableExtensionSet(message)->AddMessage(field, factory)); + } else { + Message* result = nullptr; + + // We can't use AddField<Message>() because RepeatedPtrFieldBase doesn't + // know how to allocate one. + RepeatedPtrFieldBase* repeated = nullptr; + if (IsMapFieldInApi(field)) { + repeated = + MutableRaw<MapFieldBase>(message, field)->MutableRepeatedField(); + } else { + repeated = MutableRaw<RepeatedPtrFieldBase>(message, field); + } + result = repeated->AddFromCleared<GenericTypeHandler<Message> >(); + if (result == nullptr) { + // We must allocate a new object. + const Message* prototype; + if (repeated->size() == 0) { + prototype = factory->GetPrototype(field->message_type()); + } else { + prototype = &repeated->Get<GenericTypeHandler<Message> >(0); + } + result = prototype->New(message->GetArenaForAllocation()); + // We can guarantee here that repeated and result are either both heap + // allocated or arena owned. So it is safe to call the unsafe version + // of AddAllocated. + repeated->UnsafeArenaAddAllocated<GenericTypeHandler<Message> >(result); + } + + return result; + } +} + +void Reflection::AddAllocatedMessage(Message* message, + const FieldDescriptor* field, + Message* new_entry) const { + USAGE_CHECK_ALL(AddAllocatedMessage, REPEATED, MESSAGE); + CheckInvalidAccess(schema_, field); + + if (field->is_extension()) { + MutableExtensionSet(message)->AddAllocatedMessage(field, new_entry); + } else { + RepeatedPtrFieldBase* repeated = nullptr; + if (IsMapFieldInApi(field)) { + repeated = + MutableRaw<MapFieldBase>(message, field)->MutableRepeatedField(); + } else { + repeated = MutableRaw<RepeatedPtrFieldBase>(message, field); + } + repeated->AddAllocated<GenericTypeHandler<Message> >(new_entry); + } +} + +void Reflection::UnsafeArenaAddAllocatedMessage(Message* message, + const FieldDescriptor* field, + Message* new_entry) const { + USAGE_CHECK_ALL(UnsafeArenaAddAllocatedMessage, REPEATED, MESSAGE); + CheckInvalidAccess(schema_, field); + + if (field->is_extension()) { + MutableExtensionSet(message)->UnsafeArenaAddAllocatedMessage(field, + new_entry); + } else { + RepeatedPtrFieldBase* repeated = nullptr; + if (IsMapFieldInApi(field)) { + repeated = + MutableRaw<MapFieldBase>(message, field)->MutableRepeatedField(); + } else { + repeated = MutableRaw<RepeatedPtrFieldBase>(message, field); + } + repeated->UnsafeArenaAddAllocated<GenericTypeHandler<Message>>(new_entry); + } +} + +void* Reflection::MutableRawRepeatedField(Message* message, + const FieldDescriptor* field, + FieldDescriptor::CppType cpptype, + int ctype, + const Descriptor* desc) const { + (void)ctype; // Parameter is used by Google-internal code. + USAGE_CHECK_REPEATED("MutableRawRepeatedField"); + CheckInvalidAccess(schema_, field); + + if (field->cpp_type() != cpptype && + (field->cpp_type() != FieldDescriptor::CPPTYPE_ENUM || + cpptype != FieldDescriptor::CPPTYPE_INT32)) + ReportReflectionUsageTypeError(descriptor_, field, + "MutableRawRepeatedField", cpptype); + if (desc != nullptr) + GOOGLE_CHECK_EQ(field->message_type(), desc) << "wrong submessage type"; + if (field->is_extension()) { + return MutableExtensionSet(message)->MutableRawRepeatedField( + field->number(), field->type(), field->is_packed(), field); + } else { + // Trigger transform for MapField + if (IsMapFieldInApi(field)) { + return MutableRawNonOneof<MapFieldBase>(message, field) + ->MutableRepeatedField(); + } + return MutableRawNonOneof<void>(message, field); + } +} + +const void* Reflection::GetRawRepeatedField(const Message& message, + const FieldDescriptor* field, + FieldDescriptor::CppType cpptype, + int ctype, + const Descriptor* desc) const { + USAGE_CHECK_REPEATED("GetRawRepeatedField"); + if (field->cpp_type() != cpptype) + ReportReflectionUsageTypeError(descriptor_, field, "GetRawRepeatedField", + cpptype); + if (ctype >= 0) + GOOGLE_CHECK_EQ(field->options().ctype(), ctype) << "subtype mismatch"; + if (desc != nullptr) + GOOGLE_CHECK_EQ(field->message_type(), desc) << "wrong submessage type"; + if (field->is_extension()) { + // Should use extension_set::GetRawRepeatedField. However, the required + // parameter "default repeated value" is not very easy to get here. + // Map is not supported in extensions, it is acceptable to use + // extension_set::MutableRawRepeatedField which does not change the message. + return MutableExtensionSet(const_cast<Message*>(&message)) + ->MutableRawRepeatedField(field->number(), field->type(), + field->is_packed(), field); + } else { + // Trigger transform for MapField + if (IsMapFieldInApi(field)) { + return &(GetRawNonOneof<MapFieldBase>(message, field).GetRepeatedField()); + } + return &GetRawNonOneof<char>(message, field); + } +} + +const FieldDescriptor* Reflection::GetOneofFieldDescriptor( + const Message& message, const OneofDescriptor* oneof_descriptor) const { + if (oneof_descriptor->is_synthetic()) { + const FieldDescriptor* field = oneof_descriptor->field(0); + return HasField(message, field) ? field : nullptr; + } + uint32_t field_number = GetOneofCase(message, oneof_descriptor); + if (field_number == 0) { + return nullptr; + } + return descriptor_->FindFieldByNumber(field_number); +} + +bool Reflection::ContainsMapKey(const Message& message, + const FieldDescriptor* field, + const MapKey& key) const { + USAGE_CHECK(IsMapFieldInApi(field), "LookupMapValue", + "Field is not a map field."); + return GetRaw<MapFieldBase>(message, field).ContainsMapKey(key); +} + +bool Reflection::InsertOrLookupMapValue(Message* message, + const FieldDescriptor* field, + const MapKey& key, + MapValueRef* val) const { + USAGE_CHECK(IsMapFieldInApi(field), "InsertOrLookupMapValue", + "Field is not a map field."); + val->SetType(field->message_type()->map_value()->cpp_type()); + return MutableRaw<MapFieldBase>(message, field) + ->InsertOrLookupMapValue(key, val); +} + +bool Reflection::LookupMapValue(const Message& message, + const FieldDescriptor* field, const MapKey& key, + MapValueConstRef* val) const { + USAGE_CHECK(IsMapFieldInApi(field), "LookupMapValue", + "Field is not a map field."); + val->SetType(field->message_type()->map_value()->cpp_type()); + return GetRaw<MapFieldBase>(message, field).LookupMapValue(key, val); +} + +bool Reflection::DeleteMapValue(Message* message, const FieldDescriptor* field, + const MapKey& key) const { + USAGE_CHECK(IsMapFieldInApi(field), "DeleteMapValue", + "Field is not a map field."); + return MutableRaw<MapFieldBase>(message, field)->DeleteMapValue(key); +} + +MapIterator Reflection::MapBegin(Message* message, + const FieldDescriptor* field) const { + USAGE_CHECK(IsMapFieldInApi(field), "MapBegin", "Field is not a map field."); + MapIterator iter(message, field); + GetRaw<MapFieldBase>(*message, field).MapBegin(&iter); + return iter; +} + +MapIterator Reflection::MapEnd(Message* message, + const FieldDescriptor* field) const { + USAGE_CHECK(IsMapFieldInApi(field), "MapEnd", "Field is not a map field."); + MapIterator iter(message, field); + GetRaw<MapFieldBase>(*message, field).MapEnd(&iter); + return iter; +} + +int Reflection::MapSize(const Message& message, + const FieldDescriptor* field) const { + USAGE_CHECK(IsMapFieldInApi(field), "MapSize", "Field is not a map field."); + return GetRaw<MapFieldBase>(message, field).size(); +} + +// ----------------------------------------------------------------------------- + +const FieldDescriptor* Reflection::FindKnownExtensionByName( + const std::string& name) const { + if (!schema_.HasExtensionSet()) return nullptr; + return descriptor_pool_->FindExtensionByPrintableName(descriptor_, name); +} + +const FieldDescriptor* Reflection::FindKnownExtensionByNumber( + int number) const { + if (!schema_.HasExtensionSet()) return nullptr; + return descriptor_pool_->FindExtensionByNumber(descriptor_, number); +} + +bool Reflection::SupportsUnknownEnumValues() const { + return CreateUnknownEnumValues(descriptor_->file()); +} + +// =================================================================== +// Some private helpers. + +// These simple template accessors obtain pointers (or references) to +// the given field. + +template <class Type> +const Type& Reflection::GetRawNonOneof(const Message& message, + const FieldDescriptor* field) const { + return GetConstRefAtOffset<Type>(message, + schema_.GetFieldOffsetNonOneof(field)); +} + +template <class Type> +Type* Reflection::MutableRawNonOneof(Message* message, + const FieldDescriptor* field) const { + return GetPointerAtOffset<Type>(message, + schema_.GetFieldOffsetNonOneof(field)); +} + +template <typename Type> +Type* Reflection::MutableRaw(Message* message, + const FieldDescriptor* field) const { + return GetPointerAtOffset<Type>(message, schema_.GetFieldOffset(field)); +} + +const uint32_t* Reflection::GetHasBits(const Message& message) const { + GOOGLE_DCHECK(schema_.HasHasbits()); + return &GetConstRefAtOffset<uint32_t>(message, schema_.HasBitsOffset()); +} + +uint32_t* Reflection::MutableHasBits(Message* message) const { + GOOGLE_DCHECK(schema_.HasHasbits()); + return GetPointerAtOffset<uint32_t>(message, schema_.HasBitsOffset()); +} + +uint32_t* Reflection::MutableOneofCase( + Message* message, const OneofDescriptor* oneof_descriptor) const { + GOOGLE_DCHECK(!oneof_descriptor->is_synthetic()); + return GetPointerAtOffset<uint32_t>( + message, schema_.GetOneofCaseOffset(oneof_descriptor)); +} + +const ExtensionSet& Reflection::GetExtensionSet(const Message& message) const { + return GetConstRefAtOffset<ExtensionSet>(message, + schema_.GetExtensionSetOffset()); +} + +ExtensionSet* Reflection::MutableExtensionSet(Message* message) const { + return GetPointerAtOffset<ExtensionSet>(message, + schema_.GetExtensionSetOffset()); +} + +const InternalMetadata& Reflection::GetInternalMetadata( + const Message& message) const { + return GetConstRefAtOffset<InternalMetadata>(message, + schema_.GetMetadataOffset()); +} + +InternalMetadata* Reflection::MutableInternalMetadata(Message* message) const { + return GetPointerAtOffset<InternalMetadata>(message, + schema_.GetMetadataOffset()); +} + +const uint32_t* Reflection::GetInlinedStringDonatedArray( + const Message& message) const { + GOOGLE_DCHECK(schema_.HasInlinedString()); + return &GetConstRefAtOffset<uint32_t>(message, + schema_.InlinedStringDonatedOffset()); +} + +uint32_t* Reflection::MutableInlinedStringDonatedArray(Message* message) const { + GOOGLE_DCHECK(schema_.HasInlinedString()); + return GetPointerAtOffset<uint32_t>(message, + schema_.InlinedStringDonatedOffset()); +} + +// Simple accessors for manipulating _inlined_string_donated_; +bool Reflection::IsInlinedStringDonated(const Message& message, + const FieldDescriptor* field) const { + uint32_t index = schema_.InlinedStringIndex(field); + GOOGLE_DCHECK_GT(index, 0); + return IsIndexInHasBitSet(GetInlinedStringDonatedArray(message), index); +} + +inline void SetInlinedStringDonated(uint32_t index, uint32_t* array) { + array[index / 32] |= (static_cast<uint32_t>(1) << (index % 32)); +} + +inline void ClearInlinedStringDonated(uint32_t index, uint32_t* array) { + array[index / 32] &= ~(static_cast<uint32_t>(1) << (index % 32)); +} + +void Reflection::SwapInlinedStringDonated(Message* lhs, Message* rhs, + const FieldDescriptor* field) const { + Arena* lhs_arena = lhs->GetArenaForAllocation(); + Arena* rhs_arena = rhs->GetArenaForAllocation(); + // If arenas differ, inined string fields are swapped by copying values. + // Donation status should not be swapped. + if (lhs_arena != rhs_arena) { + return; + } + bool lhs_donated = IsInlinedStringDonated(*lhs, field); + bool rhs_donated = IsInlinedStringDonated(*rhs, field); + if (lhs_donated == rhs_donated) { + return; + } + // If one is undonated, both must have already registered ArenaDtor. + uint32_t* lhs_array = MutableInlinedStringDonatedArray(lhs); + uint32_t* rhs_array = MutableInlinedStringDonatedArray(rhs); + GOOGLE_CHECK_EQ(lhs_array[0] & 0x1u, 0u); + GOOGLE_CHECK_EQ(rhs_array[0] & 0x1u, 0u); + // Swap donation status bit. + uint32_t index = schema_.InlinedStringIndex(field); + GOOGLE_DCHECK_GT(index, 0); + if (rhs_donated) { + SetInlinedStringDonated(index, lhs_array); + ClearInlinedStringDonated(index, rhs_array); + } else { // lhs_donated + ClearInlinedStringDonated(index, lhs_array); + SetInlinedStringDonated(index, rhs_array); + } +} + +// Simple accessors for manipulating has_bits_. +bool Reflection::HasBit(const Message& message, + const FieldDescriptor* field) const { + GOOGLE_DCHECK(!field->options().weak()); + if (schema_.HasBitIndex(field) != static_cast<uint32_t>(-1)) { + return IsIndexInHasBitSet(GetHasBits(message), schema_.HasBitIndex(field)); + } + + // Intentionally check here because HasBitIndex(field) != -1 means valid. + CheckInvalidAccess(schema_, field); + + // proto3: no has-bits. All fields present except messages, which are + // present only if their message-field pointer is non-null. + if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { + return !schema_.IsDefaultInstance(message) && + GetRaw<const Message*>(message, field) != nullptr; + } else { + // Non-message field (and non-oneof, since that was handled in HasField() + // before calling us), and singular (again, checked in HasField). So, this + // field must be a scalar. + + // Scalar primitive (numeric or string/bytes) fields are present if + // their value is non-zero (numeric) or non-empty (string/bytes). N.B.: + // we must use this definition here, rather than the "scalar fields + // always present" in the proto3 docs, because MergeFrom() semantics + // require presence as "present on wire", and reflection-based merge + // (which uses HasField()) needs to be consistent with this. + switch (field->cpp_type()) { + case FieldDescriptor::CPPTYPE_STRING: + switch (field->options().ctype()) { + default: { + if (IsInlined(field)) { + return !GetField<InlinedStringField>(message, field) + .GetNoArena() + .empty(); + } + + return GetField<ArenaStringPtr>(message, field).Get().size() > 0; + } + } + return false; + case FieldDescriptor::CPPTYPE_BOOL: + return GetRaw<bool>(message, field) != false; + case FieldDescriptor::CPPTYPE_INT32: + return GetRaw<int32_t>(message, field) != 0; + case FieldDescriptor::CPPTYPE_INT64: + return GetRaw<int64_t>(message, field) != 0; + case FieldDescriptor::CPPTYPE_UINT32: + return GetRaw<uint32_t>(message, field) != 0; + case FieldDescriptor::CPPTYPE_UINT64: + return GetRaw<uint64_t>(message, field) != 0; + case FieldDescriptor::CPPTYPE_FLOAT: + static_assert(sizeof(uint32_t) == sizeof(float), + "Code assumes uint32_t and float are the same size."); + return GetRaw<uint32_t>(message, field) != 0; + case FieldDescriptor::CPPTYPE_DOUBLE: + static_assert(sizeof(uint64_t) == sizeof(double), + "Code assumes uint64_t and double are the same size."); + return GetRaw<uint64_t>(message, field) != 0; + case FieldDescriptor::CPPTYPE_ENUM: + return GetRaw<int>(message, field) != 0; + case FieldDescriptor::CPPTYPE_MESSAGE: + // handled above; avoid warning + break; + } + GOOGLE_LOG(FATAL) << "Reached impossible case in HasBit()."; + return false; + } +} + +void Reflection::SetBit(Message* message, const FieldDescriptor* field) const { + GOOGLE_DCHECK(!field->options().weak()); + const uint32_t index = schema_.HasBitIndex(field); + if (index == static_cast<uint32_t>(-1)) return; + MutableHasBits(message)[index / 32] |= + (static_cast<uint32_t>(1) << (index % 32)); +} + +void Reflection::ClearBit(Message* message, + const FieldDescriptor* field) const { + GOOGLE_DCHECK(!field->options().weak()); + const uint32_t index = schema_.HasBitIndex(field); + if (index == static_cast<uint32_t>(-1)) return; + MutableHasBits(message)[index / 32] &= + ~(static_cast<uint32_t>(1) << (index % 32)); +} + +void Reflection::SwapBit(Message* message1, Message* message2, + const FieldDescriptor* field) const { + GOOGLE_DCHECK(!field->options().weak()); + if (!schema_.HasHasbits()) { + return; + } + bool temp_has_bit = HasBit(*message1, field); + if (HasBit(*message2, field)) { + SetBit(message1, field); + } else { + ClearBit(message1, field); + } + if (temp_has_bit) { + SetBit(message2, field); + } else { + ClearBit(message2, field); + } +} + +bool Reflection::HasOneof(const Message& message, + const OneofDescriptor* oneof_descriptor) const { + if (oneof_descriptor->is_synthetic()) { + return HasField(message, oneof_descriptor->field(0)); + } + return (GetOneofCase(message, oneof_descriptor) > 0); +} + +void Reflection::SetOneofCase(Message* message, + const FieldDescriptor* field) const { + *MutableOneofCase(message, field->containing_oneof()) = field->number(); +} + +void Reflection::ClearOneofField(Message* message, + const FieldDescriptor* field) const { + if (HasOneofField(*message, field)) { + ClearOneof(message, field->containing_oneof()); + } +} + +void Reflection::ClearOneof(Message* message, + const OneofDescriptor* oneof_descriptor) const { + if (oneof_descriptor->is_synthetic()) { + ClearField(message, oneof_descriptor->field(0)); + return; + } + // TODO(jieluo): Consider to cache the unused object instead of deleting + // it. It will be much faster if an application switches a lot from + // a few oneof fields. Time/space tradeoff + uint32_t oneof_case = GetOneofCase(*message, oneof_descriptor); + if (oneof_case > 0) { + const FieldDescriptor* field = descriptor_->FindFieldByNumber(oneof_case); + if (message->GetArenaForAllocation() == nullptr) { + switch (field->cpp_type()) { + case FieldDescriptor::CPPTYPE_STRING: { + switch (field->options().ctype()) { + default: // TODO(kenton): Support other string reps. + case FieldOptions::STRING: { + // Oneof string fields are never set as a default instance. + // We just need to pass some arbitrary default string to make it + // work. This allows us to not have the real default accessible + // from reflection. + MutableField<ArenaStringPtr>(message, field)->Destroy(); + break; + } + } + break; + } + + case FieldDescriptor::CPPTYPE_MESSAGE: + delete *MutableRaw<Message*>(message, field); + break; + default: + break; + } + } else { + } + + *MutableOneofCase(message, oneof_descriptor) = 0; + } +} + +#define HANDLE_TYPE(TYPE, CPPTYPE, CTYPE) \ + template <> \ + const RepeatedField<TYPE>& Reflection::GetRepeatedFieldInternal<TYPE>( \ + const Message& message, const FieldDescriptor* field) const { \ + return *static_cast<RepeatedField<TYPE>*>(MutableRawRepeatedField( \ + const_cast<Message*>(&message), field, CPPTYPE, CTYPE, nullptr)); \ + } \ + \ + template <> \ + RepeatedField<TYPE>* Reflection::MutableRepeatedFieldInternal<TYPE>( \ + Message * message, const FieldDescriptor* field) const { \ + return static_cast<RepeatedField<TYPE>*>( \ + MutableRawRepeatedField(message, field, CPPTYPE, CTYPE, nullptr)); \ + } + +HANDLE_TYPE(int32_t, FieldDescriptor::CPPTYPE_INT32, -1); +HANDLE_TYPE(int64_t, FieldDescriptor::CPPTYPE_INT64, -1); +HANDLE_TYPE(uint32_t, FieldDescriptor::CPPTYPE_UINT32, -1); +HANDLE_TYPE(uint64_t, FieldDescriptor::CPPTYPE_UINT64, -1); +HANDLE_TYPE(float, FieldDescriptor::CPPTYPE_FLOAT, -1); +HANDLE_TYPE(double, FieldDescriptor::CPPTYPE_DOUBLE, -1); +HANDLE_TYPE(bool, FieldDescriptor::CPPTYPE_BOOL, -1); + + +#undef HANDLE_TYPE + +void* Reflection::MutableRawRepeatedString(Message* message, + const FieldDescriptor* field, + bool is_string) const { + (void)is_string; // Parameter is used by Google-internal code. + return MutableRawRepeatedField(message, field, + FieldDescriptor::CPPTYPE_STRING, + FieldOptions::STRING, nullptr); +} + +// Template implementations of basic accessors. Inline because each +// template instance is only called from one location. These are +// used for all types except messages. +template <typename Type> +const Type& Reflection::GetField(const Message& message, + const FieldDescriptor* field) const { + return GetRaw<Type>(message, field); +} + +template <typename Type> +void Reflection::SetField(Message* message, const FieldDescriptor* field, + const Type& value) const { + bool real_oneof = schema_.InRealOneof(field); + if (real_oneof && !HasOneofField(*message, field)) { + ClearOneof(message, field->containing_oneof()); + } + *MutableRaw<Type>(message, field) = value; + real_oneof ? SetOneofCase(message, field) : SetBit(message, field); +} + +template <typename Type> +Type* Reflection::MutableField(Message* message, + const FieldDescriptor* field) const { + schema_.InRealOneof(field) ? SetOneofCase(message, field) + : SetBit(message, field); + return MutableRaw<Type>(message, field); +} + +template <typename Type> +const Type& Reflection::GetRepeatedField(const Message& message, + const FieldDescriptor* field, + int index) const { + return GetRaw<RepeatedField<Type> >(message, field).Get(index); +} + +template <typename Type> +const Type& Reflection::GetRepeatedPtrField(const Message& message, + const FieldDescriptor* field, + int index) const { + return GetRaw<RepeatedPtrField<Type> >(message, field).Get(index); +} + +template <typename Type> +void Reflection::SetRepeatedField(Message* message, + const FieldDescriptor* field, int index, + Type value) const { + MutableRaw<RepeatedField<Type> >(message, field)->Set(index, value); +} + +template <typename Type> +Type* Reflection::MutableRepeatedField(Message* message, + const FieldDescriptor* field, + int index) const { + RepeatedPtrField<Type>* repeated = + MutableRaw<RepeatedPtrField<Type> >(message, field); + return repeated->Mutable(index); +} + +template <typename Type> +void Reflection::AddField(Message* message, const FieldDescriptor* field, + const Type& value) const { + MutableRaw<RepeatedField<Type> >(message, field)->Add(value); +} + +template <typename Type> +Type* Reflection::AddField(Message* message, + const FieldDescriptor* field) const { + RepeatedPtrField<Type>* repeated = + MutableRaw<RepeatedPtrField<Type> >(message, field); + return repeated->Add(); +} + +MessageFactory* Reflection::GetMessageFactory() const { + return message_factory_; +} + +void* Reflection::RepeatedFieldData(Message* message, + const FieldDescriptor* field, + FieldDescriptor::CppType cpp_type, + const Descriptor* message_type) const { + GOOGLE_CHECK(field->is_repeated()); + GOOGLE_CHECK(field->cpp_type() == cpp_type || + (field->cpp_type() == FieldDescriptor::CPPTYPE_ENUM && + cpp_type == FieldDescriptor::CPPTYPE_INT32)) + << "The type parameter T in RepeatedFieldRef<T> API doesn't match " + << "the actual field type (for enums T should be the generated enum " + << "type or int32_t)."; + if (message_type != nullptr) { + GOOGLE_CHECK_EQ(message_type, field->message_type()); + } + if (field->is_extension()) { + return MutableExtensionSet(message)->MutableRawRepeatedField( + field->number(), field->type(), field->is_packed(), field); + } else { + return MutableRawNonOneof<char>(message, field); + } +} + +MapFieldBase* Reflection::MutableMapData(Message* message, + const FieldDescriptor* field) const { + USAGE_CHECK(IsMapFieldInApi(field), "GetMapData", + "Field is not a map field."); + return MutableRaw<MapFieldBase>(message, field); +} + +const MapFieldBase* Reflection::GetMapData(const Message& message, + const FieldDescriptor* field) const { + USAGE_CHECK(IsMapFieldInApi(field), "GetMapData", + "Field is not a map field."); + return &(GetRaw<MapFieldBase>(message, field)); +} + +namespace { + +// Helper function to transform migration schema into reflection schema. +ReflectionSchema MigrationToReflectionSchema( + const Message* const* default_instance, const uint32_t* offsets, + MigrationSchema migration_schema) { + ReflectionSchema result; + result.default_instance_ = *default_instance; + // First 7 offsets are offsets to the special fields. The following offsets + // are the proto fields. + result.offsets_ = offsets + migration_schema.offsets_index + 6; + result.has_bit_indices_ = offsets + migration_schema.has_bit_indices_index; + result.has_bits_offset_ = offsets[migration_schema.offsets_index + 0]; + result.metadata_offset_ = offsets[migration_schema.offsets_index + 1]; + result.extensions_offset_ = offsets[migration_schema.offsets_index + 2]; + result.oneof_case_offset_ = offsets[migration_schema.offsets_index + 3]; + result.object_size_ = migration_schema.object_size; + result.weak_field_map_offset_ = offsets[migration_schema.offsets_index + 4]; + result.inlined_string_donated_offset_ = + offsets[migration_schema.offsets_index + 5]; + result.inlined_string_indices_ = + offsets + migration_schema.inlined_string_indices_index; + return result; +} + +} // namespace + +class AssignDescriptorsHelper { + public: + AssignDescriptorsHelper(MessageFactory* factory, + Metadata* file_level_metadata, + const EnumDescriptor** file_level_enum_descriptors, + const MigrationSchema* schemas, + const Message* const* default_instance_data, + const uint32_t* offsets) + : factory_(factory), + file_level_metadata_(file_level_metadata), + file_level_enum_descriptors_(file_level_enum_descriptors), + schemas_(schemas), + default_instance_data_(default_instance_data), + offsets_(offsets) {} + + void AssignMessageDescriptor(const Descriptor* descriptor) { + for (int i = 0; i < descriptor->nested_type_count(); i++) { + AssignMessageDescriptor(descriptor->nested_type(i)); + } + + file_level_metadata_->descriptor = descriptor; + + file_level_metadata_->reflection = + new Reflection(descriptor, + MigrationToReflectionSchema(default_instance_data_, + offsets_, *schemas_), + DescriptorPool::internal_generated_pool(), factory_); + for (int i = 0; i < descriptor->enum_type_count(); i++) { + AssignEnumDescriptor(descriptor->enum_type(i)); + } + schemas_++; + default_instance_data_++; + file_level_metadata_++; + } + + void AssignEnumDescriptor(const EnumDescriptor* descriptor) { + *file_level_enum_descriptors_ = descriptor; + file_level_enum_descriptors_++; + } + + const Metadata* GetCurrentMetadataPtr() const { return file_level_metadata_; } + + private: + MessageFactory* factory_; + Metadata* file_level_metadata_; + const EnumDescriptor** file_level_enum_descriptors_; + const MigrationSchema* schemas_; + const Message* const* default_instance_data_; + const uint32_t* offsets_; +}; + +namespace { + +// We have the routines that assign descriptors and build reflection +// automatically delete the allocated reflection. MetadataOwner owns +// all the allocated reflection instances. +struct MetadataOwner { + ~MetadataOwner() { + for (auto range : metadata_arrays_) { + for (const Metadata* m = range.first; m < range.second; m++) { + delete m->reflection; + } + } + } + + void AddArray(const Metadata* begin, const Metadata* end) { + mu_.Lock(); + metadata_arrays_.push_back(std::make_pair(begin, end)); + mu_.Unlock(); + } + + static MetadataOwner* Instance() { + static MetadataOwner* res = OnShutdownDelete(new MetadataOwner); + return res; + } + + private: + MetadataOwner() = default; // private because singleton + + WrappedMutex mu_; + std::vector<std::pair<const Metadata*, const Metadata*> > metadata_arrays_; +}; + +void AddDescriptors(const DescriptorTable* table); + +void AssignDescriptorsImpl(const DescriptorTable* table, bool eager) { + // Ensure the file descriptor is added to the pool. + { + // This only happens once per proto file. So a global mutex to serialize + // calls to AddDescriptors. + static WrappedMutex mu{GOOGLE_PROTOBUF_LINKER_INITIALIZED}; + mu.Lock(); + AddDescriptors(table); + mu.Unlock(); + } + if (eager) { + // Normally we do not want to eagerly build descriptors of our deps. + // However if this proto is optimized for code size (ie using reflection) + // and it has a message extending a custom option of a descriptor with that + // message being optimized for code size as well. Building the descriptors + // in this file requires parsing the serialized file descriptor, which now + // requires parsing the message extension, which potentially requires + // building the descriptor of the message extending one of the options. + // However we are already updating descriptor pool under a lock. To prevent + // this the compiler statically looks for this case and we just make sure we + // first build the descriptors of all our dependencies, preventing the + // deadlock. + int num_deps = table->num_deps; + for (int i = 0; i < num_deps; i++) { + // In case of weak fields deps[i] could be null. + if (table->deps[i]) AssignDescriptors(table->deps[i], true); + } + } + + // Fill the arrays with pointers to descriptors and reflection classes. + const FileDescriptor* file = + DescriptorPool::internal_generated_pool()->FindFileByName( + table->filename); + GOOGLE_CHECK(file != nullptr); + + MessageFactory* factory = MessageFactory::generated_factory(); + + AssignDescriptorsHelper helper( + factory, table->file_level_metadata, table->file_level_enum_descriptors, + table->schemas, table->default_instances, table->offsets); + + for (int i = 0; i < file->message_type_count(); i++) { + helper.AssignMessageDescriptor(file->message_type(i)); + } + + for (int i = 0; i < file->enum_type_count(); i++) { + helper.AssignEnumDescriptor(file->enum_type(i)); + } + if (file->options().cc_generic_services()) { + for (int i = 0; i < file->service_count(); i++) { + table->file_level_service_descriptors[i] = file->service(i); + } + } + MetadataOwner::Instance()->AddArray(table->file_level_metadata, + helper.GetCurrentMetadataPtr()); +} + +void AddDescriptorsImpl(const DescriptorTable* table) { + // Reflection refers to the default fields so make sure they are initialized. + internal::InitProtobufDefaults(); + + // Ensure all dependent descriptors are registered to the generated descriptor + // pool and message factory. + int num_deps = table->num_deps; + for (int i = 0; i < num_deps; i++) { + // In case of weak fields deps[i] could be null. + if (table->deps[i]) AddDescriptors(table->deps[i]); + } + + // Register the descriptor of this file. + DescriptorPool::InternalAddGeneratedFile(table->descriptor, table->size); + MessageFactory::InternalRegisterGeneratedFile(table); +} + +void AddDescriptors(const DescriptorTable* table) { + // AddDescriptors is not thread safe. Callers need to ensure calls are + // properly serialized. This function is only called pre-main by global + // descriptors and we can assume single threaded access or it's called + // by AssignDescriptorImpl which uses a mutex to sequence calls. + if (table->is_initialized) return; + table->is_initialized = true; + AddDescriptorsImpl(table); +} + +} // namespace + +// Separate function because it needs to be a friend of +// Reflection +void RegisterAllTypesInternal(const Metadata* file_level_metadata, int size) { + for (int i = 0; i < size; i++) { + const Reflection* reflection = file_level_metadata[i].reflection; + MessageFactory::InternalRegisterGeneratedMessage( + file_level_metadata[i].descriptor, + reflection->schema_.default_instance_); + } +} + +namespace internal { + +Metadata AssignDescriptors(const DescriptorTable* (*table)(), + internal::once_flag* once, + const Metadata& metadata) { + call_once(*once, [=] { + auto* t = table(); + AssignDescriptorsImpl(t, t->is_eager); + }); + + return metadata; +} + +void AssignDescriptors(const DescriptorTable* table, bool eager) { + if (!eager) eager = table->is_eager; + call_once(*table->once, AssignDescriptorsImpl, table, eager); +} + +AddDescriptorsRunner::AddDescriptorsRunner(const DescriptorTable* table) { + AddDescriptors(table); +} + +void RegisterFileLevelMetadata(const DescriptorTable* table) { + AssignDescriptors(table); + RegisterAllTypesInternal(table->file_level_metadata, table->num_messages); +} + +void UnknownFieldSetSerializer(const uint8_t* base, uint32_t offset, + uint32_t /*tag*/, uint32_t /*has_offset*/, + io::CodedOutputStream* output) { + const void* ptr = base + offset; + const InternalMetadata* metadata = static_cast<const InternalMetadata*>(ptr); + if (metadata->have_unknown_fields()) { + metadata->unknown_fields<UnknownFieldSet>(UnknownFieldSet::default_instance) + .SerializeToCodedStream(output); + } +} + +bool IsDescendant(Message& root, const Message& message) { + const Reflection* reflection = root.GetReflection(); + std::vector<const FieldDescriptor*> fields; + reflection->ListFieldsOmitStripped(root, &fields); + + for (const auto* field : fields) { + // Skip non-message fields. + if (field->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE) continue; + + // Optional messages. + if (!field->is_repeated()) { + Message* sub_message = reflection->MutableMessage(&root, field); + if (sub_message == &message || IsDescendant(*sub_message, message)) { + return true; + } + continue; + } + + // Repeated messages. + if (!IsMapFieldInApi(field)) { + int count = reflection->FieldSize(root, field); + for (int i = 0; i < count; i++) { + Message* sub_message = + reflection->MutableRepeatedMessage(&root, field, i); + if (sub_message == &message || IsDescendant(*sub_message, message)) { + return true; + } + } + continue; + } + + // Map field: if accessed as repeated fields, messages are *copied* and + // matching pointer won't work. Must directly access map. + constexpr int kValIdx = 1; + const FieldDescriptor* val_field = field->message_type()->field(kValIdx); + // Skip map fields whose value type is not message. + if (val_field->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE) continue; + + MapIterator end = reflection->MapEnd(&root, field); + for (auto iter = reflection->MapBegin(&root, field); iter != end; ++iter) { + Message* sub_message = iter.MutableValueRef()->MutableMessageValue(); + if (sub_message == &message || IsDescendant(*sub_message, message)) { + return true; + } + } + } + + return false; +} + +} // namespace internal +} // namespace protobuf +} // namespace google + +#include <google/protobuf/port_undef.inc> diff --git a/toolkit/components/protobuf/src/google/protobuf/generated_message_reflection.h b/toolkit/components/protobuf/src/google/protobuf/generated_message_reflection.h new file mode 100644 index 0000000000..334b2ccf1d --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/generated_message_reflection.h @@ -0,0 +1,354 @@ +// 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. + +// Author: kenton@google.com (Kenton Varda) +// Based on original Protocol Buffers design by +// Sanjay Ghemawat, Jeff Dean, and others. +// +// This header is logically internal, but is made public because it is used +// from protocol-compiler-generated code, which may reside in other components. + +#ifndef GOOGLE_PROTOBUF_GENERATED_MESSAGE_REFLECTION_H__ +#define GOOGLE_PROTOBUF_GENERATED_MESSAGE_REFLECTION_H__ + +#include <google/protobuf/stubs/casts.h> +#include <google/protobuf/stubs/common.h> +#include <google/protobuf/stubs/once.h> +#include <google/protobuf/port.h> +#include <google/protobuf/descriptor.h> +#include <google/protobuf/generated_enum_reflection.h> +#include <google/protobuf/unknown_field_set.h> + + +// Must be included last. +#include <google/protobuf/port_def.inc> + +#ifdef SWIG +#error "You cannot SWIG proto headers" +#endif + +namespace google { +namespace protobuf { +class MapKey; +class MapValueRef; +class MessageLayoutInspector; +class Message; +struct Metadata; +} // namespace protobuf +} // namespace google + +namespace google { +namespace protobuf { +namespace internal { +class DefaultEmptyOneof; +// Defined in other files. +class ExtensionSet; // extension_set.h +class WeakFieldMap; // weak_field_map.h + +// This struct describes the internal layout of the message, hence this is +// used to act on the message reflectively. +// default_instance: The default instance of the message. This is only +// used to obtain pointers to default instances of embedded +// messages, which GetMessage() will return if the particular +// sub-message has not been initialized yet. (Thus, all +// embedded message fields *must* have non-null pointers +// in the default instance.) +// offsets: An array of ints giving the byte offsets. +// For each oneof or weak field, the offset is relative to the +// default_instance. These can be computed at compile time +// using the +// PROTO2_GENERATED_DEFAULT_ONEOF_FIELD_OFFSET() +// macro. For each none oneof field, the offset is related to +// the start of the message object. These can be computed at +// compile time using the +// PROTO2_GENERATED_MESSAGE_FIELD_OFFSET() macro. +// Besides offsets for all fields, this array also contains +// offsets for oneof unions. The offset of the i-th oneof union +// is offsets[descriptor->field_count() + i]. +// has_bit_indices: Mapping from field indexes to their index in the has +// bit array. +// has_bits_offset: Offset in the message of an array of uint32s of size +// descriptor->field_count()/32, rounded up. This is a +// bitfield where each bit indicates whether or not the +// corresponding field of the message has been initialized. +// The bit for field index i is obtained by the expression: +// has_bits[i / 32] & (1 << (i % 32)) +// unknown_fields_offset: Offset in the message of the UnknownFieldSet for +// the message. +// extensions_offset: Offset in the message of the ExtensionSet for the +// message, or -1 if the message type has no extension +// ranges. +// oneof_case_offset: Offset in the message of an array of uint32s of +// size descriptor->oneof_decl_count(). Each uint32_t +// indicates what field is set for each oneof. +// object_size: The size of a message object of this type, as measured +// by sizeof(). +// arena_offset: If a message doesn't have a unknown_field_set that stores +// the arena, it must have a direct pointer to the arena. +// weak_field_map_offset: If the message proto has weak fields, this is the +// offset of _weak_field_map_ in the generated proto. Otherwise +// -1. +struct ReflectionSchema { + public: + // Size of a google::protobuf::Message object of this type. + uint32_t GetObjectSize() const { return static_cast<uint32_t>(object_size_); } + + bool InRealOneof(const FieldDescriptor* field) const { + return field->containing_oneof() && + !field->containing_oneof()->is_synthetic(); + } + + // Offset of a non-oneof field. Getting a field offset is slightly more + // efficient when we know statically that it is not a oneof field. + uint32_t GetFieldOffsetNonOneof(const FieldDescriptor* field) const { + GOOGLE_DCHECK(!InRealOneof(field)); + return OffsetValue(offsets_[field->index()], field->type()); + } + + // Offset of any field. + uint32_t GetFieldOffset(const FieldDescriptor* field) const { + if (InRealOneof(field)) { + size_t offset = + static_cast<size_t>(field->containing_type()->field_count()) + + field->containing_oneof()->index(); + return OffsetValue(offsets_[offset], field->type()); + } else { + return GetFieldOffsetNonOneof(field); + } + } + + bool IsFieldInlined(const FieldDescriptor* field) const { + return Inlined(offsets_[field->index()], field->type()); + } + + uint32_t GetOneofCaseOffset(const OneofDescriptor* oneof_descriptor) const { + return static_cast<uint32_t>(oneof_case_offset_) + + static_cast<uint32_t>( + static_cast<size_t>(oneof_descriptor->index()) * + sizeof(uint32_t)); + } + + bool HasHasbits() const { return has_bits_offset_ != -1; } + + // Bit index within the bit array of hasbits. Bit order is low-to-high. + uint32_t HasBitIndex(const FieldDescriptor* field) const { + if (has_bits_offset_ == -1) return static_cast<uint32_t>(-1); + GOOGLE_DCHECK(HasHasbits()); + return has_bit_indices_[field->index()]; + } + + // Byte offset of the hasbits array. + uint32_t HasBitsOffset() const { + GOOGLE_DCHECK(HasHasbits()); + return static_cast<uint32_t>(has_bits_offset_); + } + + bool HasInlinedString() const { return inlined_string_donated_offset_ != -1; } + + // Bit index within the bit array of _inlined_string_donated_. Bit order is + // low-to-high. + uint32_t InlinedStringIndex(const FieldDescriptor* field) const { + GOOGLE_DCHECK(HasInlinedString()); + return inlined_string_indices_[field->index()]; + } + + // Byte offset of the _inlined_string_donated_ array. + uint32_t InlinedStringDonatedOffset() const { + GOOGLE_DCHECK(HasInlinedString()); + return static_cast<uint32_t>(inlined_string_donated_offset_); + } + + // The offset of the InternalMetadataWithArena member. + // For Lite this will actually be an InternalMetadataWithArenaLite. + // The schema doesn't contain enough information to distinguish between + // these two cases. + uint32_t GetMetadataOffset() const { + return static_cast<uint32_t>(metadata_offset_); + } + + // Whether this message has an ExtensionSet. + bool HasExtensionSet() const { return extensions_offset_ != -1; } + + // The offset of the ExtensionSet in this message. + uint32_t GetExtensionSetOffset() const { + GOOGLE_DCHECK(HasExtensionSet()); + return static_cast<uint32_t>(extensions_offset_); + } + + // The off set of WeakFieldMap when the message contains weak fields. + // The default is 0 for now. + int GetWeakFieldMapOffset() const { return weak_field_map_offset_; } + + bool IsDefaultInstance(const Message& message) const { + return &message == default_instance_; + } + + // Returns a pointer to the default value for this field. The size and type + // of the underlying data depends on the field's type. + const void* GetFieldDefault(const FieldDescriptor* field) const { + return reinterpret_cast<const uint8_t*>(default_instance_) + + OffsetValue(offsets_[field->index()], field->type()); + } + + // Returns true if the field is implicitly backed by LazyField. + bool IsEagerlyVerifiedLazyField(const FieldDescriptor* field) const { + GOOGLE_DCHECK_EQ(field->type(), FieldDescriptor::TYPE_MESSAGE); + (void)field; + return false; + } + + bool IsFieldStripped(const FieldDescriptor* field) const { + (void)field; + return false; + } + + bool IsMessageStripped(const Descriptor* descriptor) const { + (void)descriptor; + return false; + } + + + bool HasWeakFields() const { return weak_field_map_offset_ > 0; } + + // These members are intended to be private, but we cannot actually make them + // private because this prevents us from using aggregate initialization of + // them, ie. + // + // ReflectionSchema schema = {a, b, c, d, e, ...}; + // private: + const Message* default_instance_; + const uint32_t* offsets_; + const uint32_t* has_bit_indices_; + int has_bits_offset_; + int metadata_offset_; + int extensions_offset_; + int oneof_case_offset_; + int object_size_; + int weak_field_map_offset_; + const uint32_t* inlined_string_indices_; + int inlined_string_donated_offset_; + + // We tag offset values to provide additional data about fields (such as + // "unused" or "lazy" or "inlined"). + static uint32_t OffsetValue(uint32_t v, FieldDescriptor::Type type) { + if (type == FieldDescriptor::TYPE_MESSAGE || + type == FieldDescriptor::TYPE_STRING || + type == FieldDescriptor::TYPE_BYTES) { + return v & 0xFFFFFFFEu; + } + return v; + } + + static bool Inlined(uint32_t v, FieldDescriptor::Type type) { + if (type == FieldDescriptor::TYPE_STRING || + type == FieldDescriptor::TYPE_BYTES) { + return (v & 1u) != 0u; + } else { + // Non string/byte fields are not inlined. + return false; + } + } +}; + +// Structs that the code generator emits directly to describe a message. +// These should never used directly except to build a ReflectionSchema +// object. +// +// EXPERIMENTAL: these are changing rapidly, and may completely disappear +// or merge with ReflectionSchema. +struct MigrationSchema { + int32_t offsets_index; + int32_t has_bit_indices_index; + int32_t inlined_string_indices_index; + int object_size; +}; + +// This struct tries to reduce unnecessary padding. +// The num_xxx might not be close to their respective pointer, but this saves +// padding. +struct PROTOBUF_EXPORT DescriptorTable { + mutable bool is_initialized; + bool is_eager; + int size; // of serialized descriptor + const char* descriptor; + const char* filename; + once_flag* once; + const DescriptorTable* const* deps; + int num_deps; + int num_messages; + const MigrationSchema* schemas; + const Message* const* default_instances; + const uint32_t* offsets; + // update the following descriptor arrays. + Metadata* file_level_metadata; + const EnumDescriptor** file_level_enum_descriptors; + const ServiceDescriptor** file_level_service_descriptors; +}; + +enum { + // Tag used on offsets for fields that don't have a real offset. + // For example, weak message fields go into the WeakFieldMap and not in an + // actual field. + kInvalidFieldOffsetTag = 0x40000000u, +}; + +// AssignDescriptors() pulls the compiled FileDescriptor from the DescriptorPool +// and uses it to populate all of the global variables which store pointers to +// the descriptor objects. It also constructs the reflection objects. It is +// called the first time anyone calls descriptor() or GetReflection() on one of +// the types defined in the file. AssignDescriptors() is thread-safe. +void PROTOBUF_EXPORT AssignDescriptors(const DescriptorTable* table, + bool eager = false); + +// Overload used to implement GetMetadataStatic in the generated code. +// See comments in compiler/cpp/internal/file.cc as to why. +// It takes a `Metadata` and returns it to allow for tail calls and reduce +// binary size. +Metadata PROTOBUF_EXPORT AssignDescriptors(const DescriptorTable* (*table)(), + internal::once_flag* once, + const Metadata& metadata); + +// These cannot be in lite so we put them in the reflection. +PROTOBUF_EXPORT void UnknownFieldSetSerializer(const uint8_t* base, + uint32_t offset, uint32_t tag, + uint32_t has_offset, + io::CodedOutputStream* output); + +struct PROTOBUF_EXPORT AddDescriptorsRunner { + explicit AddDescriptorsRunner(const DescriptorTable* table); +}; + +} // namespace internal +} // namespace protobuf +} // namespace google + +#include <google/protobuf/port_undef.inc> + +#endif // GOOGLE_PROTOBUF_GENERATED_MESSAGE_REFLECTION_H__ diff --git a/toolkit/components/protobuf/src/google/protobuf/generated_message_tctable_decl.h b/toolkit/components/protobuf/src/google/protobuf/generated_message_tctable_decl.h new file mode 100644 index 0000000000..b1bb1def70 --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/generated_message_tctable_decl.h @@ -0,0 +1,312 @@ +// 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. + +// This file contains declarations needed in generated headers for messages +// that use tail-call table parsing. Everything in this file is for internal +// use only. + +#ifndef GOOGLE_PROTOBUF_GENERATED_MESSAGE_TCTABLE_DECL_H__ +#define GOOGLE_PROTOBUF_GENERATED_MESSAGE_TCTABLE_DECL_H__ + +#include <array> +#include <cstddef> +#include <cstdint> +#include <type_traits> + +#include <google/protobuf/message_lite.h> +#include <google/protobuf/parse_context.h> + +// Must come last: +#include <google/protobuf/port_def.inc> + +namespace google { +namespace protobuf { +namespace internal { + +// Additional information about this field: +struct TcFieldData { + constexpr TcFieldData() : data(0) {} + + // Fast table entry constructor: + constexpr TcFieldData(uint16_t coded_tag, uint8_t hasbit_idx, uint8_t aux_idx, + uint16_t offset) + : data(uint64_t{offset} << 48 | // + uint64_t{aux_idx} << 24 | // + uint64_t{hasbit_idx} << 16 | // + uint64_t{coded_tag}) {} + + // Fields used in fast table parsing: + // + // Bit: + // +-----------+-------------------+ + // |63 .. 32|31 .. 0| + // +---------------+---------------+ + // : . : . : . 16|=======| [16] coded_tag() + // : . : . : 24|===| . : [ 8] hasbit_idx() + // : . : . 32|===| : . : [ 8] aux_idx() + // : . 48:---.---: . : . : [16] (unused) + // |=======| . : . : . : [16] offset() + // +-----------+-------------------+ + // |63 .. 32|31 .. 0| + // +---------------+---------------+ + + template <typename TagType = uint16_t> + TagType coded_tag() const { + return static_cast<TagType>(data); + } + uint8_t hasbit_idx() const { return static_cast<uint8_t>(data >> 16); } + uint8_t aux_idx() const { return static_cast<uint8_t>(data >> 24); } + uint16_t offset() const { return static_cast<uint16_t>(data >> 48); } + + // Fields used in mini table parsing: + // + // Bit: + // +-----------+-------------------+ + // |63 .. 32|31 .. 0| + // +---------------+---------------+ + // : . : . |===============| [32] tag() (decoded) + // |===============| . : . : [32] entry_offset() + // +-----------+-------------------+ + // |63 .. 32|31 .. 0| + // +---------------+---------------+ + + uint32_t tag() const { return static_cast<uint32_t>(data); } + uint32_t entry_offset() const { return static_cast<uint32_t>(data >> 32); } + + uint64_t data; +}; + +struct TcParseTableBase; + +// TailCallParseFunc is the function pointer type used in the tailcall table. +typedef const char* (*TailCallParseFunc)(PROTOBUF_TC_PARAM_DECL); + +namespace field_layout { +struct Offset { + uint32_t off; +}; +} // namespace field_layout + +#if defined(_MSC_VER) && !defined(_WIN64) +#pragma warning(push) +// TcParseTableBase is intentionally overaligned on 32 bit targets. +#pragma warning(disable : 4324) +#endif + +// Base class for message-level table with info for the tail-call parser. +struct alignas(uint64_t) TcParseTableBase { + // Common attributes for message layout: + uint16_t has_bits_offset; + uint16_t extension_offset; + uint32_t extension_range_low; + uint32_t extension_range_high; + uint32_t max_field_number; + uint8_t fast_idx_mask; + uint16_t lookup_table_offset; + uint32_t skipmap32; + uint32_t field_entries_offset; + uint16_t num_field_entries; + + uint16_t num_aux_entries; + uint32_t aux_offset; + + const MessageLite* default_instance; + + // Handler for fields which are not handled by table dispatch. + TailCallParseFunc fallback; + + // This constructor exactly follows the field layout, so it's technically + // not necessary. However, it makes it much much easier to add or re-arrange + // fields, because it can be overloaded with an additional constructor, + // temporarily allowing both old and new protocol buffer headers to be + // compiled. + constexpr TcParseTableBase( + uint16_t has_bits_offset, uint16_t extension_offset, + uint32_t extension_range_low, uint32_t extension_range_high, + uint32_t max_field_number, uint8_t fast_idx_mask, + uint16_t lookup_table_offset, uint32_t skipmap32, + uint32_t field_entries_offset, uint16_t num_field_entries, + uint16_t num_aux_entries, uint32_t aux_offset, + const MessageLite* default_instance, TailCallParseFunc fallback) + : has_bits_offset(has_bits_offset), + extension_offset(extension_offset), + extension_range_low(extension_range_low), + extension_range_high(extension_range_high), + max_field_number(max_field_number), + fast_idx_mask(fast_idx_mask), + lookup_table_offset(lookup_table_offset), + skipmap32(skipmap32), + field_entries_offset(field_entries_offset), + num_field_entries(num_field_entries), + num_aux_entries(num_aux_entries), + aux_offset(aux_offset), + default_instance(default_instance), + fallback(fallback) {} + + // Table entry for fast-path tailcall dispatch handling. + struct FastFieldEntry { + // Target function for dispatch: + TailCallParseFunc target; + // Field data used during parse: + TcFieldData bits; + }; + // There is always at least one table entry. + const FastFieldEntry* fast_entry(size_t idx) const { + return reinterpret_cast<const FastFieldEntry*>(this + 1) + idx; + } + + // Returns a begin iterator (pointer) to the start of the field lookup table. + const uint16_t* field_lookup_begin() const { + return reinterpret_cast<const uint16_t*>(reinterpret_cast<uintptr_t>(this) + + lookup_table_offset); + } + + // Field entry for all fields. + struct FieldEntry { + uint32_t offset; // offset in the message object + int32_t has_idx; // has-bit index + uint16_t aux_idx; // index for `field_aux`. + uint16_t type_card; // `FieldType` and `Cardinality` (see _impl.h) + }; + + // Returns a begin iterator (pointer) to the start of the field entries array. + const FieldEntry* field_entries_begin() const { + return reinterpret_cast<const FieldEntry*>( + reinterpret_cast<uintptr_t>(this) + field_entries_offset); + } + + // Auxiliary entries for field types that need extra information. + union FieldAux { + constexpr FieldAux() : message_default(nullptr) {} + constexpr FieldAux(bool (*enum_validator)(int)) + : enum_validator(enum_validator) {} + constexpr FieldAux(field_layout::Offset off) : offset(off.off) {} + constexpr FieldAux(int16_t range_start, uint16_t range_length) + : enum_range{range_start, range_length} {} + constexpr FieldAux(const MessageLite* msg) : message_default(msg) {} + bool (*enum_validator)(int); + struct { + int16_t start; // minimum enum number (if it fits) + uint16_t length; // length of range (i.e., max = start + length - 1) + } enum_range; + uint32_t offset; + const MessageLite* message_default; + }; + const FieldAux* field_aux(uint32_t idx) const { + return reinterpret_cast<const FieldAux*>(reinterpret_cast<uintptr_t>(this) + + aux_offset) + + idx; + } + const FieldAux* field_aux(const FieldEntry* entry) const { + return field_aux(entry->aux_idx); + } + + // Field name data + const char* name_data() const { + return reinterpret_cast<const char*>(reinterpret_cast<uintptr_t>(this) + + aux_offset + + num_aux_entries * sizeof(FieldAux)); + } +}; + +#if defined(_MSC_VER) && !defined(_WIN64) +#pragma warning(pop) +#endif + +static_assert(sizeof(TcParseTableBase::FastFieldEntry) <= 16, + "Fast field entry is too big."); +static_assert(sizeof(TcParseTableBase::FieldEntry) <= 16, + "Field entry is too big."); + +template <size_t kFastTableSizeLog2, size_t kNumFieldEntries = 0, + size_t kNumFieldAux = 0, size_t kNameTableSize = 0, + size_t kFieldLookupSize = 2> +struct TcParseTable { + TcParseTableBase header; + + // Entries for each field. + // + // Fields are indexed by the lowest bits of their field number. The field + // number is masked to fit inside the table. Note that the parsing logic + // generally calls `TailCallParseTableBase::fast_entry()` instead of accessing + // this field directly. + std::array<TcParseTableBase::FastFieldEntry, (1 << kFastTableSizeLog2)> + fast_entries; + + // Just big enough to find all the field entries. + std::array<uint16_t, kFieldLookupSize> field_lookup_table; + // Entries for all fields: + std::array<TcParseTableBase::FieldEntry, kNumFieldEntries> field_entries; + std::array<TcParseTableBase::FieldAux, kNumFieldAux> aux_entries; + std::array<char, kNameTableSize> field_names; +}; + +// Partial specialization: if there are no aux entries, there will be no array. +// In C++, arrays cannot have length 0, but (C++11) std::array<T, 0> is valid. +// However, different implementations have different sizeof(std::array<T, 0>). +// Skipping the member makes offset computations portable. +template <size_t kFastTableSizeLog2, size_t kNumFieldEntries, + size_t kNameTableSize, size_t kFieldLookupSize> +struct TcParseTable<kFastTableSizeLog2, kNumFieldEntries, 0, kNameTableSize, + kFieldLookupSize> { + TcParseTableBase header; + std::array<TcParseTableBase::FastFieldEntry, (1 << kFastTableSizeLog2)> + fast_entries; + std::array<uint16_t, kFieldLookupSize> field_lookup_table; + std::array<TcParseTableBase::FieldEntry, kNumFieldEntries> field_entries; + std::array<char, kNameTableSize> field_names; +}; + +// Partial specialization: if there are no fields at all, then we can save space +// by skipping the field numbers and entries. +template <size_t kNameTableSize, size_t kFieldLookupSize> +struct TcParseTable<0, 0, 0, kNameTableSize, kFieldLookupSize> { + TcParseTableBase header; + // N.B.: the fast entries are sized by log2, so 2**0 fields = 1 entry. + // The fast parsing loop will always use this entry, so it must be present. + std::array<TcParseTableBase::FastFieldEntry, 1> fast_entries; + std::array<uint16_t, kFieldLookupSize> field_lookup_table; + std::array<char, kNameTableSize> field_names; +}; + +static_assert(std::is_standard_layout<TcParseTable<1>>::value, + "TcParseTable must be standard layout."); + +static_assert(offsetof(TcParseTable<1>, fast_entries) == + sizeof(TcParseTableBase), + "Table entries must be laid out after TcParseTableBase."); + +} // namespace internal +} // namespace protobuf +} // namespace google + +#include <google/protobuf/port_undef.inc> + +#endif // GOOGLE_PROTOBUF_GENERATED_MESSAGE_TCTABLE_DECL_H__ diff --git a/toolkit/components/protobuf/src/google/protobuf/generated_message_tctable_full.cc b/toolkit/components/protobuf/src/google/protobuf/generated_message_tctable_full.cc new file mode 100644 index 0000000000..b77bb8d8e3 --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/generated_message_tctable_full.cc @@ -0,0 +1,53 @@ +// 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. + +#include <cstdint> + +#include <google/protobuf/extension_set.h> +#include <google/protobuf/generated_message_tctable_impl.h> +#include <google/protobuf/message.h> +#include <google/protobuf/parse_context.h> +#include <google/protobuf/unknown_field_set.h> + +// clang-format off +#include <google/protobuf/port_def.inc> +// clang-format on + +namespace google { +namespace protobuf { +namespace internal { + +const char* TcParser::GenericFallback(PROTOBUF_TC_PARAM_DECL) { + return GenericFallbackImpl<Message, UnknownFieldSet>(PROTOBUF_TC_PARAM_PASS); +} + +} // namespace internal +} // namespace protobuf +} // namespace google diff --git a/toolkit/components/protobuf/src/google/protobuf/generated_message_tctable_impl.h b/toolkit/components/protobuf/src/google/protobuf/generated_message_tctable_impl.h new file mode 100644 index 0000000000..21fa5332d3 --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/generated_message_tctable_impl.h @@ -0,0 +1,553 @@ +// 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. + +#ifndef GOOGLE_PROTOBUF_GENERATED_MESSAGE_TCTABLE_IMPL_H__ +#define GOOGLE_PROTOBUF_GENERATED_MESSAGE_TCTABLE_IMPL_H__ + +#include <cstdint> +#include <type_traits> + +#include <google/protobuf/port.h> +#include <google/protobuf/extension_set.h> +#include <google/protobuf/generated_message_tctable_decl.h> +#include <google/protobuf/message_lite.h> +#include <google/protobuf/metadata_lite.h> +#include <google/protobuf/parse_context.h> +#include <google/protobuf/wire_format_lite.h> + +// Must come last: +#include <google/protobuf/port_def.inc> + +namespace google { +namespace protobuf { + +class Message; +class UnknownFieldSet; + +namespace internal { + +// Field layout enums. +// +// Structural information about fields is packed into a 16-bit value. The enum +// types below represent bitwise fields, along with their respective widths, +// shifts, and masks. +// +// Bit: +// +-----------------------+-----------------------+ +// |15 .. 8|7 .. 0| +// +-----------------------+-----------------------+ +// : . : . : . : . : . : . : 3|========| [3] FieldType +// : : : : : : 5|=====| : : [2] FieldCardinality +// : . : . : . : . 8|========| : . : . : [3] FieldRep +// : : : 10|=====| : : : : [2] TransformValidation +// : . : .12|=====| . : . : . : . : . : [2] FormatDiscriminator +// +-----------------------+-----------------------+ +// |15 .. 8|7 .. 0| +// +-----------------------+-----------------------+ +// +namespace field_layout { +// clang-format off + +// Field kind (3 bits): +// These values broadly represent a wire type and an in-memory storage class. +enum FieldKind : uint16_t { + kFkShift = 0, + kFkBits = 3, + kFkMask = ((1 << kFkBits) - 1) << kFkShift, + + kFkNone = 0, + kFkVarint, // WT=0 rep=8,32,64 bits + kFkPackedVarint, // WT=2 rep=8,32,64 bits + kFkFixed, // WT=1,5 rep=32,64 bits + kFkPackedFixed, // WT=2 rep=32,64 bits + kFkString, // WT=2 rep=various + kFkMessage, // WT=2,3,4 rep=MessageLite* + // Maps are a special case of Message, but use different parsing logic. + kFkMap, // WT=2 rep=Map(Lite)<various, various> +}; + +static_assert(kFkMap < (1 << kFkBits), "too many types"); + +// Cardinality (2 bits): +// These values determine how many values a field can have and its presence. +// Packed fields are represented in FieldType. +enum Cardinality : uint16_t { + kFcShift = kFkShift + kFkBits, + kFcBits = 2, + kFcMask = ((1 << kFcBits) - 1) << kFcShift, + + kFcSingular = 0, + kFcOptional = 1 << kFcShift, + kFcRepeated = 2 << kFcShift, + kFcOneof = 3 << kFcShift, +}; + +// Field representation (3 bits): +// These values are the specific refinements of storage classes in FieldType. +enum FieldRep : uint16_t { + kRepShift = kFcShift + kFcBits, + kRepBits = 3, + kRepMask = ((1 << kRepBits) - 1) << kRepShift, + + // Numeric types (used for optional and repeated fields): + kRep8Bits = 0, + kRep32Bits = 2 << kRepShift, + kRep64Bits = 3 << kRepShift, + // String types: + kRepAString = 0, // ArenaStringPtr + kRepIString = 1 << kRepShift, // InlinedString + kRepCord = 2 << kRepShift, // absl::Cord + kRepSPiece = 3 << kRepShift, // StringPieceField + kRepSString = 4 << kRepShift, // std::string* + // Message types (WT=2 unless otherwise noted): + kRepMessage = 0, // MessageLite* + kRepGroup = 1 << kRepShift, // MessageLite* (WT=3,4) + kRepLazy = 2 << kRepShift, // LazyField* + kRepIWeak = 3 << kRepShift, // ImplicitWeak +}; + +// Transform/validation (2 bits): +// These values determine transforms or validation to/from wire format. +enum TransformValidation : uint16_t { + kTvShift = kRepShift + kRepBits, + kTvBits = 2, + kTvMask = ((1 << kTvBits) - 1) << kTvShift, + + // Varint fields: + kTvZigZag = 1 << kTvShift, + kTvEnum = 2 << kTvShift, // validate using generated _IsValid() + kTvRange = 3 << kTvShift, // validate using FieldAux::enum_range + // String fields: + kTvUtf8Debug = 1 << kTvShift, // proto2 + kTvUtf8 = 2 << kTvShift, // proto3 +}; + +static_assert((kTvEnum & kTvRange) != 0, + "enum validation types must share a bit"); +static_assert((kTvEnum & kTvRange & kTvZigZag) == 0, + "zigzag encoding is not enum validation"); + +// Format discriminators (2 bits): +enum FormatDiscriminator : uint16_t { + kFmtShift = kTvShift + kTvBits, + kFmtBits = 2, + kFmtMask = ((1 << kFmtBits) - 1) << kFmtShift, + + // Numeric: + kFmtUnsigned = 1 << kFmtShift, // fixed, varint + kFmtSigned = 2 << kFmtShift, // fixed, varint + kFmtFloating = 3 << kFmtShift, // fixed + kFmtEnum = 3 << kFmtShift, // varint + // Strings: + kFmtUtf8 = 1 << kFmtShift, // string (proto3, enforce_utf8=true) + kFmtUtf8Escape = 2 << kFmtShift, // string (proto2, enforce_utf8=false) + // Bytes: + kFmtArray = 1 << kFmtShift, // bytes + // Messages: + kFmtShow = 1 << kFmtShift, // message, map +}; + +// Update this assertion (and comments above) when adding or removing bits: +static_assert(kFmtShift + kFmtBits == 12, "number of bits changed"); + +// This assertion should not change unless the storage width changes: +static_assert(kFmtShift + kFmtBits <= 16, "too many bits"); + +// Convenience aliases (16 bits, with format): +enum FieldType : uint16_t { + // Numeric types: + kBool = kFkVarint | kRep8Bits, + + kFixed32 = kFkFixed | kRep32Bits | kFmtUnsigned, + kUInt32 = kFkVarint | kRep32Bits | kFmtUnsigned, + kSFixed32 = kFkFixed | kRep32Bits | kFmtSigned, + kInt32 = kFkVarint | kRep32Bits | kFmtSigned, + kSInt32 = kFkVarint | kRep32Bits | kFmtSigned | kTvZigZag, + kFloat = kFkFixed | kRep32Bits | kFmtFloating, + kEnum = kFkVarint | kRep32Bits | kFmtEnum | kTvEnum, + kEnumRange = kFkVarint | kRep32Bits | kFmtEnum | kTvRange, + kOpenEnum = kFkVarint | kRep32Bits | kFmtEnum, + + kFixed64 = kFkFixed | kRep64Bits | kFmtUnsigned, + kUInt64 = kFkVarint | kRep64Bits | kFmtUnsigned, + kSFixed64 = kFkFixed | kRep64Bits | kFmtSigned, + kInt64 = kFkVarint | kRep64Bits | kFmtSigned, + kSInt64 = kFkVarint | kRep64Bits | kFmtSigned | kTvZigZag, + kDouble = kFkFixed | kRep64Bits | kFmtFloating, + + kPackedBool = kFkPackedVarint | kRep8Bits, + + kPackedFixed32 = kFkPackedFixed | kRep32Bits | kFmtUnsigned, + kPackedUInt32 = kFkPackedVarint | kRep32Bits | kFmtUnsigned, + kPackedSFixed32 = kFkPackedFixed | kRep32Bits | kFmtSigned, + kPackedInt32 = kFkPackedVarint | kRep32Bits | kFmtSigned, + kPackedSInt32 = kFkPackedVarint | kRep32Bits | kFmtSigned | kTvZigZag, + kPackedFloat = kFkPackedFixed | kRep32Bits | kFmtFloating, + kPackedEnum = kFkPackedVarint | kRep32Bits | kFmtEnum | kTvEnum, + kPackedEnumRange = kFkPackedVarint | kRep32Bits | kFmtEnum | kTvRange, + kPackedOpenEnum = kFkPackedVarint | kRep32Bits | kFmtEnum, + + kPackedFixed64 = kFkPackedFixed | kRep64Bits | kFmtUnsigned, + kPackedUInt64 = kFkPackedVarint | kRep64Bits | kFmtUnsigned, + kPackedSFixed64 = kFkPackedFixed | kRep64Bits | kFmtSigned, + kPackedInt64 = kFkPackedVarint | kRep64Bits | kFmtSigned, + kPackedSInt64 = kFkPackedVarint | kRep64Bits | kFmtSigned | kTvZigZag, + kPackedDouble = kFkPackedFixed | kRep64Bits | kFmtFloating, + + // String types: + kBytes = kFkString | kFmtArray, + kRawString = kFkString | kFmtUtf8 | kTvUtf8Debug, + kUtf8String = kFkString | kFmtUtf8 | kTvUtf8, + + // Message types: + kMessage = kFkMessage, + + // Map types: + kMap = kFkMap, +}; + +// clang-format on +} // namespace field_layout + +// PROTOBUF_TC_PARAM_DECL are the parameters for tailcall functions, it is +// defined in port_def.inc. +// +// Note that this is performance sensitive: changing the parameters will change +// the registers used by the ABI calling convention, which subsequently affects +// register selection logic inside the function. + +// PROTOBUF_TC_PARAM_PASS passes values to match PROTOBUF_TC_PARAM_DECL. +#define PROTOBUF_TC_PARAM_PASS msg, ptr, ctx, table, hasbits, data + +#ifndef NDEBUG +template <size_t align> +#ifndef _MSC_VER +[[noreturn]] +#endif +void AlignFail(uintptr_t address) { + GOOGLE_LOG(FATAL) << "Unaligned (" << align << ") access at " << address; +} + +extern template void AlignFail<4>(uintptr_t); +extern template void AlignFail<8>(uintptr_t); +#endif + +// TcParser implements most of the parsing logic for tailcall tables. +class PROTOBUF_EXPORT TcParser final { + public: + static const char* GenericFallback(PROTOBUF_TC_PARAM_DECL); + static const char* GenericFallbackLite(PROTOBUF_TC_PARAM_DECL); + + static const char* ParseLoop(MessageLite* msg, const char* ptr, + ParseContext* ctx, + const TcParseTableBase* table); + + // Functions referenced by generated fast tables (numeric types): + // F: fixed V: varint Z: zigzag + // 8/32/64: storage type width (bits) + // S: singular R: repeated P: packed + // 1/2: tag length (bytes) + + // Fixed: + static const char* FastF32S1(PROTOBUF_TC_PARAM_DECL); + static const char* FastF32S2(PROTOBUF_TC_PARAM_DECL); + static const char* FastF32R1(PROTOBUF_TC_PARAM_DECL); + static const char* FastF32R2(PROTOBUF_TC_PARAM_DECL); + static const char* FastF32P1(PROTOBUF_TC_PARAM_DECL); + static const char* FastF32P2(PROTOBUF_TC_PARAM_DECL); + static const char* FastF64S1(PROTOBUF_TC_PARAM_DECL); + static const char* FastF64S2(PROTOBUF_TC_PARAM_DECL); + static const char* FastF64R1(PROTOBUF_TC_PARAM_DECL); + static const char* FastF64R2(PROTOBUF_TC_PARAM_DECL); + static const char* FastF64P1(PROTOBUF_TC_PARAM_DECL); + static const char* FastF64P2(PROTOBUF_TC_PARAM_DECL); + + // Varint: + static const char* FastV8S1(PROTOBUF_TC_PARAM_DECL); + static const char* FastV8S2(PROTOBUF_TC_PARAM_DECL); + static const char* FastV8R1(PROTOBUF_TC_PARAM_DECL); + static const char* FastV8R2(PROTOBUF_TC_PARAM_DECL); + static const char* FastV8P1(PROTOBUF_TC_PARAM_DECL); + static const char* FastV8P2(PROTOBUF_TC_PARAM_DECL); + static const char* FastV32S1(PROTOBUF_TC_PARAM_DECL); + static const char* FastV32S2(PROTOBUF_TC_PARAM_DECL); + static const char* FastV32R1(PROTOBUF_TC_PARAM_DECL); + static const char* FastV32R2(PROTOBUF_TC_PARAM_DECL); + static const char* FastV32P1(PROTOBUF_TC_PARAM_DECL); + static const char* FastV32P2(PROTOBUF_TC_PARAM_DECL); + static const char* FastV64S1(PROTOBUF_TC_PARAM_DECL); + static const char* FastV64S2(PROTOBUF_TC_PARAM_DECL); + static const char* FastV64R1(PROTOBUF_TC_PARAM_DECL); + static const char* FastV64R2(PROTOBUF_TC_PARAM_DECL); + static const char* FastV64P1(PROTOBUF_TC_PARAM_DECL); + static const char* FastV64P2(PROTOBUF_TC_PARAM_DECL); + + // Varint (with zigzag): + static const char* FastZ32S1(PROTOBUF_TC_PARAM_DECL); + static const char* FastZ32S2(PROTOBUF_TC_PARAM_DECL); + static const char* FastZ32R1(PROTOBUF_TC_PARAM_DECL); + static const char* FastZ32R2(PROTOBUF_TC_PARAM_DECL); + static const char* FastZ32P1(PROTOBUF_TC_PARAM_DECL); + static const char* FastZ32P2(PROTOBUF_TC_PARAM_DECL); + static const char* FastZ64S1(PROTOBUF_TC_PARAM_DECL); + static const char* FastZ64S2(PROTOBUF_TC_PARAM_DECL); + static const char* FastZ64R1(PROTOBUF_TC_PARAM_DECL); + static const char* FastZ64R2(PROTOBUF_TC_PARAM_DECL); + static const char* FastZ64P1(PROTOBUF_TC_PARAM_DECL); + static const char* FastZ64P2(PROTOBUF_TC_PARAM_DECL); + + // Functions referenced by generated fast tables (closed enum): + // E: closed enum (N.B.: open enums use V32, above) + // r: enum range v: enum validator (_IsValid function) + // S: singular R: repeated + // 1/2: tag length (bytes) + static const char* FastErS1(PROTOBUF_TC_PARAM_DECL); + static const char* FastErS2(PROTOBUF_TC_PARAM_DECL); + static const char* FastErR1(PROTOBUF_TC_PARAM_DECL); + static const char* FastErR2(PROTOBUF_TC_PARAM_DECL); + static const char* FastEvS1(PROTOBUF_TC_PARAM_DECL); + static const char* FastEvS2(PROTOBUF_TC_PARAM_DECL); + static const char* FastEvR1(PROTOBUF_TC_PARAM_DECL); + static const char* FastEvR2(PROTOBUF_TC_PARAM_DECL); + + // Functions referenced by generated fast tables (string types): + // B: bytes S: string U: UTF-8 string + // (empty): ArenaStringPtr i: InlinedString + // S: singular R: repeated + // 1/2: tag length (bytes) + static const char* FastBS1(PROTOBUF_TC_PARAM_DECL); + static const char* FastBS2(PROTOBUF_TC_PARAM_DECL); + static const char* FastBR1(PROTOBUF_TC_PARAM_DECL); + static const char* FastBR2(PROTOBUF_TC_PARAM_DECL); + static const char* FastSS1(PROTOBUF_TC_PARAM_DECL); + static const char* FastSS2(PROTOBUF_TC_PARAM_DECL); + static const char* FastSR1(PROTOBUF_TC_PARAM_DECL); + static const char* FastSR2(PROTOBUF_TC_PARAM_DECL); + static const char* FastUS1(PROTOBUF_TC_PARAM_DECL); + static const char* FastUS2(PROTOBUF_TC_PARAM_DECL); + static const char* FastUR1(PROTOBUF_TC_PARAM_DECL); + static const char* FastUR2(PROTOBUF_TC_PARAM_DECL); + + static const char* FastBiS1(PROTOBUF_TC_PARAM_DECL); + static const char* FastBiS2(PROTOBUF_TC_PARAM_DECL); + static const char* FastSiS1(PROTOBUF_TC_PARAM_DECL); + static const char* FastSiS2(PROTOBUF_TC_PARAM_DECL); + static const char* FastUiS1(PROTOBUF_TC_PARAM_DECL); + static const char* FastUiS2(PROTOBUF_TC_PARAM_DECL); + + // Functions referenced by generated fast tables (message types): + // M: message G: group + // S: singular R: repeated + // 1/2: tag length (bytes) + static const char* FastMS1(PROTOBUF_TC_PARAM_DECL); + static const char* FastMS2(PROTOBUF_TC_PARAM_DECL); + static const char* FastMR1(PROTOBUF_TC_PARAM_DECL); + static const char* FastMR2(PROTOBUF_TC_PARAM_DECL); + static const char* FastGS1(PROTOBUF_TC_PARAM_DECL); + static const char* FastGS2(PROTOBUF_TC_PARAM_DECL); + static const char* FastGR1(PROTOBUF_TC_PARAM_DECL); + static const char* FastGR2(PROTOBUF_TC_PARAM_DECL); + + template <typename T> + static inline T& RefAt(void* x, size_t offset) { + T* target = reinterpret_cast<T*>(static_cast<char*>(x) + offset); +#ifndef NDEBUG + if (PROTOBUF_PREDICT_FALSE( + reinterpret_cast<uintptr_t>(target) % alignof(T) != 0)) { + AlignFail<alignof(T)>(reinterpret_cast<uintptr_t>(target)); + } +#endif + return *target; + } + + template <typename T> + static inline const T& RefAt(const void* x, size_t offset) { + const T* target = + reinterpret_cast<const T*>(static_cast<const char*>(x) + offset); +#ifndef NDEBUG + if (PROTOBUF_PREDICT_FALSE( + reinterpret_cast<uintptr_t>(target) % alignof(T) != 0)) { + AlignFail<alignof(T)>(reinterpret_cast<uintptr_t>(target)); + } +#endif + return *target; + } + + template <typename T> + static inline T ReadAt(const void* x, size_t offset) { + T out; + memcpy(&out, static_cast<const char*>(x) + offset, sizeof(T)); + return out; + } + + // Mini parsing: + // + // This function parses a field from incoming data based on metadata stored in + // the message definition. If the field is not defined in the message, it is + // stored in either the ExtensionSet (if applicable) or the UnknownFieldSet. + // + // NOTE: Currently, this function only calls the table-level fallback + // function, so it should only be called as the fallback from fast table + // parsing. + static const char* MiniParse(PROTOBUF_TC_PARAM_DECL); + + private: + friend class GeneratedTcTableLiteTest; + + template <typename TagType, bool group_coding> + static inline const char* SingularParseMessageAuxImpl(PROTOBUF_TC_PARAM_DECL); + template <typename TagType, bool group_coding> + static inline const char* RepeatedParseMessageAuxImpl(PROTOBUF_TC_PARAM_DECL); + + static inline PROTOBUF_ALWAYS_INLINE void SyncHasbits( + MessageLite* msg, uint64_t hasbits, const TcParseTableBase* table) { + const uint32_t has_bits_offset = table->has_bits_offset; + if (has_bits_offset) { + // Only the first 32 has-bits are updated. Nothing above those is stored, + // but e.g. messages without has-bits update the upper bits. + RefAt<uint32_t>(msg, has_bits_offset) = static_cast<uint32_t>(hasbits); + } + } + + static const char* TagDispatch(PROTOBUF_TC_PARAM_DECL); + static const char* ToTagDispatch(PROTOBUF_TC_PARAM_DECL); + static const char* ToParseLoop(PROTOBUF_TC_PARAM_DECL); + static const char* Error(PROTOBUF_TC_PARAM_DECL); + + static const char* FastUnknownEnumFallback(PROTOBUF_TC_PARAM_DECL); + + class ScopedArenaSwap; + + template <class MessageBaseT, class UnknownFieldsT> + static const char* GenericFallbackImpl(PROTOBUF_TC_PARAM_DECL) { +#define CHK_(x) \ + if (PROTOBUF_PREDICT_FALSE(!(x))) return nullptr /* NOLINT */ + + SyncHasbits(msg, hasbits, table); + CHK_(ptr); + uint32_t tag = data.tag(); + if ((tag & 7) == WireFormatLite::WIRETYPE_END_GROUP || tag == 0) { + ctx->SetLastTag(tag); + return ptr; + } + uint32_t num = tag >> 3; + if (table->extension_range_low <= num && + num <= table->extension_range_high) { + return RefAt<ExtensionSet>(msg, table->extension_offset) + .ParseField(tag, ptr, + static_cast<const MessageBaseT*>(table->default_instance), + &msg->_internal_metadata_, ctx); + } + return UnknownFieldParse( + tag, msg->_internal_metadata_.mutable_unknown_fields<UnknownFieldsT>(), + ptr, ctx); +#undef CHK_ + } + + // Note: `inline` is needed on template function declarations below to avoid + // -Wattributes diagnostic in GCC. + + // Implementations for fast fixed field parsing functions: + template <typename LayoutType, typename TagType> + static inline const char* SingularFixed(PROTOBUF_TC_PARAM_DECL); + template <typename LayoutType, typename TagType> + static inline const char* RepeatedFixed(PROTOBUF_TC_PARAM_DECL); + template <typename LayoutType, typename TagType> + static inline const char* PackedFixed(PROTOBUF_TC_PARAM_DECL); + + // Implementations for fast varint field parsing functions: + template <typename FieldType, typename TagType, bool zigzag = false> + static inline const char* SingularVarint(PROTOBUF_TC_PARAM_DECL); + template <typename FieldType, typename TagType, bool zigzag = false> + static inline const char* RepeatedVarint(PROTOBUF_TC_PARAM_DECL); + template <typename FieldType, typename TagType, bool zigzag = false> + static inline const char* PackedVarint(PROTOBUF_TC_PARAM_DECL); + + // Helper for ints > 127: + template <typename FieldType, typename TagType, bool zigzag = false> + static const char* SingularVarBigint(PROTOBUF_TC_PARAM_DECL); + + // Implementations for fast enum field parsing functions: + template <typename TagType, uint16_t xform_val> + static inline const char* SingularEnum(PROTOBUF_TC_PARAM_DECL); + template <typename TagType, uint16_t xform_val> + static inline const char* RepeatedEnum(PROTOBUF_TC_PARAM_DECL); + + // Implementations for fast string field parsing functions: + enum Utf8Type { kNoUtf8 = 0, kUtf8 = 1, kUtf8ValidateOnly = 2 }; + template <typename TagType, Utf8Type utf8> + static inline const char* SingularString(PROTOBUF_TC_PARAM_DECL); + template <typename TagType, Utf8Type utf8> + static inline const char* RepeatedString(PROTOBUF_TC_PARAM_DECL); + + // Mini field lookup: + static const TcParseTableBase::FieldEntry* FindFieldEntry( + const TcParseTableBase* table, uint32_t field_num); + static StringPiece MessageName(const TcParseTableBase* table); + static StringPiece FieldName(const TcParseTableBase* table, + const TcParseTableBase::FieldEntry*); + static bool ChangeOneof(const TcParseTableBase* table, + const TcParseTableBase::FieldEntry& entry, + uint32_t field_num, ParseContext* ctx, + MessageLite* msg); + + // UTF-8 validation: + static void ReportFastUtf8Error(uint32_t decoded_tag, + const TcParseTableBase* table); + static bool MpVerifyUtf8(StringPiece wire_bytes, + const TcParseTableBase* table, + const TcParseTableBase::FieldEntry& entry, + uint16_t xform_val); + + // For FindFieldEntry tests: + friend class FindFieldEntryTest; + static constexpr const uint32_t kMtSmallScanSize = 4; + + // Mini parsing: + static const char* MpVarint(PROTOBUF_TC_PARAM_DECL); + static const char* MpRepeatedVarint(PROTOBUF_TC_PARAM_DECL); + static const char* MpPackedVarint(PROTOBUF_TC_PARAM_DECL); + static const char* MpFixed(PROTOBUF_TC_PARAM_DECL); + static const char* MpRepeatedFixed(PROTOBUF_TC_PARAM_DECL); + static const char* MpPackedFixed(PROTOBUF_TC_PARAM_DECL); + static const char* MpString(PROTOBUF_TC_PARAM_DECL); + static const char* MpRepeatedString(PROTOBUF_TC_PARAM_DECL); + static const char* MpMessage(PROTOBUF_TC_PARAM_DECL); + static const char* MpRepeatedMessage(PROTOBUF_TC_PARAM_DECL); + static const char* MpMap(PROTOBUF_TC_PARAM_DECL); +}; + +} // namespace internal +} // namespace protobuf +} // namespace google + +#include <google/protobuf/port_undef.inc> + +#endif // GOOGLE_PROTOBUF_GENERATED_MESSAGE_TCTABLE_IMPL_H__ diff --git a/toolkit/components/protobuf/src/google/protobuf/generated_message_tctable_lite.cc b/toolkit/components/protobuf/src/google/protobuf/generated_message_tctable_lite.cc new file mode 100644 index 0000000000..9993811dca --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/generated_message_tctable_lite.cc @@ -0,0 +1,1859 @@ +// 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. + +#include <cstdint> +#include <numeric> + +#include <google/protobuf/extension_set.h> +#include <google/protobuf/generated_message_tctable_decl.h> +#include <google/protobuf/generated_message_tctable_impl.h> +#include <google/protobuf/inlined_string_field.h> +#include <google/protobuf/message_lite.h> +#include <google/protobuf/parse_context.h> +#include <google/protobuf/wire_format_lite.h> + +// clang-format off +#include <google/protobuf/port_def.inc> +// clang-format on + +namespace google { +namespace protobuf { +namespace internal { + +using FieldEntry = TcParseTableBase::FieldEntry; + +////////////////////////////////////////////////////////////////////////////// +// Template instantiations: +////////////////////////////////////////////////////////////////////////////// + +#ifndef NDEBUG +template void AlignFail<4>(uintptr_t); +template void AlignFail<8>(uintptr_t); +#endif + +const char* TcParser::GenericFallbackLite(PROTOBUF_TC_PARAM_DECL) { + return GenericFallbackImpl<MessageLite, std::string>(PROTOBUF_TC_PARAM_PASS); +} + +////////////////////////////////////////////////////////////////////////////// +// Core fast parsing implementation: +////////////////////////////////////////////////////////////////////////////// + +class TcParser::ScopedArenaSwap final { + public: + ScopedArenaSwap(MessageLite* msg, ParseContext* ctx) + : ctx_(ctx), saved_(ctx->data().arena) { + ctx_->data().arena = msg->GetArenaForAllocation(); + } + ScopedArenaSwap(const ScopedArenaSwap&) = delete; + ~ScopedArenaSwap() { ctx_->data().arena = saved_; } + + private: + ParseContext* const ctx_; + Arena* const saved_; +}; + +PROTOBUF_NOINLINE const char* TcParser::ParseLoop( + MessageLite* msg, const char* ptr, ParseContext* ctx, + const TcParseTableBase* table) { + ScopedArenaSwap saved(msg, ctx); + while (!ctx->Done(&ptr)) { + // Unconditionally read has bits, even if we don't have has bits. + // has_bits_offset will be 0 and we will just read something valid. + uint64_t hasbits = ReadAt<uint32_t>(msg, table->has_bits_offset); + ptr = TagDispatch(msg, ptr, ctx, table, hasbits, {}); + if (ptr == nullptr) break; + if (ctx->LastTag() != 1) break; // Ended on terminating tag + } + return ptr; +} + + // Dispatch to the designated parse function +inline PROTOBUF_ALWAYS_INLINE const char* TcParser::TagDispatch( + PROTOBUF_TC_PARAM_DECL) { + const auto coded_tag = UnalignedLoad<uint16_t>(ptr); + const size_t idx = coded_tag & table->fast_idx_mask; + PROTOBUF_ASSUME((idx & 7) == 0); + auto* fast_entry = table->fast_entry(idx >> 3); + data = fast_entry->bits; + data.data ^= coded_tag; + PROTOBUF_MUSTTAIL return fast_entry->target(PROTOBUF_TC_PARAM_PASS); +} + +// We can only safely call from field to next field if the call is optimized +// to a proper tail call. Otherwise we blow through stack. Clang and gcc +// reliably do this optimization in opt mode, but do not perform this in debug +// mode. Luckily the structure of the algorithm is such that it's always +// possible to just return and use the enclosing parse loop as a trampoline. +inline PROTOBUF_ALWAYS_INLINE const char* TcParser::ToTagDispatch( + PROTOBUF_TC_PARAM_DECL) { + constexpr bool always_return = !PROTOBUF_TAILCALL; + if (always_return || !ctx->DataAvailable(ptr)) { + PROTOBUF_MUSTTAIL return ToParseLoop(PROTOBUF_TC_PARAM_PASS); + } + PROTOBUF_MUSTTAIL return TagDispatch(PROTOBUF_TC_PARAM_PASS); +} + +inline PROTOBUF_ALWAYS_INLINE const char* TcParser::ToParseLoop( + PROTOBUF_TC_PARAM_DECL) { + (void)data; + (void)ctx; + SyncHasbits(msg, hasbits, table); + return ptr; +} + +inline PROTOBUF_ALWAYS_INLINE const char* TcParser::Error( + PROTOBUF_TC_PARAM_DECL) { + (void)data; + (void)ctx; + (void)ptr; + SyncHasbits(msg, hasbits, table); + return nullptr; +} + +// On the fast path, a (matching) 1-byte tag already has the decoded value. +static uint32_t FastDecodeTag(uint8_t coded_tag) { + return coded_tag; +} + +// On the fast path, a (matching) 2-byte tag always needs to be decoded. +static uint32_t FastDecodeTag(uint16_t coded_tag) { + uint32_t result = coded_tag; + result += static_cast<int8_t>(coded_tag); + return result >> 1; +} + +////////////////////////////////////////////////////////////////////////////// +// Core mini parsing implementation: +////////////////////////////////////////////////////////////////////////////// + +// Field lookup table layout: +// +// Because it consists of a series of variable-length segments, the lookuup +// table is organized within an array of uint16_t, and each element is either +// a uint16_t or a uint32_t stored little-endian as a pair of uint16_t. +// +// Its fundamental building block maps 16 contiguously ascending field numbers +// to their locations within the field entry table: + +struct SkipEntry16 { + uint16_t skipmap; + uint16_t field_entry_offset; +}; + +// The skipmap is a bitfield of which of those field numbers do NOT have a +// field entry. The lowest bit of the skipmap corresponds to the lowest of +// the 16 field numbers, so if a proto had only fields 1, 2, 3, and 7, the +// skipmap would contain 0b11111111'10111000. +// +// The field lookup table begins with a single 32-bit skipmap that maps the +// field numbers 1 through 32. This is because the majority of proto +// messages only contain fields numbered 1 to 32. +// +// The rest of the lookup table is a repeated series of +// { 32-bit field #, #SkipEntry16s, {SkipEntry16...} } +// That is, the next thing is a pair of uint16_t that form the next +// lowest field number that the lookup table handles. If this number is -1, +// that is the end of the table. Then there is a uint16_t that is +// the number of contiguous SkipEntry16 entries that follow, and then of +// course the SkipEntry16s themselves. + +// Originally developed and tested at https://godbolt.org/z/vbc7enYcf + +// Returns the address of the field for `tag` in the table's field entries. +// Returns nullptr if the field was not found. +const TcParseTableBase::FieldEntry* TcParser::FindFieldEntry( + const TcParseTableBase* table, uint32_t field_num) { + const FieldEntry* const field_entries = table->field_entries_begin(); + + uint32_t fstart = 1; + uint32_t adj_fnum = field_num - fstart; + + if (PROTOBUF_PREDICT_TRUE(adj_fnum < 32)) { + uint32_t skipmap = table->skipmap32; + uint32_t skipbit = 1 << adj_fnum; + if (PROTOBUF_PREDICT_FALSE(skipmap & skipbit)) return nullptr; + skipmap &= skipbit - 1; +#if (__GNUC__ || __clang__) && __POPCNT__ + // Note: here and below, skipmap typically has very few set bits + // (31 in the worst case, but usually zero) so a loop isn't that + // bad, and a compiler-generated popcount is typically only + // worthwhile if the processor itself has hardware popcount support. + adj_fnum -= __builtin_popcount(skipmap); +#else + while (skipmap) { + --adj_fnum; + skipmap &= skipmap - 1; + } +#endif + auto* entry = field_entries + adj_fnum; + PROTOBUF_ASSUME(entry != nullptr); + return entry; + } + const uint16_t* lookup_table = table->field_lookup_begin(); + for (;;) { +#ifdef PROTOBUF_LITTLE_ENDIAN + memcpy(&fstart, lookup_table, sizeof(fstart)); +#else + fstart = lookup_table[0] | (lookup_table[1] << 16); +#endif + lookup_table += sizeof(fstart) / sizeof(*lookup_table); + uint32_t num_skip_entries = *lookup_table++; + if (field_num < fstart) return nullptr; + adj_fnum = field_num - fstart; + uint32_t skip_num = adj_fnum / 16; + if (PROTOBUF_PREDICT_TRUE(skip_num < num_skip_entries)) { + // for each group of 16 fields we have: + // a bitmap of 16 bits + // a 16-bit field-entry offset for the first of them. + auto* skip_data = lookup_table + (adj_fnum / 16) * (sizeof(SkipEntry16) / + sizeof(uint16_t)); + SkipEntry16 se = {skip_data[0], skip_data[1]}; + adj_fnum &= 15; + uint32_t skipmap = se.skipmap; + uint16_t skipbit = 1 << adj_fnum; + if (PROTOBUF_PREDICT_FALSE(skipmap & skipbit)) return nullptr; + skipmap &= skipbit - 1; + adj_fnum += se.field_entry_offset; +#if (__GNUC__ || __clang__) && __POPCNT__ + adj_fnum -= __builtin_popcount(skipmap); +#else + while (skipmap) { + --adj_fnum; + skipmap &= skipmap - 1; + } +#endif + auto* entry = field_entries + adj_fnum; + PROTOBUF_ASSUME(entry != nullptr); + return entry; + } + lookup_table += + num_skip_entries * (sizeof(SkipEntry16) / sizeof(*lookup_table)); + } +} + +// Field names are stored in a format of: +// +// 1) A table of name sizes, one byte each, from 1 to 255 per name. +// `entries` is the size of this first table. +// 1a) padding bytes, so the table of name sizes is a multiple of +// eight bytes in length. They are zero. +// +// 2) All the names, concatenated, with neither separation nor termination. +// +// This is designed to be compact but not particularly fast to retrieve. +// In particular, it takes O(n) to retrieve the name of the n'th field, +// which is usually fine because most protos have fewer than 10 fields. +static StringPiece FindName(const char* name_data, size_t entries, + size_t index) { + // The compiler unrolls these... if this isn't fast enough, + // there's an AVX version at https://godbolt.org/z/eojrjqzfr + // ARM-compatible version at https://godbolt.org/z/n5YT5Ee85 + + // The field name sizes are padded up to a multiple of 8, so we + // must pad them here. + size_t num_sizes = (entries + 7) & -8; + auto* uint8s = reinterpret_cast<const uint8_t*>(name_data); + size_t pos = std::accumulate(uint8s, uint8s + index, num_sizes); + size_t size = name_data[index]; + auto* start = &name_data[pos]; + return {start, size}; +} + +StringPiece TcParser::MessageName(const TcParseTableBase* table) { + return FindName(table->name_data(), table->num_field_entries + 1, 0); +} + +StringPiece TcParser::FieldName(const TcParseTableBase* table, + const FieldEntry* field_entry) { + const FieldEntry* const field_entries = table->field_entries_begin(); + auto field_index = static_cast<size_t>(field_entry - field_entries); + return FindName(table->name_data(), table->num_field_entries + 1, + field_index + 1); +} + +const char* TcParser::MiniParse(PROTOBUF_TC_PARAM_DECL) { + uint32_t tag; + ptr = ReadTagInlined(ptr, &tag); + if (PROTOBUF_PREDICT_FALSE(ptr == nullptr)) return nullptr; + + auto* entry = FindFieldEntry(table, tag >> 3); + if (entry == nullptr) { + data.data = tag; + PROTOBUF_MUSTTAIL return table->fallback(PROTOBUF_TC_PARAM_PASS); + } + + // The handler may need the tag and the entry to resolve fallback logic. Both + // of these are 32 bits, so pack them into (the 64-bit) `data`. Since we can't + // pack the entry pointer itself, just pack its offset from `table`. + uint64_t entry_offset = reinterpret_cast<const char*>(entry) - + reinterpret_cast<const char*>(table); + data.data = entry_offset << 32 | tag; + + using field_layout::FieldKind; + auto field_type = entry->type_card & FieldKind::kFkMask; + switch (field_type) { + case FieldKind::kFkNone: + PROTOBUF_MUSTTAIL return table->fallback(PROTOBUF_TC_PARAM_PASS); + case FieldKind::kFkVarint: + PROTOBUF_MUSTTAIL return MpVarint(PROTOBUF_TC_PARAM_PASS); + case FieldKind::kFkPackedVarint: + PROTOBUF_MUSTTAIL return MpPackedVarint(PROTOBUF_TC_PARAM_PASS); + case FieldKind::kFkFixed: + PROTOBUF_MUSTTAIL return MpFixed(PROTOBUF_TC_PARAM_PASS); + case FieldKind::kFkPackedFixed: + PROTOBUF_MUSTTAIL return MpPackedFixed(PROTOBUF_TC_PARAM_PASS); + case FieldKind::kFkString: + PROTOBUF_MUSTTAIL return MpString(PROTOBUF_TC_PARAM_PASS); + case FieldKind::kFkMessage: + PROTOBUF_MUSTTAIL return MpMessage(PROTOBUF_TC_PARAM_PASS); + case FieldKind::kFkMap: + PROTOBUF_MUSTTAIL return MpMap(PROTOBUF_TC_PARAM_PASS); + default: + return Error(PROTOBUF_TC_PARAM_PASS); + } +} + +namespace { + +// Offset returns the address `offset` bytes after `base`. +inline void* Offset(void* base, uint32_t offset) { + return static_cast<uint8_t*>(base) + offset; +} + +// InvertPacked changes tag bits from the given wire type to length +// delimited. This is the difference expected between packed and non-packed +// repeated fields. +template <WireFormatLite::WireType Wt> +inline PROTOBUF_ALWAYS_INLINE void InvertPacked(TcFieldData& data) { + data.data ^= Wt ^ WireFormatLite::WIRETYPE_LENGTH_DELIMITED; +} + +} // namespace + +////////////////////////////////////////////////////////////////////////////// +// Message fields +////////////////////////////////////////////////////////////////////////////// + +template <typename TagType, bool group_coding> +inline PROTOBUF_ALWAYS_INLINE +const char* TcParser::SingularParseMessageAuxImpl(PROTOBUF_TC_PARAM_DECL) { + if (PROTOBUF_PREDICT_FALSE(data.coded_tag<TagType>() != 0)) { + PROTOBUF_MUSTTAIL return MiniParse(PROTOBUF_TC_PARAM_PASS); + } + auto saved_tag = UnalignedLoad<TagType>(ptr); + ptr += sizeof(TagType); + hasbits |= (uint64_t{1} << data.hasbit_idx()); + SyncHasbits(msg, hasbits, table); + auto& field = RefAt<MessageLite*>(msg, data.offset()); + if (field == nullptr) { + const MessageLite* default_instance = + table->field_aux(data.aux_idx())->message_default; + field = default_instance->New(ctx->data().arena); + } + if (group_coding) { + return ctx->ParseGroup(field, ptr, FastDecodeTag(saved_tag)); + } + return ctx->ParseMessage(field, ptr); +} + +const char* TcParser::FastMS1(PROTOBUF_TC_PARAM_DECL) { + PROTOBUF_MUSTTAIL return SingularParseMessageAuxImpl<uint8_t, false>( + PROTOBUF_TC_PARAM_PASS); +} + +const char* TcParser::FastMS2(PROTOBUF_TC_PARAM_DECL) { + PROTOBUF_MUSTTAIL return SingularParseMessageAuxImpl<uint16_t, false>( + PROTOBUF_TC_PARAM_PASS); +} + +const char* TcParser::FastGS1(PROTOBUF_TC_PARAM_DECL) { + PROTOBUF_MUSTTAIL return SingularParseMessageAuxImpl<uint8_t, true>( + PROTOBUF_TC_PARAM_PASS); +} + +const char* TcParser::FastGS2(PROTOBUF_TC_PARAM_DECL) { + PROTOBUF_MUSTTAIL return SingularParseMessageAuxImpl<uint16_t, true>( + PROTOBUF_TC_PARAM_PASS); +} + +template <typename TagType, bool group_coding> +inline PROTOBUF_ALWAYS_INLINE +const char* TcParser::RepeatedParseMessageAuxImpl(PROTOBUF_TC_PARAM_DECL) { + if (PROTOBUF_PREDICT_FALSE(data.coded_tag<TagType>() != 0)) { + PROTOBUF_MUSTTAIL return MiniParse(PROTOBUF_TC_PARAM_PASS); + } + auto saved_tag = UnalignedLoad<TagType>(ptr); + ptr += sizeof(TagType); + SyncHasbits(msg, hasbits, table); + const MessageLite* default_instance = + table->field_aux(data.aux_idx())->message_default; + auto& field = RefAt<RepeatedPtrFieldBase>(msg, data.offset()); + MessageLite* submsg = + field.Add<GenericTypeHandler<MessageLite>>(default_instance); + if (group_coding) { + return ctx->ParseGroup(submsg, ptr, FastDecodeTag(saved_tag)); + } + return ctx->ParseMessage(submsg, ptr); +} + +const char* TcParser::FastMR1(PROTOBUF_TC_PARAM_DECL) { + PROTOBUF_MUSTTAIL return RepeatedParseMessageAuxImpl<uint8_t, false>( + PROTOBUF_TC_PARAM_PASS); +} + +const char* TcParser::FastMR2(PROTOBUF_TC_PARAM_DECL) { + PROTOBUF_MUSTTAIL return RepeatedParseMessageAuxImpl<uint16_t, false>( + PROTOBUF_TC_PARAM_PASS); +} + +const char* TcParser::FastGR1(PROTOBUF_TC_PARAM_DECL) { + PROTOBUF_MUSTTAIL return RepeatedParseMessageAuxImpl<uint8_t, true>( + PROTOBUF_TC_PARAM_PASS); +} + +const char* TcParser::FastGR2(PROTOBUF_TC_PARAM_DECL) { + PROTOBUF_MUSTTAIL return RepeatedParseMessageAuxImpl<uint16_t, true>( + PROTOBUF_TC_PARAM_PASS); +} + +////////////////////////////////////////////////////////////////////////////// +// Fixed fields +////////////////////////////////////////////////////////////////////////////// + +template <typename LayoutType, typename TagType> +PROTOBUF_ALWAYS_INLINE const char* TcParser::SingularFixed( + PROTOBUF_TC_PARAM_DECL) { + if (PROTOBUF_PREDICT_FALSE(data.coded_tag<TagType>() != 0)) { + PROTOBUF_MUSTTAIL return MiniParse(PROTOBUF_TC_PARAM_PASS); + } + ptr += sizeof(TagType); // Consume tag + hasbits |= (uint64_t{1} << data.hasbit_idx()); + RefAt<LayoutType>(msg, data.offset()) = UnalignedLoad<LayoutType>(ptr); + ptr += sizeof(LayoutType); + PROTOBUF_MUSTTAIL return ToTagDispatch(PROTOBUF_TC_PARAM_PASS); +} + +const char* TcParser::FastF32S1(PROTOBUF_TC_PARAM_DECL) { + PROTOBUF_MUSTTAIL return SingularFixed<uint32_t, uint8_t>( + PROTOBUF_TC_PARAM_PASS); +} +const char* TcParser::FastF32S2(PROTOBUF_TC_PARAM_DECL) { + PROTOBUF_MUSTTAIL return SingularFixed<uint32_t, uint16_t>( + PROTOBUF_TC_PARAM_PASS); +} +const char* TcParser::FastF64S1(PROTOBUF_TC_PARAM_DECL) { + PROTOBUF_MUSTTAIL return SingularFixed<uint64_t, uint8_t>( + PROTOBUF_TC_PARAM_PASS); +} +const char* TcParser::FastF64S2(PROTOBUF_TC_PARAM_DECL) { + PROTOBUF_MUSTTAIL return SingularFixed<uint64_t, uint16_t>( + PROTOBUF_TC_PARAM_PASS); +} + +template <typename LayoutType, typename TagType> +PROTOBUF_ALWAYS_INLINE const char* TcParser::RepeatedFixed( + PROTOBUF_TC_PARAM_DECL) { + if (PROTOBUF_PREDICT_FALSE(data.coded_tag<TagType>() != 0)) { + // Check if the field can be parsed as packed repeated: + constexpr WireFormatLite::WireType fallback_wt = + sizeof(LayoutType) == 4 ? WireFormatLite::WIRETYPE_FIXED32 + : WireFormatLite::WIRETYPE_FIXED64; + InvertPacked<fallback_wt>(data); + if (data.coded_tag<TagType>() == 0) { + return PackedFixed<LayoutType, TagType>(PROTOBUF_TC_PARAM_PASS); + } else { + PROTOBUF_MUSTTAIL return MiniParse(PROTOBUF_TC_PARAM_PASS); + } + } + auto& field = RefAt<RepeatedField<LayoutType>>(msg, data.offset()); + int idx = field.size(); + auto elem = field.Add(); + int space = field.Capacity() - idx; + idx = 0; + auto expected_tag = UnalignedLoad<TagType>(ptr); + do { + ptr += sizeof(TagType); + elem[idx++] = UnalignedLoad<LayoutType>(ptr); + ptr += sizeof(LayoutType); + if (idx >= space) break; + if (!ctx->DataAvailable(ptr)) break; + } while (UnalignedLoad<TagType>(ptr) == expected_tag); + field.AddNAlreadyReserved(idx - 1); + return ToParseLoop(PROTOBUF_TC_PARAM_PASS); +} + +const char* TcParser::FastF32R1(PROTOBUF_TC_PARAM_DECL) { + PROTOBUF_MUSTTAIL return RepeatedFixed<uint32_t, uint8_t>( + PROTOBUF_TC_PARAM_PASS); +} +const char* TcParser::FastF32R2(PROTOBUF_TC_PARAM_DECL) { + PROTOBUF_MUSTTAIL return RepeatedFixed<uint32_t, uint16_t>( + PROTOBUF_TC_PARAM_PASS); +} +const char* TcParser::FastF64R1(PROTOBUF_TC_PARAM_DECL) { + PROTOBUF_MUSTTAIL return RepeatedFixed<uint64_t, uint8_t>( + PROTOBUF_TC_PARAM_PASS); +} +const char* TcParser::FastF64R2(PROTOBUF_TC_PARAM_DECL) { + PROTOBUF_MUSTTAIL return RepeatedFixed<uint64_t, uint16_t>( + PROTOBUF_TC_PARAM_PASS); +} + +// Note: some versions of GCC will fail with error "function not inlinable" if +// corecursive functions are both marked with PROTOBUF_ALWAYS_INLINE (Clang +// accepts this). We can still apply the attribute to one of the two functions, +// just not both (so we do mark the Repeated variant as always inlined). This +// also applies to PackedVarint, below. +template <typename LayoutType, typename TagType> +const char* TcParser::PackedFixed(PROTOBUF_TC_PARAM_DECL) { + if (PROTOBUF_PREDICT_FALSE(data.coded_tag<TagType>() != 0)) { + // Try parsing as non-packed repeated: + constexpr WireFormatLite::WireType fallback_wt = + sizeof(LayoutType) == 4 ? WireFormatLite::WIRETYPE_FIXED32 + : WireFormatLite::WIRETYPE_FIXED64; + InvertPacked<fallback_wt>(data); + if (data.coded_tag<TagType>() == 0) { + return RepeatedFixed<LayoutType, TagType>(PROTOBUF_TC_PARAM_PASS); + } else { + PROTOBUF_MUSTTAIL return MiniParse(PROTOBUF_TC_PARAM_PASS); + } + } + ptr += sizeof(TagType); + // Since ctx->ReadPackedFixed does not use TailCall<> or Return<>, sync any + // pending hasbits now: + SyncHasbits(msg, hasbits, table); + auto& field = RefAt<RepeatedField<LayoutType>>(msg, data.offset()); + int size = ReadSize(&ptr); + // TODO(dlj): add a tailcalling variant of ReadPackedFixed. + return ctx->ReadPackedFixed(ptr, size, + static_cast<RepeatedField<LayoutType>*>(&field)); +} + +const char* TcParser::FastF32P1(PROTOBUF_TC_PARAM_DECL) { + PROTOBUF_MUSTTAIL return PackedFixed<uint32_t, uint8_t>( + PROTOBUF_TC_PARAM_PASS); +} +const char* TcParser::FastF32P2(PROTOBUF_TC_PARAM_DECL) { + PROTOBUF_MUSTTAIL return PackedFixed<uint32_t, uint16_t>( + PROTOBUF_TC_PARAM_PASS); +} +const char* TcParser::FastF64P1(PROTOBUF_TC_PARAM_DECL) { + PROTOBUF_MUSTTAIL return PackedFixed<uint64_t, uint8_t>( + PROTOBUF_TC_PARAM_PASS); +} +const char* TcParser::FastF64P2(PROTOBUF_TC_PARAM_DECL) { + PROTOBUF_MUSTTAIL return PackedFixed<uint64_t, uint16_t>( + PROTOBUF_TC_PARAM_PASS); +} + +////////////////////////////////////////////////////////////////////////////// +// Varint fields +////////////////////////////////////////////////////////////////////////////// + +namespace { + +// Shift "byte" left by n * 7 bits, filling vacated bits with ones. +template <int n> +inline PROTOBUF_ALWAYS_INLINE uint64_t +shift_left_fill_with_ones(uint64_t byte, uint64_t ones) { + return (byte << (n * 7)) | (ones >> (64 - (n * 7))); +} + +// Shift "byte" left by n * 7 bits, filling vacated bits with ones, and +// put the new value in res. Return whether the result was negative. +template <int n> +inline PROTOBUF_ALWAYS_INLINE bool shift_left_fill_with_ones_was_negative( + uint64_t byte, uint64_t ones, int64_t& res) { +#if defined(__GCC_ASM_FLAG_OUTPUTS__) && defined(__x86_64__) + // For the first two rounds (ptr[1] and ptr[2]), micro benchmarks show a + // substantial improvement from capturing the sign from the condition code + // register on x86-64. + bool sign_bit; + asm("shldq %3, %2, %1" + : "=@ccs"(sign_bit), "+r"(byte) + : "r"(ones), "i"(n * 7)); + res = byte; + return sign_bit; +#else + // Generic fallback: + res = (byte << (n * 7)) | (ones >> (64 - (n * 7))); + return static_cast<int64_t>(res) < 0; +#endif +} + +inline PROTOBUF_ALWAYS_INLINE std::pair<const char*, uint64_t> +Parse64FallbackPair(const char* p, int64_t res1) { + auto ptr = reinterpret_cast<const int8_t*>(p); + + // The algorithm relies on sign extension for each byte to set all high bits + // when the varint continues. It also relies on asserting all of the lower + // bits for each successive byte read. This allows the result to be aggregated + // using a bitwise AND. For example: + // + // 8 1 64 57 ... 24 17 16 9 8 1 + // ptr[0] = 1aaa aaaa ; res1 = 1111 1111 ... 1111 1111 1111 1111 1aaa aaaa + // ptr[1] = 1bbb bbbb ; res2 = 1111 1111 ... 1111 1111 11bb bbbb b111 1111 + // ptr[2] = 1ccc cccc ; res3 = 0000 0000 ... 000c cccc cc11 1111 1111 1111 + // --------------------------------------------- + // res1 & res2 & res3 = 0000 0000 ... 000c cccc ccbb bbbb baaa aaaa + // + // On x86-64, a shld from a single register filled with enough 1s in the high + // bits can accomplish all this in one instruction. It so happens that res1 + // has 57 high bits of ones, which is enough for the largest shift done. + GOOGLE_DCHECK_EQ(res1 >> 7, -1); + uint64_t ones = res1; // save the high 1 bits from res1 (input to SHLD) + int64_t res2, res3; // accumulated result chunks + + if (!shift_left_fill_with_ones_was_negative<1>(ptr[1], ones, res2)) + goto done2; + if (!shift_left_fill_with_ones_was_negative<2>(ptr[2], ones, res3)) + goto done3; + + // For the remainder of the chunks, check the sign of the AND result. + res1 &= shift_left_fill_with_ones<3>(ptr[3], ones); + if (res1 >= 0) goto done4; + res2 &= shift_left_fill_with_ones<4>(ptr[4], ones); + if (res2 >= 0) goto done5; + res3 &= shift_left_fill_with_ones<5>(ptr[5], ones); + if (res3 >= 0) goto done6; + res1 &= shift_left_fill_with_ones<6>(ptr[6], ones); + if (res1 >= 0) goto done7; + res2 &= shift_left_fill_with_ones<7>(ptr[7], ones); + if (res2 >= 0) goto done8; + res3 &= shift_left_fill_with_ones<8>(ptr[8], ones); + if (res3 >= 0) goto done9; + + // For valid 64bit varints, the 10th byte/ptr[9] should be exactly 1. In this + // case, the continuation bit of ptr[8] already set the top bit of res3 + // correctly, so all we have to do is check that the expected case is true. + if (PROTOBUF_PREDICT_TRUE(ptr[9] == 1)) goto done10; + + // A value of 0, however, represents an over-serialized varint. This case + // should not happen, but if does (say, due to a nonconforming serializer), + // deassert the continuation bit that came from ptr[8]. + if (ptr[9] == 0) { +#if defined(__GCC_ASM_FLAG_OUTPUTS__) && defined(__x86_64__) + // Use a small instruction since this is an uncommon code path. + asm("btcq $63,%0" : "+r"(res3)); +#else + res3 ^= static_cast<uint64_t>(1) << 63; +#endif + goto done10; + } + + // If the 10th byte/ptr[9] itself has any other value, then it is too big to + // fit in 64 bits. If the continue bit is set, it is an unterminated varint. + return {nullptr, 0}; + +done2: + return {p + 2, res1 & res2}; +done3: + return {p + 3, res1 & res2 & res3}; +done4: + return {p + 4, res1 & res2 & res3}; +done5: + return {p + 5, res1 & res2 & res3}; +done6: + return {p + 6, res1 & res2 & res3}; +done7: + return {p + 7, res1 & res2 & res3}; +done8: + return {p + 8, res1 & res2 & res3}; +done9: + return {p + 9, res1 & res2 & res3}; +done10: + return {p + 10, res1 & res2 & res3}; +} + +inline PROTOBUF_ALWAYS_INLINE const char* ParseVarint(const char* p, + uint64_t* value) { + int64_t byte = static_cast<int8_t>(*p); + if (PROTOBUF_PREDICT_TRUE(byte >= 0)) { + *value = byte; + return p + 1; + } else { + auto tmp = Parse64FallbackPair(p, byte); + if (PROTOBUF_PREDICT_TRUE(tmp.first)) *value = tmp.second; + return tmp.first; + } +} + +template <typename FieldType, bool zigzag = false> +inline FieldType ZigZagDecodeHelper(uint64_t value) { + return static_cast<FieldType>(value); +} + +template <> +inline int32_t ZigZagDecodeHelper<int32_t, true>(uint64_t value) { + return WireFormatLite::ZigZagDecode32(value); +} + +template <> +inline int64_t ZigZagDecodeHelper<int64_t, true>(uint64_t value) { + return WireFormatLite::ZigZagDecode64(value); +} + +bool EnumIsValidAux(int32_t val, uint16_t xform_val, + TcParseTableBase::FieldAux aux) { + if (xform_val == field_layout::kTvRange) { + auto lo = aux.enum_range.start; + return lo <= val && val < (lo + aux.enum_range.length); + } + return aux.enum_validator(val); +} + +} // namespace + +template <typename FieldType, typename TagType, bool zigzag> +PROTOBUF_ALWAYS_INLINE const char* TcParser::SingularVarint( + PROTOBUF_TC_PARAM_DECL) { + if (PROTOBUF_PREDICT_FALSE(data.coded_tag<TagType>() != 0)) { + PROTOBUF_MUSTTAIL return MiniParse(PROTOBUF_TC_PARAM_PASS); + } + ptr += sizeof(TagType); // Consume tag + hasbits |= (uint64_t{1} << data.hasbit_idx()); + + // clang isn't smart enough to be able to only conditionally save + // registers to the stack, so we turn the integer-greater-than-128 + // case into a separate routine. + if (PROTOBUF_PREDICT_FALSE(static_cast<int8_t>(*ptr) < 0)) { + PROTOBUF_MUSTTAIL return SingularVarBigint<FieldType, TagType, zigzag>( + PROTOBUF_TC_PARAM_PASS); + } + + RefAt<FieldType>(msg, data.offset()) = + ZigZagDecodeHelper<FieldType, zigzag>(static_cast<uint8_t>(*ptr++)); + PROTOBUF_MUSTTAIL return ToTagDispatch(PROTOBUF_TC_PARAM_PASS); +} + +template <typename FieldType, typename TagType, bool zigzag> +PROTOBUF_NOINLINE const char* TcParser::SingularVarBigint( + PROTOBUF_TC_PARAM_DECL) { + // For some reason clang wants to save 5 registers to the stack here, + // but we only need four for this code, so save the data we don't need + // to the stack. Happily, saving them this way uses regular store + // instructions rather than PUSH/POP, which saves time at the cost of greater + // code size, but for this heavily-used piece of code, that's fine. + struct Spill { + uint64_t field_data; + ::google::protobuf::MessageLite* msg; + const ::google::protobuf::internal::TcParseTableBase* table; + uint64_t hasbits; + }; + volatile Spill spill = {data.data, msg, table, hasbits}; + + uint64_t tmp; + PROTOBUF_ASSUME(static_cast<int8_t>(*ptr) < 0); + ptr = ParseVarint(ptr, &tmp); + + data.data = spill.field_data; + msg = spill.msg; + table = spill.table; + hasbits = spill.hasbits; + + if (PROTOBUF_PREDICT_FALSE(ptr == nullptr)) { + return Error(PROTOBUF_TC_PARAM_PASS); + } + RefAt<FieldType>(msg, data.offset()) = + ZigZagDecodeHelper<FieldType, zigzag>(tmp); + PROTOBUF_MUSTTAIL return ToTagDispatch(PROTOBUF_TC_PARAM_PASS); +} + +const char* TcParser::FastV8S1(PROTOBUF_TC_PARAM_DECL) { + PROTOBUF_MUSTTAIL return SingularVarint<bool, uint8_t>( + PROTOBUF_TC_PARAM_PASS); +} +const char* TcParser::FastV8S2(PROTOBUF_TC_PARAM_DECL) { + PROTOBUF_MUSTTAIL return SingularVarint<bool, uint16_t>( + PROTOBUF_TC_PARAM_PASS); +} +const char* TcParser::FastV32S1(PROTOBUF_TC_PARAM_DECL) { + PROTOBUF_MUSTTAIL return SingularVarint<uint32_t, uint8_t>( + PROTOBUF_TC_PARAM_PASS); +} +const char* TcParser::FastV32S2(PROTOBUF_TC_PARAM_DECL) { + PROTOBUF_MUSTTAIL return SingularVarint<uint32_t, uint16_t>( + PROTOBUF_TC_PARAM_PASS); +} +const char* TcParser::FastV64S1(PROTOBUF_TC_PARAM_DECL) { + PROTOBUF_MUSTTAIL return SingularVarint<uint64_t, uint8_t>( + PROTOBUF_TC_PARAM_PASS); +} +const char* TcParser::FastV64S2(PROTOBUF_TC_PARAM_DECL) { + PROTOBUF_MUSTTAIL return SingularVarint<uint64_t, uint16_t>( + PROTOBUF_TC_PARAM_PASS); +} + +const char* TcParser::FastZ32S1(PROTOBUF_TC_PARAM_DECL) { + PROTOBUF_MUSTTAIL return SingularVarint<int32_t, uint8_t, true>( + PROTOBUF_TC_PARAM_PASS); +} +const char* TcParser::FastZ32S2(PROTOBUF_TC_PARAM_DECL) { + PROTOBUF_MUSTTAIL return SingularVarint<int32_t, uint16_t, true>( + PROTOBUF_TC_PARAM_PASS); +} +const char* TcParser::FastZ64S1(PROTOBUF_TC_PARAM_DECL) { + PROTOBUF_MUSTTAIL return SingularVarint<int64_t, uint8_t, true>( + PROTOBUF_TC_PARAM_PASS); +} +const char* TcParser::FastZ64S2(PROTOBUF_TC_PARAM_DECL) { + PROTOBUF_MUSTTAIL return SingularVarint<int64_t, uint16_t, true>( + PROTOBUF_TC_PARAM_PASS); +} + +template <typename FieldType, typename TagType, bool zigzag> +PROTOBUF_ALWAYS_INLINE const char* TcParser::RepeatedVarint( + PROTOBUF_TC_PARAM_DECL) { + if (PROTOBUF_PREDICT_FALSE(data.coded_tag<TagType>() != 0)) { + // Try parsing as non-packed repeated: + InvertPacked<WireFormatLite::WIRETYPE_VARINT>(data); + if (data.coded_tag<TagType>() == 0) { + return PackedVarint<FieldType, TagType, zigzag>(PROTOBUF_TC_PARAM_PASS); + } else { + PROTOBUF_MUSTTAIL return MiniParse(PROTOBUF_TC_PARAM_PASS); + } + } + auto& field = RefAt<RepeatedField<FieldType>>(msg, data.offset()); + auto expected_tag = UnalignedLoad<TagType>(ptr); + do { + ptr += sizeof(TagType); + uint64_t tmp; + ptr = ParseVarint(ptr, &tmp); + if (ptr == nullptr) { + return Error(PROTOBUF_TC_PARAM_PASS); + } + field.Add(ZigZagDecodeHelper<FieldType, zigzag>(tmp)); + if (!ctx->DataAvailable(ptr)) { + break; + } + } while (UnalignedLoad<TagType>(ptr) == expected_tag); + return ToParseLoop(PROTOBUF_TC_PARAM_PASS); +} + +const char* TcParser::FastV8R1(PROTOBUF_TC_PARAM_DECL) { + PROTOBUF_MUSTTAIL return RepeatedVarint<bool, uint8_t>( + PROTOBUF_TC_PARAM_PASS); +} +const char* TcParser::FastV8R2(PROTOBUF_TC_PARAM_DECL) { + PROTOBUF_MUSTTAIL return RepeatedVarint<bool, uint16_t>( + PROTOBUF_TC_PARAM_PASS); +} +const char* TcParser::FastV32R1(PROTOBUF_TC_PARAM_DECL) { + PROTOBUF_MUSTTAIL return RepeatedVarint<uint32_t, uint8_t>( + PROTOBUF_TC_PARAM_PASS); +} +const char* TcParser::FastV32R2(PROTOBUF_TC_PARAM_DECL) { + PROTOBUF_MUSTTAIL return RepeatedVarint<uint32_t, uint16_t>( + PROTOBUF_TC_PARAM_PASS); +} +const char* TcParser::FastV64R1(PROTOBUF_TC_PARAM_DECL) { + PROTOBUF_MUSTTAIL return RepeatedVarint<uint64_t, uint8_t>( + PROTOBUF_TC_PARAM_PASS); +} +const char* TcParser::FastV64R2(PROTOBUF_TC_PARAM_DECL) { + PROTOBUF_MUSTTAIL return RepeatedVarint<uint64_t, uint16_t>( + PROTOBUF_TC_PARAM_PASS); +} + +const char* TcParser::FastZ32R1(PROTOBUF_TC_PARAM_DECL) { + PROTOBUF_MUSTTAIL return RepeatedVarint<int32_t, uint8_t, true>( + PROTOBUF_TC_PARAM_PASS); +} +const char* TcParser::FastZ32R2(PROTOBUF_TC_PARAM_DECL) { + PROTOBUF_MUSTTAIL return RepeatedVarint<int32_t, uint16_t, true>( + PROTOBUF_TC_PARAM_PASS); +} +const char* TcParser::FastZ64R1(PROTOBUF_TC_PARAM_DECL) { + PROTOBUF_MUSTTAIL return RepeatedVarint<int64_t, uint8_t, true>( + PROTOBUF_TC_PARAM_PASS); +} +const char* TcParser::FastZ64R2(PROTOBUF_TC_PARAM_DECL) { + PROTOBUF_MUSTTAIL return RepeatedVarint<int64_t, uint16_t, true>( + PROTOBUF_TC_PARAM_PASS); +} + +// See comment on PackedFixed for why this is not PROTOBUF_ALWAYS_INLINE. +template <typename FieldType, typename TagType, bool zigzag> +const char* TcParser::PackedVarint(PROTOBUF_TC_PARAM_DECL) { + if (PROTOBUF_PREDICT_FALSE(data.coded_tag<TagType>() != 0)) { + InvertPacked<WireFormatLite::WIRETYPE_VARINT>(data); + if (data.coded_tag<TagType>() == 0) { + return RepeatedVarint<FieldType, TagType, zigzag>(PROTOBUF_TC_PARAM_PASS); + } else { + PROTOBUF_MUSTTAIL return MiniParse(PROTOBUF_TC_PARAM_PASS); + } + } + ptr += sizeof(TagType); + // Since ctx->ReadPackedVarint does not use TailCall or Return, sync any + // pending hasbits now: + SyncHasbits(msg, hasbits, table); + auto* field = &RefAt<RepeatedField<FieldType>>(msg, data.offset()); + return ctx->ReadPackedVarint(ptr, [field](uint64_t varint) { + FieldType val; + if (zigzag) { + if (sizeof(FieldType) == 8) { + val = WireFormatLite::ZigZagDecode64(varint); + } else { + val = WireFormatLite::ZigZagDecode32(varint); + } + } else { + val = varint; + } + field->Add(val); + }); +} + +const char* TcParser::FastV8P1(PROTOBUF_TC_PARAM_DECL) { + PROTOBUF_MUSTTAIL return PackedVarint<bool, uint8_t>(PROTOBUF_TC_PARAM_PASS); +} +const char* TcParser::FastV8P2(PROTOBUF_TC_PARAM_DECL) { + PROTOBUF_MUSTTAIL return PackedVarint<bool, uint16_t>(PROTOBUF_TC_PARAM_PASS); +} +const char* TcParser::FastV32P1(PROTOBUF_TC_PARAM_DECL) { + PROTOBUF_MUSTTAIL return PackedVarint<uint32_t, uint8_t>( + PROTOBUF_TC_PARAM_PASS); +} +const char* TcParser::FastV32P2(PROTOBUF_TC_PARAM_DECL) { + PROTOBUF_MUSTTAIL return PackedVarint<uint32_t, uint16_t>( + PROTOBUF_TC_PARAM_PASS); +} +const char* TcParser::FastV64P1(PROTOBUF_TC_PARAM_DECL) { + PROTOBUF_MUSTTAIL return PackedVarint<uint64_t, uint8_t>( + PROTOBUF_TC_PARAM_PASS); +} +const char* TcParser::FastV64P2(PROTOBUF_TC_PARAM_DECL) { + PROTOBUF_MUSTTAIL return PackedVarint<uint64_t, uint16_t>( + PROTOBUF_TC_PARAM_PASS); +} + +const char* TcParser::FastZ32P1(PROTOBUF_TC_PARAM_DECL) { + PROTOBUF_MUSTTAIL return PackedVarint<int32_t, uint8_t, true>( + PROTOBUF_TC_PARAM_PASS); +} +const char* TcParser::FastZ32P2(PROTOBUF_TC_PARAM_DECL) { + PROTOBUF_MUSTTAIL return PackedVarint<int32_t, uint16_t, true>( + PROTOBUF_TC_PARAM_PASS); +} +const char* TcParser::FastZ64P1(PROTOBUF_TC_PARAM_DECL) { + PROTOBUF_MUSTTAIL return PackedVarint<int64_t, uint8_t, true>( + PROTOBUF_TC_PARAM_PASS); +} +const char* TcParser::FastZ64P2(PROTOBUF_TC_PARAM_DECL) { + PROTOBUF_MUSTTAIL return PackedVarint<int64_t, uint16_t, true>( + PROTOBUF_TC_PARAM_PASS); +} + +////////////////////////////////////////////////////////////////////////////// +// Enum fields +////////////////////////////////////////////////////////////////////////////// + +PROTOBUF_NOINLINE const char* TcParser::FastUnknownEnumFallback( + PROTOBUF_TC_PARAM_DECL) { + (void)msg; + (void)ctx; + (void)hasbits; + + // If we know we want to put this field directly into the unknown field set, + // then we can skip the call to MiniParse and directly call table->fallback. + // However, we first have to update `data` to contain the decoded tag. + uint32_t tag; + ptr = ReadTag(ptr, &tag); + if (PROTOBUF_PREDICT_FALSE(ptr == nullptr)) { + return Error(PROTOBUF_TC_PARAM_PASS); + } + data.data = tag; + PROTOBUF_MUSTTAIL return table->fallback(PROTOBUF_TC_PARAM_PASS); +} + +template <typename TagType, uint16_t xform_val> +PROTOBUF_ALWAYS_INLINE const char* TcParser::SingularEnum( + PROTOBUF_TC_PARAM_DECL) { + if (PROTOBUF_PREDICT_FALSE(data.coded_tag<TagType>() != 0)) { + PROTOBUF_MUSTTAIL return MiniParse(PROTOBUF_TC_PARAM_PASS); + } + const char* ptr2 = ptr; // Save for unknown enum case + ptr += sizeof(TagType); // Consume tag + uint64_t tmp; + ptr = ParseVarint(ptr, &tmp); + if (ptr == nullptr) { + return Error(PROTOBUF_TC_PARAM_PASS); + } + const TcParseTableBase::FieldAux aux = *table->field_aux(data.aux_idx()); + if (PROTOBUF_PREDICT_FALSE( + !EnumIsValidAux(static_cast<int32_t>(tmp), xform_val, aux))) { + ptr = ptr2; + PROTOBUF_MUSTTAIL return FastUnknownEnumFallback(PROTOBUF_TC_PARAM_PASS); + } + hasbits |= (uint64_t{1} << data.hasbit_idx()); + RefAt<int32_t>(msg, data.offset()) = tmp; + PROTOBUF_MUSTTAIL return ToTagDispatch(PROTOBUF_TC_PARAM_PASS); +} + +const char* TcParser::FastErS1(PROTOBUF_TC_PARAM_DECL) { + PROTOBUF_MUSTTAIL return SingularEnum<uint8_t, field_layout::kTvRange>( + PROTOBUF_TC_PARAM_PASS); +} +const char* TcParser::FastErS2(PROTOBUF_TC_PARAM_DECL) { + PROTOBUF_MUSTTAIL return SingularEnum<uint16_t, field_layout::kTvRange>( + PROTOBUF_TC_PARAM_PASS); +} +const char* TcParser::FastEvS1(PROTOBUF_TC_PARAM_DECL) { + PROTOBUF_MUSTTAIL return SingularEnum<uint8_t, field_layout::kTvEnum>( + PROTOBUF_TC_PARAM_PASS); +} +const char* TcParser::FastEvS2(PROTOBUF_TC_PARAM_DECL) { + PROTOBUF_MUSTTAIL return SingularEnum<uint16_t, field_layout::kTvEnum>( + PROTOBUF_TC_PARAM_PASS); +} + +template <typename TagType, uint16_t xform_val> +PROTOBUF_ALWAYS_INLINE const char* TcParser::RepeatedEnum( + PROTOBUF_TC_PARAM_DECL) { + if (PROTOBUF_PREDICT_FALSE(data.coded_tag<TagType>() != 0)) { + InvertPacked<WireFormatLite::WIRETYPE_VARINT>(data); + if (data.coded_tag<TagType>() == 0) { + // Packed parsing is handled by generated fallback. + PROTOBUF_MUSTTAIL return FastUnknownEnumFallback(PROTOBUF_TC_PARAM_PASS); + } else { + PROTOBUF_MUSTTAIL return MiniParse(PROTOBUF_TC_PARAM_PASS); + } + } + auto& field = RefAt<RepeatedField<int32_t>>(msg, data.offset()); + auto expected_tag = UnalignedLoad<TagType>(ptr); + const TcParseTableBase::FieldAux aux = *table->field_aux(data.aux_idx()); + do { + const char* ptr2 = ptr; // save for unknown enum case + ptr += sizeof(TagType); + uint64_t tmp; + ptr = ParseVarint(ptr, &tmp); + if (ptr == nullptr) { + return Error(PROTOBUF_TC_PARAM_PASS); + } + if (PROTOBUF_PREDICT_FALSE( + !EnumIsValidAux(static_cast<int32_t>(tmp), xform_val, aux))) { + // We can avoid duplicate work in MiniParse by directly calling + // table->fallback. + ptr = ptr2; + PROTOBUF_MUSTTAIL return FastUnknownEnumFallback(PROTOBUF_TC_PARAM_PASS); + } + field.Add(static_cast<int32_t>(tmp)); + if (!ctx->DataAvailable(ptr)) { + break; + } + } while (UnalignedLoad<TagType>(ptr) == expected_tag); + return ToParseLoop(PROTOBUF_TC_PARAM_PASS); +} + +const char* TcParser::FastErR1(PROTOBUF_TC_PARAM_DECL) { + PROTOBUF_MUSTTAIL return RepeatedEnum<uint8_t, field_layout::kTvRange>( + PROTOBUF_TC_PARAM_PASS); +} +const char* TcParser::FastErR2(PROTOBUF_TC_PARAM_DECL) { + PROTOBUF_MUSTTAIL return RepeatedEnum<uint16_t, field_layout::kTvRange>( + PROTOBUF_TC_PARAM_PASS); +} +const char* TcParser::FastEvR1(PROTOBUF_TC_PARAM_DECL) { + PROTOBUF_MUSTTAIL return RepeatedEnum<uint8_t, field_layout::kTvEnum>( + PROTOBUF_TC_PARAM_PASS); +} +const char* TcParser::FastEvR2(PROTOBUF_TC_PARAM_DECL) { + PROTOBUF_MUSTTAIL return RepeatedEnum<uint16_t, field_layout::kTvEnum>( + PROTOBUF_TC_PARAM_PASS); +} + +////////////////////////////////////////////////////////////////////////////// +// String/bytes fields +////////////////////////////////////////////////////////////////////////////// + +// Defined in wire_format_lite.cc +void PrintUTF8ErrorLog(StringPiece message_name, + StringPiece field_name, const char* operation_str, + bool emit_stacktrace); + +void TcParser::ReportFastUtf8Error(uint32_t decoded_tag, + const TcParseTableBase* table) { + uint32_t field_num = decoded_tag >> 3; + const auto* entry = FindFieldEntry(table, field_num); + PrintUTF8ErrorLog(MessageName(table), FieldName(table, entry), "parsing", + false); +} + +namespace { + +PROTOBUF_NOINLINE +const char* SingularStringParserFallback(ArenaStringPtr* s, const char* ptr, + EpsCopyInputStream* stream) { + int size = ReadSize(&ptr); + if (!ptr) return nullptr; + return stream->ReadString(ptr, size, s->MutableNoCopy(nullptr)); +} + +} // namespace + +template <typename TagType, TcParser::Utf8Type utf8> +PROTOBUF_ALWAYS_INLINE const char* TcParser::SingularString( + PROTOBUF_TC_PARAM_DECL) { + if (PROTOBUF_PREDICT_FALSE(data.coded_tag<TagType>() != 0)) { + PROTOBUF_MUSTTAIL return MiniParse(PROTOBUF_TC_PARAM_PASS); + } + auto saved_tag = UnalignedLoad<TagType>(ptr); + ptr += sizeof(TagType); + hasbits |= (uint64_t{1} << data.hasbit_idx()); + auto& field = RefAt<ArenaStringPtr>(msg, data.offset()); + auto arena = ctx->data().arena; + if (arena) { + ptr = ctx->ReadArenaString(ptr, &field, arena); + } else { + ptr = SingularStringParserFallback(&field, ptr, ctx); + } + if (ptr == nullptr) return Error(PROTOBUF_TC_PARAM_PASS); + switch (utf8) { + case kNoUtf8: +#ifdef NDEBUG + case kUtf8ValidateOnly: +#endif + return ToParseLoop(PROTOBUF_TC_PARAM_PASS); + default: + if (PROTOBUF_PREDICT_TRUE(IsStructurallyValidUTF8(field.Get()))) { + return ToParseLoop(PROTOBUF_TC_PARAM_PASS); + } + ReportFastUtf8Error(FastDecodeTag(saved_tag), table); + return utf8 == kUtf8 ? Error(PROTOBUF_TC_PARAM_PASS) + : ToParseLoop(PROTOBUF_TC_PARAM_PASS); + } +} + +const char* TcParser::FastBS1(PROTOBUF_TC_PARAM_DECL) { + PROTOBUF_MUSTTAIL return SingularString<uint8_t, kNoUtf8>( + PROTOBUF_TC_PARAM_PASS); +} +const char* TcParser::FastBS2(PROTOBUF_TC_PARAM_DECL) { + PROTOBUF_MUSTTAIL return SingularString<uint16_t, kNoUtf8>( + PROTOBUF_TC_PARAM_PASS); +} +const char* TcParser::FastSS1(PROTOBUF_TC_PARAM_DECL) { + PROTOBUF_MUSTTAIL return SingularString<uint8_t, kUtf8ValidateOnly>( + PROTOBUF_TC_PARAM_PASS); +} +const char* TcParser::FastSS2(PROTOBUF_TC_PARAM_DECL) { + PROTOBUF_MUSTTAIL return SingularString<uint16_t, kUtf8ValidateOnly>( + PROTOBUF_TC_PARAM_PASS); +} +const char* TcParser::FastUS1(PROTOBUF_TC_PARAM_DECL) { + PROTOBUF_MUSTTAIL return SingularString<uint8_t, kUtf8>( + PROTOBUF_TC_PARAM_PASS); +} +const char* TcParser::FastUS2(PROTOBUF_TC_PARAM_DECL) { + PROTOBUF_MUSTTAIL return SingularString<uint16_t, kUtf8>( + PROTOBUF_TC_PARAM_PASS); +} + +// Inlined string variants: + +const char* TcParser::FastBiS1(PROTOBUF_TC_PARAM_DECL) { + PROTOBUF_MUSTTAIL return MiniParse(PROTOBUF_TC_PARAM_PASS); +} +const char* TcParser::FastBiS2(PROTOBUF_TC_PARAM_DECL) { + PROTOBUF_MUSTTAIL return MiniParse(PROTOBUF_TC_PARAM_PASS); +} +const char* TcParser::FastSiS1(PROTOBUF_TC_PARAM_DECL) { + PROTOBUF_MUSTTAIL return MiniParse(PROTOBUF_TC_PARAM_PASS); +} +const char* TcParser::FastSiS2(PROTOBUF_TC_PARAM_DECL) { + PROTOBUF_MUSTTAIL return MiniParse(PROTOBUF_TC_PARAM_PASS); +} +const char* TcParser::FastUiS1(PROTOBUF_TC_PARAM_DECL) { + PROTOBUF_MUSTTAIL return MiniParse(PROTOBUF_TC_PARAM_PASS); +} +const char* TcParser::FastUiS2(PROTOBUF_TC_PARAM_DECL) { + PROTOBUF_MUSTTAIL return MiniParse(PROTOBUF_TC_PARAM_PASS); +} + +template <typename TagType, TcParser::Utf8Type utf8> +PROTOBUF_ALWAYS_INLINE const char* TcParser::RepeatedString( + PROTOBUF_TC_PARAM_DECL) { + if (PROTOBUF_PREDICT_FALSE(data.coded_tag<TagType>() != 0)) { + PROTOBUF_MUSTTAIL return MiniParse(PROTOBUF_TC_PARAM_PASS); + } + auto expected_tag = UnalignedLoad<TagType>(ptr); + auto& field = RefAt<RepeatedPtrField<std::string>>(msg, data.offset()); + do { + ptr += sizeof(TagType); + std::string* str = field.Add(); + ptr = InlineGreedyStringParser(str, ptr, ctx); + if (ptr == nullptr) { + return Error(PROTOBUF_TC_PARAM_PASS); + } + switch (utf8) { + case kNoUtf8: +#ifdef NDEBUG + case kUtf8ValidateOnly: +#endif + break; + default: + if (PROTOBUF_PREDICT_TRUE(IsStructurallyValidUTF8(*str))) { + break; + } + ReportFastUtf8Error(FastDecodeTag(expected_tag), table); + if (utf8 == kUtf8) return Error(PROTOBUF_TC_PARAM_PASS); + break; + } + if (!ctx->DataAvailable(ptr)) break; + } while (UnalignedLoad<TagType>(ptr) == expected_tag); + return ToParseLoop(PROTOBUF_TC_PARAM_PASS); +} + +const char* TcParser::FastBR1(PROTOBUF_TC_PARAM_DECL) { + PROTOBUF_MUSTTAIL return RepeatedString<uint8_t, kNoUtf8>( + PROTOBUF_TC_PARAM_PASS); +} +const char* TcParser::FastBR2(PROTOBUF_TC_PARAM_DECL) { + PROTOBUF_MUSTTAIL return RepeatedString<uint16_t, kNoUtf8>( + PROTOBUF_TC_PARAM_PASS); +} +const char* TcParser::FastSR1(PROTOBUF_TC_PARAM_DECL) { + PROTOBUF_MUSTTAIL return RepeatedString<uint8_t, kUtf8ValidateOnly>( + PROTOBUF_TC_PARAM_PASS); +} +const char* TcParser::FastSR2(PROTOBUF_TC_PARAM_DECL) { + PROTOBUF_MUSTTAIL return RepeatedString<uint16_t, kUtf8ValidateOnly>( + PROTOBUF_TC_PARAM_PASS); +} +const char* TcParser::FastUR1(PROTOBUF_TC_PARAM_DECL) { + PROTOBUF_MUSTTAIL return RepeatedString<uint8_t, kUtf8>( + PROTOBUF_TC_PARAM_PASS); +} +const char* TcParser::FastUR2(PROTOBUF_TC_PARAM_DECL) { + PROTOBUF_MUSTTAIL return RepeatedString<uint16_t, kUtf8>( + PROTOBUF_TC_PARAM_PASS); +} + +////////////////////////////////////////////////////////////////////////////// +// Mini parsing +////////////////////////////////////////////////////////////////////////////// + +namespace { +inline void SetHas(const TcParseTableBase* table, const FieldEntry& entry, + MessageLite* msg, uint64_t& hasbits) { + int32_t has_idx = entry.has_idx; + if (has_idx < 32) { + hasbits |= uint64_t{1} << has_idx; + } else { + auto* hasblocks = &TcParser::RefAt<uint32_t>(msg, table->has_bits_offset); +#if defined(__x86_64__) && defined(__GNUC__) + asm("bts %1, %0\n" : "+m"(*hasblocks) : "r"(has_idx)); +#else + auto& hasblock = hasblocks[has_idx / 32]; + hasblock |= uint32_t{1} << (has_idx % 32); +#endif + } +} +} // namespace + +// Destroys any existing oneof union member (if necessary). Returns true if the +// caller is responsible for initializing the object, or false if the field +// already has the desired case. +bool TcParser::ChangeOneof(const TcParseTableBase* table, + const TcParseTableBase::FieldEntry& entry, + uint32_t field_num, ParseContext* ctx, + MessageLite* msg) { + // The _oneof_case_ array offset is stored in the first aux entry. + uint32_t oneof_case_offset = table->field_aux(0u)->offset; + // The _oneof_case_ array index is stored in the has-bit index. + uint32_t* oneof_case = + &TcParser::RefAt<uint32_t>(msg, oneof_case_offset) + entry.has_idx; + uint32_t current_case = *oneof_case; + *oneof_case = field_num; + + if (current_case == 0) { + // If the member is empty, we don't have anything to clear. Caller is + // responsible for creating a new member object. + return true; + } + if (current_case == field_num) { + // If the member is already active, then it should be merged. We're done. + return false; + } + // Look up the value that is already stored, and dispose of it if necessary. + const FieldEntry* current_entry = FindFieldEntry(table, current_case); + uint16_t current_kind = current_entry->type_card & field_layout::kFkMask; + uint16_t current_rep = current_entry->type_card & field_layout::kRepMask; + if (current_kind == field_layout::kFkString) { + switch (current_rep) { + case field_layout::kRepAString: { + auto& field = RefAt<ArenaStringPtr>(msg, current_entry->offset); + field.Destroy(); + break; + } + case field_layout::kRepSString: + case field_layout::kRepIString: + default: + GOOGLE_LOG(DFATAL) << "string rep not handled: " + << (current_rep >> field_layout::kRepShift); + return true; + } + } else if (current_kind == field_layout::kFkMessage) { + switch (current_rep) { + case field_layout::kRepMessage: + case field_layout::kRepGroup: + case field_layout::kRepIWeak: { + auto& field = RefAt<MessageLite*>(msg, current_entry->offset); + if (!ctx->data().arena) { + delete field; + } + break; + } + default: + GOOGLE_LOG(DFATAL) << "message rep not handled: " + << (current_rep >> field_layout::kRepShift); + break; + } + } + return true; +} + +const char* TcParser::MpFixed(PROTOBUF_TC_PARAM_DECL) { + const auto& entry = RefAt<FieldEntry>(table, data.entry_offset()); + const uint16_t type_card = entry.type_card; + const uint16_t card = type_card & field_layout::kFcMask; + + // Check for repeated parsing (wiretype fallback is handled there): + if (card == field_layout::kFcRepeated) { + PROTOBUF_MUSTTAIL return MpRepeatedFixed(PROTOBUF_TC_PARAM_PASS); + } + // Check for mismatched wiretype: + const uint16_t rep = type_card & field_layout::kRepMask; + const uint32_t decoded_wiretype = data.tag() & 7; + if (rep == field_layout::kRep64Bits) { + if (decoded_wiretype != WireFormatLite::WIRETYPE_FIXED64) { + PROTOBUF_MUSTTAIL return table->fallback(PROTOBUF_TC_PARAM_PASS); + } + } else { + GOOGLE_DCHECK_EQ(rep, static_cast<uint16_t>(field_layout::kRep32Bits)); + if (decoded_wiretype != WireFormatLite::WIRETYPE_FIXED32) { + PROTOBUF_MUSTTAIL return table->fallback(PROTOBUF_TC_PARAM_PASS); + } + } + // Set the field present: + if (card == field_layout::kFcOptional) { + SetHas(table, entry, msg, hasbits); + } else if (card == field_layout::kFcOneof) { + ChangeOneof(table, entry, data.tag() >> 3, ctx, msg); + } + // Copy the value: + if (rep == field_layout::kRep64Bits) { + RefAt<uint64_t>(msg, entry.offset) = UnalignedLoad<uint64_t>(ptr); + ptr += sizeof(uint64_t); + } else { + RefAt<uint32_t>(msg, entry.offset) = UnalignedLoad<uint32_t>(ptr); + ptr += sizeof(uint32_t); + } + PROTOBUF_MUSTTAIL return ToTagDispatch(PROTOBUF_TC_PARAM_PASS); +} + +const char* TcParser::MpRepeatedFixed(PROTOBUF_TC_PARAM_DECL) { + const auto& entry = RefAt<FieldEntry>(table, data.entry_offset()); + const uint32_t decoded_tag = data.tag(); + const uint32_t decoded_wiretype = decoded_tag & 7; + + // Check for packed repeated fallback: + if (decoded_wiretype == WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + PROTOBUF_MUSTTAIL return MpPackedFixed(PROTOBUF_TC_PARAM_PASS); + } + + const uint16_t type_card = entry.type_card; + const uint16_t rep = type_card & field_layout::kRepMask; + if (rep == field_layout::kRep64Bits) { + if (decoded_wiretype != WireFormatLite::WIRETYPE_FIXED64) { + PROTOBUF_MUSTTAIL return table->fallback(PROTOBUF_TC_PARAM_PASS); + } + auto& field = RefAt<RepeatedField<uint64_t>>(msg, entry.offset); + constexpr auto size = sizeof(uint64_t); + const char* ptr2 = ptr; + uint32_t next_tag; + do { + ptr = ptr2; + *field.Add() = UnalignedLoad<uint64_t>(ptr); + ptr += size; + if (!ctx->DataAvailable(ptr)) break; + ptr2 = ReadTag(ptr, &next_tag); + } while (next_tag == decoded_tag); + } else { + GOOGLE_DCHECK_EQ(rep, static_cast<uint16_t>(field_layout::kRep32Bits)); + if (decoded_wiretype != WireFormatLite::WIRETYPE_FIXED32) { + PROTOBUF_MUSTTAIL return table->fallback(PROTOBUF_TC_PARAM_PASS); + } + auto& field = RefAt<RepeatedField<uint32_t>>(msg, entry.offset); + constexpr auto size = sizeof(uint32_t); + const char* ptr2 = ptr; + uint32_t next_tag; + do { + ptr = ptr2; + *field.Add() = UnalignedLoad<uint32_t>(ptr); + ptr += size; + if (!ctx->DataAvailable(ptr)) break; + ptr2 = ReadTag(ptr, &next_tag); + } while (next_tag == decoded_tag); + } + + PROTOBUF_MUSTTAIL return ToTagDispatch(PROTOBUF_TC_PARAM_PASS); +} + +const char* TcParser::MpPackedFixed(PROTOBUF_TC_PARAM_DECL) { + const auto& entry = RefAt<FieldEntry>(table, data.entry_offset()); + const uint16_t type_card = entry.type_card; + const uint32_t decoded_wiretype = data.tag() & 7; + + // Check for non-packed repeated fallback: + if (decoded_wiretype != WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + PROTOBUF_MUSTTAIL return MpRepeatedFixed(PROTOBUF_TC_PARAM_PASS); + } + + // Since ctx->ReadPackedFixed does not use TailCall<> or Return<>, sync any + // pending hasbits now: + SyncHasbits(msg, hasbits, table); + + int size = ReadSize(&ptr); + uint16_t rep = type_card & field_layout::kRepMask; + if (rep == field_layout::kRep64Bits) { + auto& field = RefAt<RepeatedField<uint64_t>>(msg, entry.offset); + ptr = ctx->ReadPackedFixed(ptr, size, &field); + } else { + GOOGLE_DCHECK_EQ(rep, static_cast<uint16_t>(field_layout::kRep32Bits)); + auto& field = RefAt<RepeatedField<uint32_t>>(msg, entry.offset); + ptr = ctx->ReadPackedFixed(ptr, size, &field); + } + + if (ptr == nullptr) { + return Error(PROTOBUF_TC_PARAM_PASS); + } + PROTOBUF_MUSTTAIL return ToTagDispatch(PROTOBUF_TC_PARAM_PASS); +} + +const char* TcParser::MpVarint(PROTOBUF_TC_PARAM_DECL) { + const auto& entry = RefAt<FieldEntry>(table, data.entry_offset()); + const uint16_t type_card = entry.type_card; + const uint16_t card = type_card & field_layout::kFcMask; + + // Check for repeated parsing: + if (card == field_layout::kFcRepeated) { + PROTOBUF_MUSTTAIL return MpRepeatedVarint(PROTOBUF_TC_PARAM_PASS); + } + // Check for wire type mismatch: + if ((data.tag() & 7) != WireFormatLite::WIRETYPE_VARINT) { + PROTOBUF_MUSTTAIL return table->fallback(PROTOBUF_TC_PARAM_PASS); + } + const uint16_t xform_val = type_card & field_layout::kTvMask; + const bool is_zigzag = xform_val == field_layout::kTvZigZag; + const bool is_validated_enum = xform_val & field_layout::kTvEnum; + + // Parse the value: + const char* ptr2 = ptr; // save for unknown enum case + uint64_t tmp; + ptr = ParseVarint(ptr, &tmp); + if (ptr == nullptr) return Error(PROTOBUF_TC_PARAM_PASS); + + // Transform and/or validate the value + uint16_t rep = type_card & field_layout::kRepMask; + if (rep == field_layout::kRep64Bits) { + if (is_zigzag) { + tmp = WireFormatLite::ZigZagDecode64(tmp); + } + } else if (rep == field_layout::kRep32Bits) { + if (is_validated_enum) { + if (!EnumIsValidAux(tmp, xform_val, *table->field_aux(&entry))) { + ptr = ptr2; + PROTOBUF_MUSTTAIL return table->fallback(PROTOBUF_TC_PARAM_PASS); + } + } else if (is_zigzag) { + tmp = WireFormatLite::ZigZagDecode32(static_cast<uint32_t>(tmp)); + } + } + + // Mark the field as present: + const bool is_oneof = card == field_layout::kFcOneof; + if (card == field_layout::kFcOptional) { + SetHas(table, entry, msg, hasbits); + } else if (is_oneof) { + ChangeOneof(table, entry, data.tag() >> 3, ctx, msg); + } + + if (rep == field_layout::kRep64Bits) { + RefAt<uint64_t>(msg, entry.offset) = tmp; + } else if (rep == field_layout::kRep32Bits) { + RefAt<uint32_t>(msg, entry.offset) = static_cast<uint32_t>(tmp); + } else { + GOOGLE_DCHECK_EQ(rep, static_cast<uint16_t>(field_layout::kRep8Bits)); + RefAt<bool>(msg, entry.offset) = static_cast<bool>(tmp); + } + + PROTOBUF_MUSTTAIL return ToTagDispatch(PROTOBUF_TC_PARAM_PASS); +} + +const char* TcParser::MpRepeatedVarint(PROTOBUF_TC_PARAM_DECL) { + const auto& entry = RefAt<FieldEntry>(table, data.entry_offset()); + auto type_card = entry.type_card; + const uint32_t decoded_tag = data.tag(); + auto decoded_wiretype = decoded_tag & 7; + + // Check for packed repeated fallback: + if (decoded_wiretype == WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + PROTOBUF_MUSTTAIL return MpPackedVarint(PROTOBUF_TC_PARAM_PASS); + } + // Check for wire type mismatch: + if (decoded_wiretype != WireFormatLite::WIRETYPE_VARINT) { + PROTOBUF_MUSTTAIL return table->fallback(PROTOBUF_TC_PARAM_PASS); + } + uint16_t xform_val = (type_card & field_layout::kTvMask); + const bool is_zigzag = xform_val == field_layout::kTvZigZag; + const bool is_validated_enum = xform_val & field_layout::kTvEnum; + + uint16_t rep = type_card & field_layout::kRepMask; + if (rep == field_layout::kRep64Bits) { + auto& field = RefAt<RepeatedField<uint64_t>>(msg, entry.offset); + const char* ptr2 = ptr; + uint32_t next_tag; + do { + uint64_t tmp; + ptr = ParseVarint(ptr2, &tmp); + if (ptr == nullptr) return Error(PROTOBUF_TC_PARAM_PASS); + field.Add(is_zigzag ? WireFormatLite::ZigZagDecode64(tmp) : tmp); + if (!ctx->DataAvailable(ptr)) break; + ptr2 = ReadTag(ptr, &next_tag); + } while (next_tag == decoded_tag); + } else if (rep == field_layout::kRep32Bits) { + auto& field = RefAt<RepeatedField<uint32_t>>(msg, entry.offset); + const char* ptr2 = ptr; + uint32_t next_tag; + do { + uint64_t tmp; + ptr = ParseVarint(ptr2, &tmp); + if (ptr == nullptr) return Error(PROTOBUF_TC_PARAM_PASS); + if (is_validated_enum) { + if (!EnumIsValidAux(tmp, xform_val, *table->field_aux(&entry))) { + ptr = ptr2; + PROTOBUF_MUSTTAIL return table->fallback(PROTOBUF_TC_PARAM_PASS); + } + } else if (is_zigzag) { + tmp = WireFormatLite::ZigZagDecode32(tmp); + } + field.Add(tmp); + if (!ctx->DataAvailable(ptr)) break; + ptr2 = ReadTag(ptr, &next_tag); + } while (next_tag == decoded_tag); + } else { + GOOGLE_DCHECK_EQ(rep, static_cast<uint16_t>(field_layout::kRep8Bits)); + auto& field = RefAt<RepeatedField<bool>>(msg, entry.offset); + const char* ptr2 = ptr; + uint32_t next_tag; + do { + uint64_t tmp; + ptr = ParseVarint(ptr2, &tmp); + if (ptr == nullptr) return Error(PROTOBUF_TC_PARAM_PASS); + field.Add(static_cast<bool>(tmp)); + if (!ctx->DataAvailable(ptr)) break; + ptr2 = ReadTag(ptr, &next_tag); + } while (next_tag == decoded_tag); + } + + PROTOBUF_MUSTTAIL return ToTagDispatch(PROTOBUF_TC_PARAM_PASS); +} + +const char* TcParser::MpPackedVarint(PROTOBUF_TC_PARAM_DECL) { + const auto& entry = RefAt<FieldEntry>(table, data.entry_offset()); + auto type_card = entry.type_card; + auto decoded_wiretype = data.tag() & 7; + + // Check for non-packed repeated fallback: + if (decoded_wiretype != WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + PROTOBUF_MUSTTAIL return MpRepeatedVarint(PROTOBUF_TC_PARAM_PASS); + } + uint16_t xform_val = (type_card & field_layout::kTvMask); + const bool is_zigzag = xform_val == field_layout::kTvZigZag; + const bool is_validated_enum = xform_val & field_layout::kTvEnum; + if (is_validated_enum) { + // TODO(b/206890171): handle enums + PROTOBUF_MUSTTAIL return table->fallback(PROTOBUF_TC_PARAM_PASS); + } + + // Since ctx->ReadPackedFixed does not use TailCall<> or Return<>, sync any + // pending hasbits now: + SyncHasbits(msg, hasbits, table); + + uint16_t rep = type_card & field_layout::kRepMask; + if (rep == field_layout::kRep64Bits) { + auto* field = &RefAt<RepeatedField<uint64_t>>(msg, entry.offset); + return ctx->ReadPackedVarint(ptr, [field, is_zigzag](uint64_t value) { + field->Add(is_zigzag ? WireFormatLite::ZigZagDecode64(value) : value); + }); + } else if (rep == field_layout::kRep32Bits) { + auto* field = &RefAt<RepeatedField<uint32_t>>(msg, entry.offset); + return ctx->ReadPackedVarint(ptr, [field, is_zigzag](uint64_t value) { + field->Add(is_zigzag ? WireFormatLite::ZigZagDecode32( + static_cast<uint32_t>(value)) + : value); + }); + } else { + GOOGLE_DCHECK_EQ(rep, static_cast<uint16_t>(field_layout::kRep8Bits)); + auto* field = &RefAt<RepeatedField<bool>>(msg, entry.offset); + return ctx->ReadPackedVarint( + ptr, [field](uint64_t value) { field->Add(value); }); + } + + return Error(PROTOBUF_TC_PARAM_PASS); +} + +bool TcParser::MpVerifyUtf8(StringPiece wire_bytes, + const TcParseTableBase* table, + const FieldEntry& entry, uint16_t xform_val) { + if (xform_val == field_layout::kTvUtf8) { + if (!IsStructurallyValidUTF8(wire_bytes)) { + PrintUTF8ErrorLog(MessageName(table), FieldName(table, &entry), "parsing", + false); + return false; + } + return true; + } +#ifndef NDEBUG + if (xform_val == field_layout::kTvUtf8Debug) { + if (!IsStructurallyValidUTF8(wire_bytes)) { + PrintUTF8ErrorLog(MessageName(table), FieldName(table, &entry), "parsing", + false); + } + } +#endif // NDEBUG + return true; +} + +const char* TcParser::MpString(PROTOBUF_TC_PARAM_DECL) { + const auto& entry = RefAt<FieldEntry>(table, data.entry_offset()); + const uint16_t type_card = entry.type_card; + const uint16_t card = type_card & field_layout::kFcMask; + const uint32_t decoded_wiretype = data.tag() & 7; + + if (decoded_wiretype != WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + PROTOBUF_MUSTTAIL return table->fallback(PROTOBUF_TC_PARAM_PASS); + } + if (card == field_layout::kFcRepeated) { + PROTOBUF_MUSTTAIL return MpRepeatedString(PROTOBUF_TC_PARAM_PASS); + } + const uint16_t xform_val = type_card & field_layout::kTvMask; + const uint16_t rep = type_card & field_layout::kRepMask; + if (rep == field_layout::kRepIString) { + // TODO(b/198211897): support InilnedStringField. + PROTOBUF_MUSTTAIL return table->fallback(PROTOBUF_TC_PARAM_PASS); + } + + // Mark the field as present: + const bool is_oneof = card == field_layout::kFcOneof; + bool need_init = false; + if (card == field_layout::kFcOptional) { + SetHas(table, entry, msg, hasbits); + } else if (is_oneof) { + need_init = ChangeOneof(table, entry, data.tag() >> 3, ctx, msg); + } + + bool is_valid = false; + Arena* arena = ctx->data().arena; + switch (rep) { + case field_layout::kRepAString: { + auto& field = RefAt<ArenaStringPtr>(msg, entry.offset); + if (need_init) field.InitDefault(); + if (arena) { + ptr = ctx->ReadArenaString(ptr, &field, arena); + } else { + std::string* str = field.MutableNoCopy(nullptr); + ptr = InlineGreedyStringParser(str, ptr, ctx); + } + if (!ptr) break; + is_valid = MpVerifyUtf8(field.Get(), table, entry, xform_val); + break; + } + + case field_layout::kRepIString: { + break; + } + } + + if (ptr == nullptr || !is_valid) { + return Error(PROTOBUF_TC_PARAM_PASS); + } + return ToParseLoop(PROTOBUF_TC_PARAM_PASS); +} + +const char* TcParser::MpRepeatedString(PROTOBUF_TC_PARAM_DECL) { + const auto& entry = RefAt<FieldEntry>(table, data.entry_offset()); + const uint16_t type_card = entry.type_card; + const uint32_t decoded_tag = data.tag(); + const uint32_t decoded_wiretype = decoded_tag & 7; + + if (decoded_wiretype != WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + PROTOBUF_MUSTTAIL return table->fallback(PROTOBUF_TC_PARAM_PASS); + } + + const uint16_t rep = type_card & field_layout::kRepMask; + const uint16_t xform_val = type_card & field_layout::kTvMask; + switch (rep) { + case field_layout::kRepSString: { + auto& field = RefAt<RepeatedPtrField<std::string>>(msg, entry.offset); + const char* ptr2 = ptr; + uint32_t next_tag; + do { + ptr = ptr2; + std::string* str = field.Add(); + ptr = InlineGreedyStringParser(str, ptr, ctx); + if (PROTOBUF_PREDICT_FALSE( + ptr == nullptr || + !MpVerifyUtf8(*str, table, entry, xform_val))) { + return Error(PROTOBUF_TC_PARAM_PASS); + } + if (!ctx->DataAvailable(ptr)) break; + ptr2 = ReadTag(ptr, &next_tag); + } while (next_tag == decoded_tag); + break; + } + +#ifndef NDEBUG + default: + GOOGLE_LOG(FATAL) << "Unsupported repeated string rep: " << rep; + break; +#endif + } + + return ToParseLoop(PROTOBUF_TC_PARAM_PASS); +} + +const char* TcParser::MpMessage(PROTOBUF_TC_PARAM_DECL) { + const auto& entry = RefAt<FieldEntry>(table, data.entry_offset()); + const uint16_t type_card = entry.type_card; + const uint16_t card = type_card & field_layout::kFcMask; + + // Check for repeated parsing: + if (card == field_layout::kFcRepeated) { + PROTOBUF_MUSTTAIL return MpRepeatedMessage(PROTOBUF_TC_PARAM_PASS); + } + + const uint32_t decoded_tag = data.tag(); + const uint32_t decoded_wiretype = decoded_tag & 7; + const uint16_t rep = type_card & field_layout::kRepMask; + const bool is_group = rep == field_layout::kRepGroup; + + // Validate wiretype: + switch (rep) { + case field_layout::kRepMessage: + if (decoded_wiretype != WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + goto fallback; + } + break; + case field_layout::kRepGroup: + if (decoded_wiretype != WireFormatLite::WIRETYPE_START_GROUP) { + goto fallback; + } + break; + default: { + fallback: + // Lazy and implicit weak fields are handled by generated code: + // TODO(b/210762816): support these. + PROTOBUF_MUSTTAIL return table->fallback(PROTOBUF_TC_PARAM_PASS); + } + } + + const bool is_oneof = card == field_layout::kFcOneof; + bool need_init = false; + if (card == field_layout::kFcOptional) { + SetHas(table, entry, msg, hasbits); + } else if (is_oneof) { + need_init = ChangeOneof(table, entry, data.tag() >> 3, ctx, msg); + } + MessageLite*& field = RefAt<MessageLite*>(msg, entry.offset); + if (need_init || field == nullptr) { + const MessageLite* default_instance = + table->field_aux(&entry)->message_default; + field = default_instance->New(ctx->data().arena); + } + SyncHasbits(msg, hasbits, table); + if (is_group) { + return ctx->ParseGroup(field, ptr, decoded_tag); + } + return ctx->ParseMessage(field, ptr); +} + +const char* TcParser::MpRepeatedMessage(PROTOBUF_TC_PARAM_DECL) { + const auto& entry = RefAt<FieldEntry>(table, data.entry_offset()); + const uint16_t type_card = entry.type_card; + GOOGLE_DCHECK_EQ(type_card & field_layout::kFcMask, + static_cast<uint16_t>(field_layout::kFcRepeated)); + const uint32_t decoded_tag = data.tag(); + const uint32_t decoded_wiretype = decoded_tag & 7; + const uint16_t rep = type_card & field_layout::kRepMask; + const bool is_group = rep == field_layout::kRepGroup; + + // Validate wiretype: + switch (rep) { + case field_layout::kRepMessage: + if (decoded_wiretype != WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + goto fallback; + } + break; + case field_layout::kRepGroup: + if (decoded_wiretype != WireFormatLite::WIRETYPE_START_GROUP) { + goto fallback; + } + break; + default: { + fallback: + // Lazy and implicit weak fields are handled by generated code: + // TODO(b/210762816): support these. + PROTOBUF_MUSTTAIL return table->fallback(PROTOBUF_TC_PARAM_PASS); + } + } + + SyncHasbits(msg, hasbits, table); + const MessageLite* default_instance = + table->field_aux(&entry)->message_default; + auto& field = RefAt<RepeatedPtrFieldBase>(msg, entry.offset); + MessageLite* value = + field.Add<GenericTypeHandler<MessageLite>>(default_instance); + if (is_group) { + return ctx->ParseGroup(value, ptr, decoded_tag); + } + return ctx->ParseMessage(value, ptr); +} + +const char* TcParser::MpMap(PROTOBUF_TC_PARAM_DECL) { + const auto& entry = RefAt<FieldEntry>(table, data.entry_offset()); + (void)entry; + PROTOBUF_MUSTTAIL return table->fallback(PROTOBUF_TC_PARAM_PASS); +} + +} // namespace internal +} // namespace protobuf +} // namespace google diff --git a/toolkit/components/protobuf/src/google/protobuf/generated_message_util.cc b/toolkit/components/protobuf/src/google/protobuf/generated_message_util.cc new file mode 100644 index 0000000000..cad12a3511 --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/generated_message_util.cc @@ -0,0 +1,409 @@ +// 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. + +// Author: kenton@google.com (Kenton Varda) +// Based on original Protocol Buffers design by +// Sanjay Ghemawat, Jeff Dean, and others. + +#include <google/protobuf/generated_message_util.h> + +#include <atomic> +#include <limits> +#include <vector> + +#include <google/protobuf/io/coded_stream.h> +#include <google/protobuf/io/zero_copy_stream_impl_lite.h> +#include <google/protobuf/arenastring.h> +#include <google/protobuf/extension_set.h> +#include <google/protobuf/message_lite.h> +#include <google/protobuf/metadata_lite.h> +#include <google/protobuf/repeated_field.h> +#include <google/protobuf/wire_format_lite.h> + +// Must be included last +#include <google/protobuf/port_def.inc> + +PROTOBUF_PRAGMA_INIT_SEG + + +namespace google { +namespace protobuf { +namespace internal { + +void DestroyMessage(const void* message) { + static_cast<const MessageLite*>(message)->~MessageLite(); +} +void DestroyString(const void* s) { + static_cast<const std::string*>(s)->~basic_string(); +} + +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT + PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 ExplicitlyConstructedArenaString + fixed_address_empty_string{}; // NOLINT + + +PROTOBUF_CONSTINIT std::atomic<bool> init_protobuf_defaults_state{false}; +static bool InitProtobufDefaultsImpl() { + fixed_address_empty_string.DefaultConstruct(); + OnShutdownDestroyString(fixed_address_empty_string.get_mutable()); + + + init_protobuf_defaults_state.store(true, std::memory_order_release); + return true; +} + +void InitProtobufDefaultsSlow() { + static bool is_inited = InitProtobufDefaultsImpl(); + (void)is_inited; +} +// Force the initialization of the empty string. +// Normally, registration would do it, but we don't have any guarantee that +// there is any object with reflection. +PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 static std::true_type init_empty_string = + (InitProtobufDefaultsSlow(), std::true_type{}); + +size_t StringSpaceUsedExcludingSelfLong(const std::string& str) { + const void* start = &str; + const void* end = &str + 1; + if (start <= str.data() && str.data() < end) { + // The string's data is stored inside the string object itself. + return 0; + } else { + return str.capacity(); + } +} + +template <typename T> +const T& Get(const void* ptr) { + return *static_cast<const T*>(ptr); +} + +// PrimitiveTypeHelper is a wrapper around the interface of WireFormatLite. +// WireFormatLite has a very inconvenient interface with respect to template +// meta-programming. This class wraps the different named functions into +// a single Serialize / SerializeToArray interface. +template <int type> +struct PrimitiveTypeHelper; + +template <> +struct PrimitiveTypeHelper<WireFormatLite::TYPE_BOOL> { + typedef bool Type; + static void Serialize(const void* ptr, io::CodedOutputStream* output) { + WireFormatLite::WriteBoolNoTag(Get<bool>(ptr), output); + } + static uint8_t* SerializeToArray(const void* ptr, uint8_t* buffer) { + return WireFormatLite::WriteBoolNoTagToArray(Get<Type>(ptr), buffer); + } +}; + +template <> +struct PrimitiveTypeHelper<WireFormatLite::TYPE_INT32> { + typedef int32_t Type; + static void Serialize(const void* ptr, io::CodedOutputStream* output) { + WireFormatLite::WriteInt32NoTag(Get<int32_t>(ptr), output); + } + static uint8_t* SerializeToArray(const void* ptr, uint8_t* buffer) { + return WireFormatLite::WriteInt32NoTagToArray(Get<Type>(ptr), buffer); + } +}; + +template <> +struct PrimitiveTypeHelper<WireFormatLite::TYPE_SINT32> { + typedef int32_t Type; + static void Serialize(const void* ptr, io::CodedOutputStream* output) { + WireFormatLite::WriteSInt32NoTag(Get<int32_t>(ptr), output); + } + static uint8_t* SerializeToArray(const void* ptr, uint8_t* buffer) { + return WireFormatLite::WriteSInt32NoTagToArray(Get<Type>(ptr), buffer); + } +}; + +template <> +struct PrimitiveTypeHelper<WireFormatLite::TYPE_UINT32> { + typedef uint32_t Type; + static void Serialize(const void* ptr, io::CodedOutputStream* output) { + WireFormatLite::WriteUInt32NoTag(Get<uint32_t>(ptr), output); + } + static uint8_t* SerializeToArray(const void* ptr, uint8_t* buffer) { + return WireFormatLite::WriteUInt32NoTagToArray(Get<Type>(ptr), buffer); + } +}; +template <> +struct PrimitiveTypeHelper<WireFormatLite::TYPE_INT64> { + typedef int64_t Type; + static void Serialize(const void* ptr, io::CodedOutputStream* output) { + WireFormatLite::WriteInt64NoTag(Get<int64_t>(ptr), output); + } + static uint8_t* SerializeToArray(const void* ptr, uint8_t* buffer) { + return WireFormatLite::WriteInt64NoTagToArray(Get<Type>(ptr), buffer); + } +}; + +template <> +struct PrimitiveTypeHelper<WireFormatLite::TYPE_SINT64> { + typedef int64_t Type; + static void Serialize(const void* ptr, io::CodedOutputStream* output) { + WireFormatLite::WriteSInt64NoTag(Get<int64_t>(ptr), output); + } + static uint8_t* SerializeToArray(const void* ptr, uint8_t* buffer) { + return WireFormatLite::WriteSInt64NoTagToArray(Get<Type>(ptr), buffer); + } +}; +template <> +struct PrimitiveTypeHelper<WireFormatLite::TYPE_UINT64> { + typedef uint64_t Type; + static void Serialize(const void* ptr, io::CodedOutputStream* output) { + WireFormatLite::WriteUInt64NoTag(Get<uint64_t>(ptr), output); + } + static uint8_t* SerializeToArray(const void* ptr, uint8_t* buffer) { + return WireFormatLite::WriteUInt64NoTagToArray(Get<Type>(ptr), buffer); + } +}; + +template <> +struct PrimitiveTypeHelper<WireFormatLite::TYPE_FIXED32> { + typedef uint32_t Type; + static void Serialize(const void* ptr, io::CodedOutputStream* output) { + WireFormatLite::WriteFixed32NoTag(Get<uint32_t>(ptr), output); + } + static uint8_t* SerializeToArray(const void* ptr, uint8_t* buffer) { + return WireFormatLite::WriteFixed32NoTagToArray(Get<Type>(ptr), buffer); + } +}; + +template <> +struct PrimitiveTypeHelper<WireFormatLite::TYPE_FIXED64> { + typedef uint64_t Type; + static void Serialize(const void* ptr, io::CodedOutputStream* output) { + WireFormatLite::WriteFixed64NoTag(Get<uint64_t>(ptr), output); + } + static uint8_t* SerializeToArray(const void* ptr, uint8_t* buffer) { + return WireFormatLite::WriteFixed64NoTagToArray(Get<Type>(ptr), buffer); + } +}; + +template <> +struct PrimitiveTypeHelper<WireFormatLite::TYPE_ENUM> + : PrimitiveTypeHelper<WireFormatLite::TYPE_INT32> {}; + +template <> +struct PrimitiveTypeHelper<WireFormatLite::TYPE_SFIXED32> + : PrimitiveTypeHelper<WireFormatLite::TYPE_FIXED32> { + typedef int32_t Type; +}; +template <> +struct PrimitiveTypeHelper<WireFormatLite::TYPE_SFIXED64> + : PrimitiveTypeHelper<WireFormatLite::TYPE_FIXED64> { + typedef int64_t Type; +}; +template <> +struct PrimitiveTypeHelper<WireFormatLite::TYPE_FLOAT> + : PrimitiveTypeHelper<WireFormatLite::TYPE_FIXED32> { + typedef float Type; +}; +template <> +struct PrimitiveTypeHelper<WireFormatLite::TYPE_DOUBLE> + : PrimitiveTypeHelper<WireFormatLite::TYPE_FIXED64> { + typedef double Type; +}; + +template <> +struct PrimitiveTypeHelper<WireFormatLite::TYPE_STRING> { + typedef std::string Type; + static void Serialize(const void* ptr, io::CodedOutputStream* output) { + const Type& value = *static_cast<const Type*>(ptr); + output->WriteVarint32(value.size()); + output->WriteRawMaybeAliased(value.data(), value.size()); + } + static uint8_t* SerializeToArray(const void* ptr, uint8_t* buffer) { + const Type& value = *static_cast<const Type*>(ptr); + return io::CodedOutputStream::WriteStringWithSizeToArray(value, buffer); + } +}; + +template <> +struct PrimitiveTypeHelper<WireFormatLite::TYPE_BYTES> + : PrimitiveTypeHelper<WireFormatLite::TYPE_STRING> {}; + +// We want to serialize to both CodedOutputStream and directly into byte arrays +// without duplicating the code. In fact we might want extra output channels in +// the future. +template <typename O, int type> +struct OutputHelper; + +template <int type, typename O> +void SerializeTo(const void* ptr, O* output) { + OutputHelper<O, type>::Serialize(ptr, output); +} + +template <typename O> +void WriteTagTo(uint32_t tag, O* output) { + SerializeTo<WireFormatLite::TYPE_UINT32>(&tag, output); +} + +template <typename O> +void WriteLengthTo(uint32_t length, O* output) { + SerializeTo<WireFormatLite::TYPE_UINT32>(&length, output); +} + +// Specialization for coded output stream +template <int type> +struct OutputHelper<io::CodedOutputStream, type> { + static void Serialize(const void* ptr, io::CodedOutputStream* output) { + PrimitiveTypeHelper<type>::Serialize(ptr, output); + } +}; + +// Specialization for writing into a plain array +struct ArrayOutput { + uint8_t* ptr; + bool is_deterministic; +}; + +template <int type> +struct OutputHelper<ArrayOutput, type> { + static void Serialize(const void* ptr, ArrayOutput* output) { + output->ptr = PrimitiveTypeHelper<type>::SerializeToArray(ptr, output->ptr); + } +}; + +void SerializeMessageNoTable(const MessageLite* msg, + io::CodedOutputStream* output) { + msg->SerializeWithCachedSizes(output); +} + +void SerializeMessageNoTable(const MessageLite* msg, ArrayOutput* output) { + io::ArrayOutputStream array_stream(output->ptr, INT_MAX); + io::CodedOutputStream o(&array_stream); + o.SetSerializationDeterministic(output->is_deterministic); + msg->SerializeWithCachedSizes(&o); + output->ptr += o.ByteCount(); +} + +// We need to use a helper class to get access to the private members +class AccessorHelper { + public: + static int Size(const RepeatedPtrFieldBase& x) { return x.size(); } + static void const* Get(const RepeatedPtrFieldBase& x, int idx) { + return x.raw_data()[idx]; + } +}; + +void SerializeNotImplemented(int field) { + GOOGLE_LOG(FATAL) << "Not implemented field number " << field; +} + +// When switching to c++11 we should make these constexpr functions +#define SERIALIZE_TABLE_OP(type, type_class) \ + ((type - 1) + static_cast<int>(type_class) * FieldMetadata::kNumTypes) + +template <int type> +bool IsNull(const void* ptr) { + return *static_cast<const typename PrimitiveTypeHelper<type>::Type*>(ptr) == + 0; +} + +template <> +bool IsNull<WireFormatLite::TYPE_STRING>(const void* ptr) { + return static_cast<const ArenaStringPtr*>(ptr)->Get().size() == 0; +} + +template <> +bool IsNull<WireFormatLite::TYPE_BYTES>(const void* ptr) { + return static_cast<const ArenaStringPtr*>(ptr)->Get().size() == 0; +} + +template <> +bool IsNull<WireFormatLite::TYPE_GROUP>(const void* ptr) { + return Get<const MessageLite*>(ptr) == nullptr; +} + +template <> +bool IsNull<WireFormatLite::TYPE_MESSAGE>(const void* ptr) { + return Get<const MessageLite*>(ptr) == nullptr; +} + +void ExtensionSerializer(const MessageLite* extendee, const uint8_t* ptr, + uint32_t offset, uint32_t tag, uint32_t has_offset, + io::CodedOutputStream* output) { + reinterpret_cast<const ExtensionSet*>(ptr + offset) + ->SerializeWithCachedSizes(extendee, tag, has_offset, output); +} + +void UnknownFieldSerializerLite(const uint8_t* ptr, uint32_t offset, + uint32_t /*tag*/, uint32_t /*has_offset*/, + io::CodedOutputStream* output) { + output->WriteString( + reinterpret_cast<const InternalMetadata*>(ptr + offset) + ->unknown_fields<std::string>(&internal::GetEmptyString)); +} + +MessageLite* DuplicateIfNonNullInternal(MessageLite* message) { + if (message) { + MessageLite* ret = message->New(); + ret->CheckTypeAndMergeFrom(*message); + return ret; + } else { + return nullptr; + } +} + +void GenericSwap(MessageLite* m1, MessageLite* m2) { + std::unique_ptr<MessageLite> tmp(m1->New()); + tmp->CheckTypeAndMergeFrom(*m1); + m1->Clear(); + m1->CheckTypeAndMergeFrom(*m2); + m2->Clear(); + m2->CheckTypeAndMergeFrom(*tmp); +} + +// Returns a message owned by this Arena. This may require Own()ing or +// duplicating the message. +MessageLite* GetOwnedMessageInternal(Arena* message_arena, + MessageLite* submessage, + Arena* submessage_arena) { + GOOGLE_DCHECK(Arena::InternalGetOwningArena(submessage) == submessage_arena); + GOOGLE_DCHECK(message_arena != submessage_arena); + GOOGLE_DCHECK_EQ(submessage_arena, nullptr); + if (message_arena != nullptr && submessage_arena == nullptr) { + message_arena->Own(submessage); + return submessage; + } else { + MessageLite* ret = submessage->New(message_arena); + ret->CheckTypeAndMergeFrom(*submessage); + return ret; + } +} + +} // namespace internal +} // namespace protobuf +} // namespace google + +#include <google/protobuf/port_undef.inc> diff --git a/toolkit/components/protobuf/src/google/protobuf/generated_message_util.h b/toolkit/components/protobuf/src/google/protobuf/generated_message_util.h new file mode 100644 index 0000000000..71d15cdebc --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/generated_message_util.h @@ -0,0 +1,214 @@ +// 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. + +// Author: kenton@google.com (Kenton Varda) +// Based on original Protocol Buffers design by +// Sanjay Ghemawat, Jeff Dean, and others. +// +// This file contains miscellaneous helper code used by generated code -- +// including lite types -- but which should not be used directly by users. + +#ifndef GOOGLE_PROTOBUF_GENERATED_MESSAGE_UTIL_H__ +#define GOOGLE_PROTOBUF_GENERATED_MESSAGE_UTIL_H__ + +#include <assert.h> + +#include <atomic> +#include <climits> +#include <string> +#include <vector> + +#include <google/protobuf/stubs/common.h> +#include <google/protobuf/stubs/once.h> // Add direct dep on port for pb.cc +#include <google/protobuf/port.h> +#include <google/protobuf/stubs/strutil.h> +#include <google/protobuf/any.h> +#include <google/protobuf/has_bits.h> +#include <google/protobuf/implicit_weak_message.h> +#include <google/protobuf/message_lite.h> +#include <google/protobuf/repeated_field.h> +#include <google/protobuf/wire_format_lite.h> +#include <google/protobuf/stubs/casts.h> + +// Must be included last. +#include <google/protobuf/port_def.inc> + +#ifdef SWIG +#error "You cannot SWIG proto headers" +#endif + +namespace google { +namespace protobuf { + +class Arena; +class Message; + +namespace io { +class CodedInputStream; +} + +namespace internal { + +template <typename To, typename From> +inline To DownCast(From* f) { + return PROTOBUF_NAMESPACE_ID::internal::down_cast<To>(f); +} +template <typename To, typename From> +inline To DownCast(From& f) { + return PROTOBUF_NAMESPACE_ID::internal::down_cast<To>(f); +} + + +// This fastpath inlines a single branch instead of having to make the +// InitProtobufDefaults function call. +// It also generates less inlined code than a function-scope static initializer. +PROTOBUF_EXPORT extern std::atomic<bool> init_protobuf_defaults_state; +PROTOBUF_EXPORT void InitProtobufDefaultsSlow(); +PROTOBUF_EXPORT inline void InitProtobufDefaults() { + if (PROTOBUF_PREDICT_FALSE( + !init_protobuf_defaults_state.load(std::memory_order_acquire))) { + InitProtobufDefaultsSlow(); + } +} + +// This used by proto1 +PROTOBUF_EXPORT inline const std::string& GetEmptyString() { + InitProtobufDefaults(); + return GetEmptyStringAlreadyInited(); +} + + +// True if IsInitialized() is true for all elements of t. Type is expected +// to be a RepeatedPtrField<some message type>. It's useful to have this +// helper here to keep the protobuf compiler from ever having to emit loops in +// IsInitialized() methods. We want the C++ compiler to inline this or not +// as it sees fit. +template <typename Msg> +bool AllAreInitialized(const RepeatedPtrField<Msg>& t) { + for (int i = t.size(); --i >= 0;) { + if (!t.Get(i).IsInitialized()) return false; + } + return true; +} + +// "Weak" variant of AllAreInitialized, used to implement implicit weak fields. +// This version operates on MessageLite to avoid introducing a dependency on the +// concrete message type. +template <class T> +bool AllAreInitializedWeak(const RepeatedPtrField<T>& t) { + for (int i = t.size(); --i >= 0;) { + if (!reinterpret_cast<const RepeatedPtrFieldBase&>(t) + .Get<ImplicitWeakTypeHandler<T> >(i) + .IsInitialized()) { + return false; + } + } + return true; +} + +inline bool IsPresent(const void* base, uint32_t hasbit) { + const uint32_t* has_bits_array = static_cast<const uint32_t*>(base); + return (has_bits_array[hasbit / 32] & (1u << (hasbit & 31))) != 0; +} + +inline bool IsOneofPresent(const void* base, uint32_t offset, uint32_t tag) { + const uint32_t* oneof = reinterpret_cast<const uint32_t*>( + static_cast<const uint8_t*>(base) + offset); + return *oneof == tag >> 3; +} + +typedef void (*SpecialSerializer)(const uint8_t* base, uint32_t offset, + uint32_t tag, uint32_t has_offset, + io::CodedOutputStream* output); + +PROTOBUF_EXPORT void ExtensionSerializer(const MessageLite* extendee, + const uint8_t* ptr, uint32_t offset, + uint32_t tag, uint32_t has_offset, + io::CodedOutputStream* output); +PROTOBUF_EXPORT void UnknownFieldSerializerLite(const uint8_t* base, + uint32_t offset, uint32_t tag, + uint32_t has_offset, + io::CodedOutputStream* output); + +PROTOBUF_EXPORT MessageLite* DuplicateIfNonNullInternal(MessageLite* message); +PROTOBUF_EXPORT MessageLite* GetOwnedMessageInternal(Arena* message_arena, + MessageLite* submessage, + Arena* submessage_arena); +PROTOBUF_EXPORT void GenericSwap(MessageLite* m1, MessageLite* m2); +// We specialize GenericSwap for non-lite messages to benefit from reflection. +PROTOBUF_EXPORT void GenericSwap(Message* m1, Message* m2); + +template <typename T> +T* DuplicateIfNonNull(T* message) { + // The casts must be reinterpret_cast<> because T might be a forward-declared + // type that the compiler doesn't know is related to MessageLite. + return reinterpret_cast<T*>( + DuplicateIfNonNullInternal(reinterpret_cast<MessageLite*>(message))); +} + +template <typename T> +T* GetOwnedMessage(Arena* message_arena, T* submessage, + Arena* submessage_arena) { + // The casts must be reinterpret_cast<> because T might be a forward-declared + // type that the compiler doesn't know is related to MessageLite. + return reinterpret_cast<T*>(GetOwnedMessageInternal( + message_arena, reinterpret_cast<MessageLite*>(submessage), + submessage_arena)); +} + +// Hide atomic from the public header and allow easy change to regular int +// on platforms where the atomic might have a perf impact. +class PROTOBUF_EXPORT CachedSize { + public: + int Get() const { return size_.load(std::memory_order_relaxed); } + void Set(int size) { size_.store(size, std::memory_order_relaxed); } + + private: + std::atomic<int> size_{0}; +}; + +PROTOBUF_EXPORT void DestroyMessage(const void* message); +PROTOBUF_EXPORT void DestroyString(const void* s); +// Destroy (not delete) the message +inline void OnShutdownDestroyMessage(const void* ptr) { + OnShutdownRun(DestroyMessage, ptr); +} +// Destroy the string (call std::string destructor) +inline void OnShutdownDestroyString(const std::string* ptr) { + OnShutdownRun(DestroyString, ptr); +} + +} // namespace internal +} // namespace protobuf +} // namespace google + +#include <google/protobuf/port_undef.inc> + +#endif // GOOGLE_PROTOBUF_GENERATED_MESSAGE_UTIL_H__ diff --git a/toolkit/components/protobuf/src/google/protobuf/has_bits.h b/toolkit/components/protobuf/src/google/protobuf/has_bits.h new file mode 100644 index 0000000000..f8a45879f1 --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/has_bits.h @@ -0,0 +1,117 @@ +// 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. + +#ifndef GOOGLE_PROTOBUF_HAS_BITS_H__ +#define GOOGLE_PROTOBUF_HAS_BITS_H__ + +#include <google/protobuf/stubs/common.h> +#include <google/protobuf/port.h> + +// Must be included last. +#include <google/protobuf/port_def.inc> + +#ifdef SWIG +#error "You cannot SWIG proto headers" +#endif + +namespace google { +namespace protobuf { +namespace internal { + +template <size_t doublewords> +class HasBits { + public: + PROTOBUF_NDEBUG_INLINE constexpr HasBits() : has_bits_{} {} + + PROTOBUF_NDEBUG_INLINE void Clear() { + memset(has_bits_, 0, sizeof(has_bits_)); + } + + PROTOBUF_NDEBUG_INLINE uint32_t& operator[](int index) { + return has_bits_[index]; + } + + PROTOBUF_NDEBUG_INLINE const uint32_t& operator[](int index) const { + return has_bits_[index]; + } + + bool operator==(const HasBits<doublewords>& rhs) const { + return memcmp(has_bits_, rhs.has_bits_, sizeof(has_bits_)) == 0; + } + + bool operator!=(const HasBits<doublewords>& rhs) const { + return !(*this == rhs); + } + + void Or(const HasBits<doublewords>& rhs) { + for (size_t i = 0; i < doublewords; i++) has_bits_[i] |= rhs[i]; + } + + bool empty() const; + + private: + uint32_t has_bits_[doublewords]; +}; + +template <> +inline bool HasBits<1>::empty() const { + return !has_bits_[0]; +} + +template <> +inline bool HasBits<2>::empty() const { + return !(has_bits_[0] | has_bits_[1]); +} + +template <> +inline bool HasBits<3>::empty() const { + return !(has_bits_[0] | has_bits_[1] | has_bits_[2]); +} + +template <> +inline bool HasBits<4>::empty() const { + return !(has_bits_[0] | has_bits_[1] | has_bits_[2] | has_bits_[3]); +} + +template <size_t doublewords> +inline bool HasBits<doublewords>::empty() const { + for (size_t i = 0; i < doublewords; ++i) { + if (has_bits_[i]) return false; + } + return true; +} + +} // namespace internal +} // namespace protobuf +} // namespace google + +#include <google/protobuf/port_undef.inc> + +#endif // GOOGLE_PROTOBUF_HAS_BITS_H__ diff --git a/toolkit/components/protobuf/src/google/protobuf/implicit_weak_message.cc b/toolkit/components/protobuf/src/google/protobuf/implicit_weak_message.cc new file mode 100644 index 0000000000..27ed6b65d2 --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/implicit_weak_message.cc @@ -0,0 +1,72 @@ +// 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. + +#include <google/protobuf/implicit_weak_message.h> + +#include <google/protobuf/io/zero_copy_stream_impl_lite.h> +#include <google/protobuf/parse_context.h> +#include <google/protobuf/wire_format_lite.h> + +// Must be included last. +#include <google/protobuf/port_def.inc> + +PROTOBUF_PRAGMA_INIT_SEG + +namespace google { +namespace protobuf { +namespace internal { + +const char* ImplicitWeakMessage::_InternalParse(const char* ptr, + ParseContext* ctx) { + return ctx->AppendString(ptr, data_); +} + +struct ImplicitWeakMessageDefaultType { + constexpr ImplicitWeakMessageDefaultType() + : instance(ConstantInitialized{}) {} + ~ImplicitWeakMessageDefaultType() {} + union { + ImplicitWeakMessage instance; + }; +}; + +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT ImplicitWeakMessageDefaultType + implicit_weak_message_default_instance; + +const ImplicitWeakMessage* ImplicitWeakMessage::default_instance() { + return reinterpret_cast<ImplicitWeakMessage*>( + &implicit_weak_message_default_instance); +} + +} // namespace internal +} // namespace protobuf +} // namespace google + +#include <google/protobuf/port_undef.inc> diff --git a/toolkit/components/protobuf/src/google/protobuf/implicit_weak_message.h b/toolkit/components/protobuf/src/google/protobuf/implicit_weak_message.h new file mode 100644 index 0000000000..b894ab4809 --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/implicit_weak_message.h @@ -0,0 +1,213 @@ +// 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. + +#ifndef GOOGLE_PROTOBUF_IMPLICIT_WEAK_MESSAGE_H__ +#define GOOGLE_PROTOBUF_IMPLICIT_WEAK_MESSAGE_H__ + +#include <string> + +#include <google/protobuf/io/coded_stream.h> +#include <google/protobuf/arena.h> +#include <google/protobuf/message_lite.h> +#include <google/protobuf/repeated_field.h> + +#ifdef SWIG +#error "You cannot SWIG proto headers" +#endif + +// Must be included last. +#include <google/protobuf/port_def.inc> + +// This file is logically internal-only and should only be used by protobuf +// generated code. + +namespace google { +namespace protobuf { +namespace internal { + +// An implementation of MessageLite that treats all data as unknown. This type +// acts as a placeholder for an implicit weak field in the case where the true +// message type does not get linked into the binary. +class PROTOBUF_EXPORT ImplicitWeakMessage : public MessageLite { + public: + ImplicitWeakMessage() : data_(new std::string) {} + explicit constexpr ImplicitWeakMessage(ConstantInitialized) + : data_(nullptr) {} + explicit ImplicitWeakMessage(Arena* arena) + : MessageLite(arena), data_(new std::string) {} + + ~ImplicitWeakMessage() override { + // data_ will be null in the default instance, but we can safely call delete + // here because the default instance will never be destroyed. + delete data_; + } + + static const ImplicitWeakMessage* default_instance(); + + std::string GetTypeName() const override { return ""; } + + MessageLite* New(Arena* arena) const override { + return Arena::CreateMessage<ImplicitWeakMessage>(arena); + } + + void Clear() override { data_->clear(); } + + bool IsInitialized() const override { return true; } + + void CheckTypeAndMergeFrom(const MessageLite& other) override { + const std::string* other_data = + static_cast<const ImplicitWeakMessage&>(other).data_; + if (other_data != nullptr) { + data_->append(*other_data); + } + } + + const char* _InternalParse(const char* ptr, ParseContext* ctx) final; + + size_t ByteSizeLong() const override { + return data_ == nullptr ? 0 : data_->size(); + } + + uint8_t* _InternalSerialize(uint8_t* target, + io::EpsCopyOutputStream* stream) const final { + if (data_ == nullptr) { + return target; + } + return stream->WriteRaw(data_->data(), static_cast<int>(data_->size()), + target); + } + + int GetCachedSize() const override { + return data_ == nullptr ? 0 : static_cast<int>(data_->size()); + } + + typedef void InternalArenaConstructable_; + + private: + // This std::string is allocated on the heap, but we use a raw pointer so that + // the default instance can be constant-initialized. In the const methods, we + // have to handle the possibility of data_ being null. + std::string* data_; + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImplicitWeakMessage); +}; + +struct ImplicitWeakMessageDefaultType; +extern ImplicitWeakMessageDefaultType implicit_weak_message_default_instance; + +// A type handler for use with implicit weak repeated message fields. +template <typename ImplicitWeakType> +class ImplicitWeakTypeHandler { + public: + typedef MessageLite Type; + static constexpr bool Moveable = false; + + static inline MessageLite* NewFromPrototype(const MessageLite* prototype, + Arena* arena = nullptr) { + return prototype->New(arena); + } + + static inline void Delete(MessageLite* value, Arena* arena) { + if (arena == nullptr) { + delete value; + } + } + static inline Arena* GetArena(MessageLite* value) { + return value->GetArena(); + } + static inline void Clear(MessageLite* value) { value->Clear(); } + static void Merge(const MessageLite& from, MessageLite* to) { + to->CheckTypeAndMergeFrom(from); + } +}; + +} // namespace internal + +template <typename T> +struct WeakRepeatedPtrField { + using TypeHandler = internal::ImplicitWeakTypeHandler<T>; + constexpr WeakRepeatedPtrField() : weak() {} + explicit WeakRepeatedPtrField(Arena* arena) : weak(arena) {} + ~WeakRepeatedPtrField() { weak.template Destroy<TypeHandler>(); } + + typedef internal::RepeatedPtrIterator<MessageLite> iterator; + typedef internal::RepeatedPtrIterator<const MessageLite> const_iterator; + typedef internal::RepeatedPtrOverPtrsIterator<MessageLite*, void*> + pointer_iterator; + typedef internal::RepeatedPtrOverPtrsIterator<const MessageLite* const, + const void* const> + const_pointer_iterator; + + iterator begin() { return iterator(base().raw_data()); } + const_iterator begin() const { return iterator(base().raw_data()); } + const_iterator cbegin() const { return begin(); } + iterator end() { return begin() + base().size(); } + const_iterator end() const { return begin() + base().size(); } + const_iterator cend() const { return end(); } + pointer_iterator pointer_begin() { + return pointer_iterator(base().raw_mutable_data()); + } + const_pointer_iterator pointer_begin() const { + return const_pointer_iterator(base().raw_mutable_data()); + } + pointer_iterator pointer_end() { + return pointer_iterator(base().raw_mutable_data() + base().size()); + } + const_pointer_iterator pointer_end() const { + return const_pointer_iterator(base().raw_mutable_data() + base().size()); + } + + MessageLite* AddWeak(const MessageLite* prototype) { + return base().AddWeak(prototype); + } + T* Add() { return weak.Add(); } + void Clear() { base().template Clear<TypeHandler>(); } + void MergeFrom(const WeakRepeatedPtrField& other) { + base().template MergeFrom<TypeHandler>(other.base()); + } + void InternalSwap(WeakRepeatedPtrField* other) { + base().InternalSwap(&other->base()); + } + + const internal::RepeatedPtrFieldBase& base() const { return weak; } + internal::RepeatedPtrFieldBase& base() { return weak; } + // Union disables running the destructor. Which would create a strong link. + // Instead we explicitly destroy the underlying base through the virtual + // destructor. + union { + RepeatedPtrField<T> weak; + }; +}; + +} // namespace protobuf +} // namespace google + +#include <google/protobuf/port_undef.inc> + +#endif // GOOGLE_PROTOBUF_IMPLICIT_WEAK_MESSAGE_H__ diff --git a/toolkit/components/protobuf/src/google/protobuf/inlined_string_field.cc b/toolkit/components/protobuf/src/google/protobuf/inlined_string_field.cc new file mode 100644 index 0000000000..0c3e4766fd --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/inlined_string_field.cc @@ -0,0 +1,118 @@ +// 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. + +#include <google/protobuf/inlined_string_field.h> + +#include <google/protobuf/arena.h> +#include <google/protobuf/arenastring.h> +#include <google/protobuf/generated_message_util.h> +#include <google/protobuf/message_lite.h> +#include <google/protobuf/parse_context.h> + +// clang-format off +#include <google/protobuf/port_def.inc> +// clang-format on + +namespace google { +namespace protobuf { +namespace internal { + + +std::string* InlinedStringField::Mutable(const LazyString& /*default_value*/, + Arena* arena, bool donated, + uint32_t* donating_states, + uint32_t mask, MessageLite* msg) { + if (arena == nullptr || !donated) { + return UnsafeMutablePointer(); + } + return MutableSlow(arena, donated, donating_states, mask, msg); +} + +std::string* InlinedStringField::Mutable(Arena* arena, bool donated, + uint32_t* donating_states, + uint32_t mask, MessageLite* msg) { + if (arena == nullptr || !donated) { + return UnsafeMutablePointer(); + } + return MutableSlow(arena, donated, donating_states, mask, msg); +} + +std::string* InlinedStringField::MutableSlow(::google::protobuf::Arena* arena, + bool donated, + uint32_t* donating_states, + uint32_t mask, MessageLite* msg) { + (void)mask; + (void)msg; + return UnsafeMutablePointer(); +} + +void InlinedStringField::SetAllocated(const std::string* default_value, + std::string* value, Arena* arena, + bool donated, uint32_t* donating_states, + uint32_t mask, MessageLite* msg) { + (void)mask; + (void)msg; + SetAllocatedNoArena(default_value, value); +} + +void InlinedStringField::Set(std::string&& value, Arena* arena, bool donated, + uint32_t* donating_states, uint32_t mask, + MessageLite* msg) { + (void)donating_states; + (void)mask; + (void)msg; + SetNoArena(std::move(value)); +} + +std::string* InlinedStringField::Release() { + auto* released = new std::string(std::move(*get_mutable())); + get_mutable()->clear(); + return released; +} + +std::string* InlinedStringField::Release(Arena* arena, bool donated) { + // We can not steal donated arena strings. + std::string* released = (arena != nullptr && donated) + ? new std::string(*get_mutable()) + : new std::string(std::move(*get_mutable())); + get_mutable()->clear(); + return released; +} + +void InlinedStringField::ClearToDefault(const LazyString& default_value, + Arena* arena, bool donated) { + (void)arena; + get_mutable()->assign(default_value.get()); +} + + +} // namespace internal +} // namespace protobuf +} // namespace google diff --git a/toolkit/components/protobuf/src/google/protobuf/inlined_string_field.h b/toolkit/components/protobuf/src/google/protobuf/inlined_string_field.h new file mode 100644 index 0000000000..79e37d414b --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/inlined_string_field.h @@ -0,0 +1,532 @@ +// 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. + +#ifndef GOOGLE_PROTOBUF_INLINED_STRING_FIELD_H__ +#define GOOGLE_PROTOBUF_INLINED_STRING_FIELD_H__ + +#include <string> +#include <utility> + +#include <google/protobuf/stubs/logging.h> +#include <google/protobuf/stubs/common.h> +#include <google/protobuf/port.h> +#include <google/protobuf/stubs/strutil.h> +#include <google/protobuf/arenastring.h> +#include <google/protobuf/message_lite.h> + +// Must be included last. +#include <google/protobuf/port_def.inc> + +#ifdef SWIG +#error "You cannot SWIG proto headers" +#endif + +namespace google { +namespace protobuf { + +class Arena; + +namespace internal { + +// InlinedStringField wraps a std::string instance and exposes an API similar to +// ArenaStringPtr's wrapping of a std::string* instance. +// +// default_value parameters are taken for consistency with ArenaStringPtr, but +// are not used for most methods. With inlining, these should be removed from +// the generated binary. +// +// InlinedStringField has a donating mechanism that allows string buffer +// allocated on arena. A string is donated means both the string container and +// the data buffer are on arena. The donating mechanism here is similar to the +// one in ArenaStringPtr with some differences: +// +// When an InlinedStringField is constructed, the donating state is true. This +// is because the string container is directly stored in the message on the +// arena: +// +// Construction: donated=true +// Arena: +// +-----------------------+ +// |Message foo: | +// | +-------------------+ | +// | |InlinedStringField:| | +// | | +-----+ | | +// | | | | | | | | +// | | +-----+ | | +// | +-------------------+ | +// +-----------------------+ +// +// When lvalue Set is called, the donating state is still true. String data will +// be allocated on the arena: +// +// Lvalue Set: donated=true +// Arena: +// +-----------------------+ +// |Message foo: | +// | +-------------------+ | +// | |InlinedStringField:| | +// | | +-----+ | | +// | | | | | | | | +// | | +|----+ | | +// | +--|----------------+ | +// | V | +// | +----------------+ | +// | |'f','o','o',... | | +// | +----------------+ | +// +-----------------------+ +// +// Some operations will undonate a donated string, including: Mutable, +// SetAllocated, Rvalue Set, and Swap with a non-donated string. +// +// For more details of the donating states transitions, go/pd-inlined-string. +class PROTOBUF_EXPORT InlinedStringField { + public: + InlinedStringField() { Init(); } + inline void Init() { new (get_mutable()) std::string(); } + // Add the dummy parameter just to make InlinedStringField(nullptr) + // unambiguous. + constexpr InlinedStringField( + const ExplicitlyConstructed<std::string>* /*default_value*/, + bool /*dummy*/) + : value_{} {} + explicit InlinedStringField(const std::string& default_value); + explicit InlinedStringField(Arena* arena); + ~InlinedStringField() { Destruct(); } + + // Lvalue Set. To save space, we pack the donating states of multiple + // InlinedStringFields into an uint32_t `donating_states`. The `mask` + // indicates the position of the bit for this InlinedStringField. `donated` is + // whether this field is donated. + // + // The caller should guarantee that: + // + // `donated == ((donating_states & ~mask) != 0)` + // + // This method never changes the `donating_states`. + void Set(ConstStringParam value, Arena* arena, bool donated, + uint32_t* donating_states, uint32_t mask, MessageLite* msg); + + // Rvalue Set. If this field is donated, this method will undonate this field + // by mutating the `donating_states` according to `mask`. + void Set(std::string&& value, Arena* arena, bool donated, + uint32_t* donating_states, uint32_t mask, MessageLite* msg); + + void Set(const char* str, ::google::protobuf::Arena* arena, bool donated, + uint32_t* donating_states, uint32_t mask, MessageLite* msg); + + void Set(const char* str, size_t size, ::google::protobuf::Arena* arena, bool donated, + uint32_t* donating_states, uint32_t mask, MessageLite* msg); + + template <typename RefWrappedType> + void Set(std::reference_wrapper<RefWrappedType> const_string_ref, + ::google::protobuf::Arena* arena, bool donated, uint32_t* donating_states, + uint32_t mask, MessageLite* msg); + + void SetBytes(ConstStringParam value, Arena* arena, bool donated, + uint32_t* donating_states, uint32_t mask, MessageLite* msg); + + void SetBytes(std::string&& value, Arena* arena, bool donated, + uint32_t* donating_states, uint32_t mask, MessageLite* msg); + + void SetBytes(const char* str, ::google::protobuf::Arena* arena, bool donated, + uint32_t* donating_states, uint32_t mask, MessageLite* msg); + + void SetBytes(const void* p, size_t size, ::google::protobuf::Arena* arena, + bool donated, uint32_t* donating_states, uint32_t mask, + MessageLite* msg); + + template <typename RefWrappedType> + void SetBytes(std::reference_wrapper<RefWrappedType> const_string_ref, + ::google::protobuf::Arena* arena, bool donated, uint32_t* donating_states, + uint32_t mask, MessageLite* msg); + + PROTOBUF_NDEBUG_INLINE void SetNoArena(StringPiece value); + PROTOBUF_NDEBUG_INLINE void SetNoArena(std::string&& value); + + // Basic accessors. + PROTOBUF_NDEBUG_INLINE const std::string& Get() const { return GetNoArena(); } + PROTOBUF_NDEBUG_INLINE const std::string& GetNoArena() const; + + // Mutable returns a std::string* instance that is heap-allocated. If this + // field is donated, this method undonates this field by mutating the + // `donating_states` according to `mask`, and copies the content of the + // original string to the returning string. + std::string* Mutable(Arena* arena, bool donated, uint32_t* donating_states, + uint32_t mask, MessageLite* msg); + std::string* Mutable(const LazyString& default_value, Arena* arena, + bool donated, uint32_t* donating_states, uint32_t mask, + MessageLite* msg); + + // Mutable(nullptr_t) is an overload to explicitly support Mutable(nullptr) + // calls used by the internal parser logic. This provides API equivalence with + // ArenaStringPtr, while still protecting against calls with arena pointers. + std::string* Mutable(std::nullptr_t); + std::string* MutableNoCopy(std::nullptr_t); + + // Takes a std::string that is heap-allocated, and takes ownership. The + // std::string's destructor is registered with the arena. Used to implement + // set_allocated_<field> in generated classes. + // + // If this field is donated, this method undonates this field by mutating the + // `donating_states` according to `mask`. + void SetAllocated(const std::string* default_value, std::string* value, + Arena* arena, bool donated, uint32_t* donating_states, + uint32_t mask, MessageLite* msg); + + void SetAllocatedNoArena(const std::string* default_value, + std::string* value); + + // Release returns a std::string* instance that is heap-allocated and is not + // Own()'d by any arena. If the field is not set, this returns nullptr. The + // caller retains ownership. Clears this field back to nullptr state. Used to + // implement release_<field>() methods on generated classes. + PROTOBUF_NODISCARD std::string* Release(Arena* arena, bool donated); + PROTOBUF_NODISCARD std::string* Release(); + + // -------------------------------------------------------- + // Below functions will be removed in subsequent code change + // -------------------------------------------------------- +#ifdef DEPRECATED_METHODS_TO_BE_DELETED + PROTOBUF_NODISCARD std::string* Release(const std::string*, Arena* arena, + bool donated) { + return Release(arena, donated); + } + + PROTOBUF_NODISCARD std::string* ReleaseNonDefault(const std::string*, + Arena* arena) { + return Release(); + } + + std::string* ReleaseNonDefaultNoArena(const std::string* default_value) { + return Release(); + } + + void Set(const std::string*, ConstStringParam value, Arena* arena, + bool donated, uint32_t* donating_states, uint32_t mask, + MessageLite* msg) { + Set(value, arena, donated, donating_states, mask, msg); + } + + void Set(const std::string*, std::string&& value, Arena* arena, bool donated, + uint32_t* donating_states, uint32_t mask, MessageLite* msg) { + Set(std::move(value), arena, donated, donating_states, mask, msg); + } + + + template <typename FirstParam> + void Set(FirstParam, const char* str, ::google::protobuf::Arena* arena, bool donated, + uint32_t* donating_states, uint32_t mask, MessageLite* msg) { + Set(str, arena, donated, donating_states, mask, msg); + } + + template <typename FirstParam> + void Set(FirstParam p1, const char* str, size_t size, ::google::protobuf::Arena* arena, + bool donated, uint32_t* donating_states, uint32_t mask, + MessageLite* msg) { + Set(str, size, arena, donated, donating_states, mask, msg); + } + + template <typename FirstParam, typename RefWrappedType> + void Set(FirstParam p1, + std::reference_wrapper<RefWrappedType> const_string_ref, + ::google::protobuf::Arena* arena, bool donated, uint32_t* donating_states, + uint32_t mask, MessageLite* msg) { + Set(const_string_ref, arena, donated, donating_states, mask, msg); + } + + void SetBytes(const std::string*, ConstStringParam value, Arena* arena, + bool donated, uint32_t* donating_states, uint32_t mask, + MessageLite* msg) { + Set(value, arena, donated, donating_states, mask, msg); + } + + + void SetBytes(const std::string*, std::string&& value, Arena* arena, + bool donated, uint32_t* donating_states, uint32_t mask, + MessageLite* msg) { + Set(std::move(value), arena, donated, donating_states, mask, msg); + } + + template <typename FirstParam> + void SetBytes(FirstParam p1, const char* str, ::google::protobuf::Arena* arena, + bool donated, uint32_t* donating_states, uint32_t mask, + MessageLite* msg) { + SetBytes(str, arena, donated, donating_states, mask, msg); + } + + template <typename FirstParam> + void SetBytes(FirstParam p1, const void* p, size_t size, + ::google::protobuf::Arena* arena, bool donated, uint32_t* donating_states, + uint32_t mask, MessageLite* msg) { + SetBytes(p, size, arena, donated, donating_states, mask, msg); + } + + template <typename FirstParam, typename RefWrappedType> + void SetBytes(FirstParam p1, + std::reference_wrapper<RefWrappedType> const_string_ref, + ::google::protobuf::Arena* arena, bool donated, uint32_t* donating_states, + uint32_t mask, MessageLite* msg) { + SetBytes(const_string_ref.get(), arena, donated, donating_states, mask, + msg); + } + + void SetNoArena(const std::string*, StringPiece value) { + SetNoArena(value); + } + void SetNoArena(const std::string*, std::string&& value) { + SetNoArena(std::move(value)); + } + + std::string* Mutable(ArenaStringPtr::EmptyDefault, Arena* arena, bool donated, + uint32_t* donating_states, uint32_t mask, + MessageLite* msg) { + return Mutable(arena, donated, donating_states, mask, msg); + } + + PROTOBUF_NDEBUG_INLINE std::string* MutableNoArenaNoDefault( + const std::string* /*default_value*/) { + return MutableNoCopy(nullptr); + } + +#endif // DEPRECATED_METHODS_TO_BE_DELETED + + // Arena-safety semantics: this is guarded by the logic in + // Swap()/UnsafeArenaSwap() at the message level, so this method is + // 'unsafe' if called directly. + inline PROTOBUF_NDEBUG_INLINE static void InternalSwap( + InlinedStringField* lhs, Arena* lhs_arena, bool lhs_arena_dtor_registered, + MessageLite* lhs_msg, // + InlinedStringField* rhs, Arena* rhs_arena, bool rhs_arena_dtor_registered, + MessageLite* rhs_msg); + + // Frees storage (if not on an arena). + PROTOBUF_NDEBUG_INLINE void Destroy(const std::string* default_value, + Arena* arena) { + if (arena == nullptr) { + DestroyNoArena(default_value); + } + } + PROTOBUF_NDEBUG_INLINE void DestroyNoArena(const std::string* default_value); + + // Clears content, but keeps allocated std::string, to avoid the overhead of + // heap operations. After this returns, the content (as seen by the user) will + // always be the empty std::string. + PROTOBUF_NDEBUG_INLINE void ClearToEmpty() { ClearNonDefaultToEmpty(); } + PROTOBUF_NDEBUG_INLINE void ClearNonDefaultToEmpty() { + get_mutable()->clear(); + } + + // Clears content, but keeps allocated std::string if arena != nullptr, to + // avoid the overhead of heap operations. After this returns, the content (as + // seen by the user) will always be equal to |default_value|. + void ClearToDefault(const LazyString& default_value, Arena* arena, + bool donated); + + // Generated code / reflection only! Returns a mutable pointer to the string. + PROTOBUF_NDEBUG_INLINE std::string* UnsafeMutablePointer(); + + // InlinedStringField doesn't have things like the `default_value` pointer in + // ArenaStringPtr. + static constexpr bool IsDefault() { return false; } + static constexpr bool IsDefault(const std::string*) { return false; } + + private: + void Destruct() { get_mutable()->~basic_string(); } + + PROTOBUF_NDEBUG_INLINE std::string* get_mutable(); + PROTOBUF_NDEBUG_INLINE const std::string* get_const() const; + + alignas(std::string) char value_[sizeof(std::string)]; + + std::string* MutableSlow(::google::protobuf::Arena* arena, bool donated, + uint32_t* donating_states, uint32_t mask, + MessageLite* msg); + + + // When constructed in an Arena, we want our destructor to be skipped. + friend class ::google::protobuf::Arena; + typedef void InternalArenaConstructable_; + typedef void DestructorSkippable_; +}; + +inline std::string* InlinedStringField::get_mutable() { + return reinterpret_cast<std::string*>(&value_); +} + +inline const std::string* InlinedStringField::get_const() const { + return reinterpret_cast<const std::string*>(&value_); +} + +inline InlinedStringField::InlinedStringField( + const std::string& default_value) { + new (get_mutable()) std::string(default_value); +} + + +inline InlinedStringField::InlinedStringField(Arena* /*arena*/) { Init(); } + +inline const std::string& InlinedStringField::GetNoArena() const { + return *get_const(); +} + +inline void InlinedStringField::SetAllocatedNoArena( + const std::string* /*default_value*/, std::string* value) { + if (value == nullptr) { + // Currently, inlined string field can't have non empty default. + get_mutable()->clear(); + } else { + get_mutable()->assign(std::move(*value)); + delete value; + } +} + +inline void InlinedStringField::DestroyNoArena(const std::string*) { + // This is invoked from the generated message's ArenaDtor, which is used to + // clean up objects not allocated on the Arena. + this->~InlinedStringField(); +} + +inline void InlinedStringField::SetNoArena(StringPiece value) { + get_mutable()->assign(value.data(), value.length()); +} + +inline void InlinedStringField::SetNoArena(std::string&& value) { + get_mutable()->assign(std::move(value)); +} + +// Caller should make sure rhs_arena allocated rhs, and lhs_arena allocated lhs. +inline PROTOBUF_NDEBUG_INLINE void InlinedStringField::InternalSwap( + InlinedStringField* lhs, Arena* lhs_arena, bool lhs_arena_dtor_registered, + MessageLite* lhs_msg, // + InlinedStringField* rhs, Arena* rhs_arena, bool rhs_arena_dtor_registered, + MessageLite* rhs_msg) { +#if GOOGLE_PROTOBUF_INTERNAL_DONATE_STEAL_INLINE + lhs->get_mutable()->swap(*rhs->get_mutable()); + if (!lhs_arena_dtor_registered && rhs_arena_dtor_registered) { + lhs_msg->OnDemandRegisterArenaDtor(lhs_arena); + } else if (lhs_arena_dtor_registered && !rhs_arena_dtor_registered) { + rhs_msg->OnDemandRegisterArenaDtor(rhs_arena); + } +#else + (void)lhs_arena; + (void)rhs_arena; + (void)lhs_arena_dtor_registered; + (void)rhs_arena_dtor_registered; + (void)lhs_msg; + (void)rhs_msg; + lhs->get_mutable()->swap(*rhs->get_mutable()); +#endif +} + +inline void InlinedStringField::Set(ConstStringParam value, Arena* arena, + bool donated, uint32_t* /*donating_states*/, + uint32_t /*mask*/, MessageLite* /*msg*/) { + (void)arena; + (void)donated; + SetNoArena(value); +} + +inline void InlinedStringField::Set(const char* str, ::google::protobuf::Arena* arena, + bool donated, uint32_t* donating_states, + uint32_t mask, MessageLite* msg) { + Set(ConstStringParam(str), arena, donated, donating_states, mask, msg); +} + +inline void InlinedStringField::Set(const char* str, size_t size, + ::google::protobuf::Arena* arena, bool donated, + uint32_t* donating_states, uint32_t mask, + MessageLite* msg) { + Set(ConstStringParam{str, size}, arena, donated, donating_states, mask, msg); +} + +inline void InlinedStringField::SetBytes(ConstStringParam value, Arena* arena, + bool donated, + uint32_t* donating_states, + uint32_t mask, MessageLite* msg) { + Set(value, arena, donated, donating_states, mask, msg); +} + +inline void InlinedStringField::SetBytes(std::string&& value, Arena* arena, + bool donated, + uint32_t* donating_states, + uint32_t mask, MessageLite* msg) { + Set(std::move(value), arena, donated, donating_states, mask, msg); +} + +inline void InlinedStringField::SetBytes(const char* str, + ::google::protobuf::Arena* arena, bool donated, + uint32_t* donating_states, + uint32_t mask, MessageLite* msg) { + Set(str, arena, donated, donating_states, mask, msg); +} + +inline void InlinedStringField::SetBytes(const void* p, size_t size, + ::google::protobuf::Arena* arena, bool donated, + uint32_t* donating_states, + uint32_t mask, MessageLite* msg) { + Set(static_cast<const char*>(p), size, arena, donated, donating_states, mask, + msg); +} + +template <typename RefWrappedType> +inline void InlinedStringField::Set( + std::reference_wrapper<RefWrappedType> const_string_ref, + ::google::protobuf::Arena* arena, bool donated, uint32_t* donating_states, + uint32_t mask, MessageLite* msg) { + Set(const_string_ref.get(), arena, donated, donating_states, mask, msg); +} + +template <typename RefWrappedType> +inline void InlinedStringField::SetBytes( + std::reference_wrapper<RefWrappedType> const_string_ref, + ::google::protobuf::Arena* arena, bool donated, uint32_t* donating_states, + uint32_t mask, MessageLite* msg) { + Set(const_string_ref.get(), arena, donated, donating_states, mask, msg); +} + +inline std::string* InlinedStringField::UnsafeMutablePointer() { + return get_mutable(); +} + +inline std::string* InlinedStringField::Mutable(std::nullptr_t) { + return get_mutable(); +} + +inline std::string* InlinedStringField::MutableNoCopy(std::nullptr_t) { + return get_mutable(); +} + +} // namespace internal +} // namespace protobuf +} // namespace google + +#include <google/protobuf/port_undef.inc> + +#endif // GOOGLE_PROTOBUF_INLINED_STRING_FIELD_H__ diff --git a/toolkit/components/protobuf/src/google/protobuf/io/coded_stream.cc b/toolkit/components/protobuf/src/google/protobuf/io/coded_stream.cc new file mode 100644 index 0000000000..487e1b8a37 --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/io/coded_stream.cc @@ -0,0 +1,967 @@ +// 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. + +// Author: kenton@google.com (Kenton Varda) +// Based on original Protocol Buffers design by +// Sanjay Ghemawat, Jeff Dean, and others. +// +// This implementation is heavily optimized to make reads and writes +// of small values (especially varints) as fast as possible. In +// particular, we optimize for the common case that a read or a write +// will not cross the end of the buffer, since we can avoid a lot +// of branching in this case. + +#include <google/protobuf/io/coded_stream.h> + +#include <limits.h> + +#include <algorithm> +#include <cstring> +#include <utility> + +#include <google/protobuf/stubs/logging.h> +#include <google/protobuf/stubs/common.h> +#include <google/protobuf/arena.h> +#include <google/protobuf/io/zero_copy_stream.h> +#include <google/protobuf/io/zero_copy_stream_impl_lite.h> +#include <google/protobuf/stubs/stl_util.h> + + +// Must be included last. +#include <google/protobuf/port_def.inc> + +namespace google { +namespace protobuf { +namespace io { + +namespace { + +static const int kMaxVarintBytes = 10; +static const int kMaxVarint32Bytes = 5; + + +inline bool NextNonEmpty(ZeroCopyInputStream* input, const void** data, + int* size) { + bool success; + do { + success = input->Next(data, size); + } while (success && *size == 0); + return success; +} + +} // namespace + +// CodedInputStream ================================================== + +CodedInputStream::~CodedInputStream() { + if (input_ != NULL) { + BackUpInputToCurrentPosition(); + } +} + +// Static. +int CodedInputStream::default_recursion_limit_ = 100; + + +void CodedInputStream::BackUpInputToCurrentPosition() { + int backup_bytes = BufferSize() + buffer_size_after_limit_ + overflow_bytes_; + if (backup_bytes > 0) { + input_->BackUp(backup_bytes); + + // total_bytes_read_ doesn't include overflow_bytes_. + total_bytes_read_ -= BufferSize() + buffer_size_after_limit_; + buffer_end_ = buffer_; + buffer_size_after_limit_ = 0; + overflow_bytes_ = 0; + } +} + +inline void CodedInputStream::RecomputeBufferLimits() { + buffer_end_ += buffer_size_after_limit_; + int closest_limit = std::min(current_limit_, total_bytes_limit_); + if (closest_limit < total_bytes_read_) { + // The limit position is in the current buffer. We must adjust + // the buffer size accordingly. + buffer_size_after_limit_ = total_bytes_read_ - closest_limit; + buffer_end_ -= buffer_size_after_limit_; + } else { + buffer_size_after_limit_ = 0; + } +} + +CodedInputStream::Limit CodedInputStream::PushLimit(int byte_limit) { + // Current position relative to the beginning of the stream. + int current_position = CurrentPosition(); + + Limit old_limit = current_limit_; + + // security: byte_limit is possibly evil, so check for negative values + // and overflow. Also check that the new requested limit is before the + // previous limit; otherwise we continue to enforce the previous limit. + if (PROTOBUF_PREDICT_TRUE(byte_limit >= 0 && + byte_limit <= INT_MAX - current_position && + byte_limit < current_limit_ - current_position)) { + current_limit_ = current_position + byte_limit; + RecomputeBufferLimits(); + } + + return old_limit; +} + +void CodedInputStream::PopLimit(Limit limit) { + // The limit passed in is actually the *old* limit, which we returned from + // PushLimit(). + current_limit_ = limit; + RecomputeBufferLimits(); + + // We may no longer be at a legitimate message end. ReadTag() needs to be + // called again to find out. + legitimate_message_end_ = false; +} + +std::pair<CodedInputStream::Limit, int> +CodedInputStream::IncrementRecursionDepthAndPushLimit(int byte_limit) { + return std::make_pair(PushLimit(byte_limit), --recursion_budget_); +} + +CodedInputStream::Limit CodedInputStream::ReadLengthAndPushLimit() { + uint32_t length; + return PushLimit(ReadVarint32(&length) ? length : 0); +} + +bool CodedInputStream::DecrementRecursionDepthAndPopLimit(Limit limit) { + bool result = ConsumedEntireMessage(); + PopLimit(limit); + GOOGLE_DCHECK_LT(recursion_budget_, recursion_limit_); + ++recursion_budget_; + return result; +} + +bool CodedInputStream::CheckEntireMessageConsumedAndPopLimit(Limit limit) { + bool result = ConsumedEntireMessage(); + PopLimit(limit); + return result; +} + +int CodedInputStream::BytesUntilLimit() const { + if (current_limit_ == INT_MAX) return -1; + int current_position = CurrentPosition(); + + return current_limit_ - current_position; +} + +void CodedInputStream::SetTotalBytesLimit(int total_bytes_limit) { + // Make sure the limit isn't already past, since this could confuse other + // code. + int current_position = CurrentPosition(); + total_bytes_limit_ = std::max(current_position, total_bytes_limit); + RecomputeBufferLimits(); +} + +int CodedInputStream::BytesUntilTotalBytesLimit() const { + if (total_bytes_limit_ == INT_MAX) return -1; + return total_bytes_limit_ - CurrentPosition(); +} + +void CodedInputStream::PrintTotalBytesLimitError() { + GOOGLE_LOG(ERROR) + << "A protocol message was rejected because it was too " + "big (more than " + << total_bytes_limit_ + << " bytes). To increase the limit (or to disable these " + "warnings), see CodedInputStream::SetTotalBytesLimit() " + "in third_party/protobuf/io/coded_stream.h."; +} + +bool CodedInputStream::SkipFallback(int count, int original_buffer_size) { + if (buffer_size_after_limit_ > 0) { + // We hit a limit inside this buffer. Advance to the limit and fail. + Advance(original_buffer_size); + return false; + } + + count -= original_buffer_size; + buffer_ = NULL; + buffer_end_ = buffer_; + + // Make sure this skip doesn't try to skip past the current limit. + int closest_limit = std::min(current_limit_, total_bytes_limit_); + int bytes_until_limit = closest_limit - total_bytes_read_; + if (bytes_until_limit < count) { + // We hit the limit. Skip up to it then fail. + if (bytes_until_limit > 0) { + total_bytes_read_ = closest_limit; + input_->Skip(bytes_until_limit); + } + return false; + } + + if (!input_->Skip(count)) { + total_bytes_read_ = input_->ByteCount(); + return false; + } + total_bytes_read_ += count; + return true; +} + +bool CodedInputStream::GetDirectBufferPointer(const void** data, int* size) { + if (BufferSize() == 0 && !Refresh()) return false; + + *data = buffer_; + *size = BufferSize(); + return true; +} + +bool CodedInputStream::ReadRaw(void* buffer, int size) { + int current_buffer_size; + while ((current_buffer_size = BufferSize()) < size) { + // Reading past end of buffer. Copy what we have, then refresh. + memcpy(buffer, buffer_, current_buffer_size); + buffer = reinterpret_cast<uint8_t*>(buffer) + current_buffer_size; + size -= current_buffer_size; + Advance(current_buffer_size); + if (!Refresh()) return false; + } + + memcpy(buffer, buffer_, size); + Advance(size); + + return true; +} + +bool CodedInputStream::ReadString(std::string* buffer, int size) { + if (size < 0) return false; // security: size is often user-supplied + + if (BufferSize() >= size) { + STLStringResizeUninitialized(buffer, size); + std::pair<char*, bool> z = as_string_data(buffer); + if (z.second) { + // Oddly enough, memcpy() requires its first two args to be non-NULL even + // if we copy 0 bytes. So, we have ensured that z.first is non-NULL here. + GOOGLE_DCHECK(z.first != NULL); + memcpy(z.first, buffer_, size); + Advance(size); + } + return true; + } + + return ReadStringFallback(buffer, size); +} + +bool CodedInputStream::ReadStringFallback(std::string* buffer, int size) { + if (!buffer->empty()) { + buffer->clear(); + } + + int closest_limit = std::min(current_limit_, total_bytes_limit_); + if (closest_limit != INT_MAX) { + int bytes_to_limit = closest_limit - CurrentPosition(); + if (bytes_to_limit > 0 && size > 0 && size <= bytes_to_limit) { + buffer->reserve(size); + } + } + + int current_buffer_size; + while ((current_buffer_size = BufferSize()) < size) { + // Some STL implementations "helpfully" crash on buffer->append(NULL, 0). + if (current_buffer_size != 0) { + // Note: string1.append(string2) is O(string2.size()) (as opposed to + // O(string1.size() + string2.size()), which would be bad). + buffer->append(reinterpret_cast<const char*>(buffer_), + current_buffer_size); + } + size -= current_buffer_size; + Advance(current_buffer_size); + if (!Refresh()) return false; + } + + buffer->append(reinterpret_cast<const char*>(buffer_), size); + Advance(size); + + return true; +} + + +bool CodedInputStream::ReadLittleEndian32Fallback(uint32_t* value) { + uint8_t bytes[sizeof(*value)]; + + const uint8_t* ptr; + if (BufferSize() >= static_cast<int64_t>(sizeof(*value))) { + // Fast path: Enough bytes in the buffer to read directly. + ptr = buffer_; + Advance(sizeof(*value)); + } else { + // Slow path: Had to read past the end of the buffer. + if (!ReadRaw(bytes, sizeof(*value))) return false; + ptr = bytes; + } + ReadLittleEndian32FromArray(ptr, value); + return true; +} + +bool CodedInputStream::ReadLittleEndian64Fallback(uint64_t* value) { + uint8_t bytes[sizeof(*value)]; + + const uint8_t* ptr; + if (BufferSize() >= static_cast<int64_t>(sizeof(*value))) { + // Fast path: Enough bytes in the buffer to read directly. + ptr = buffer_; + Advance(sizeof(*value)); + } else { + // Slow path: Had to read past the end of the buffer. + if (!ReadRaw(bytes, sizeof(*value))) return false; + ptr = bytes; + } + ReadLittleEndian64FromArray(ptr, value); + return true; +} + +namespace { + +// Decodes varint64 with known size, N, and returns next pointer. Knowing N at +// compile time, compiler can generate optimal code. For example, instead of +// subtracting 0x80 at each iteration, it subtracts properly shifted mask once. +template <size_t N> +const uint8_t* DecodeVarint64KnownSize(const uint8_t* buffer, uint64_t* value) { + GOOGLE_DCHECK_GT(N, 0); + uint64_t result = static_cast<uint64_t>(buffer[N - 1]) << (7 * (N - 1)); + for (size_t i = 0, offset = 0; i < N - 1; i++, offset += 7) { + result += static_cast<uint64_t>(buffer[i] - 0x80) << offset; + } + *value = result; + return buffer + N; +} + +// Read a varint from the given buffer, write it to *value, and return a pair. +// The first part of the pair is true iff the read was successful. The second +// part is buffer + (number of bytes read). This function is always inlined, +// so returning a pair is costless. +PROTOBUF_ALWAYS_INLINE +::std::pair<bool, const uint8_t*> ReadVarint32FromArray(uint32_t first_byte, + const uint8_t* buffer, + uint32_t* value); +inline ::std::pair<bool, const uint8_t*> ReadVarint32FromArray( + uint32_t first_byte, const uint8_t* buffer, uint32_t* value) { + // Fast path: We have enough bytes left in the buffer to guarantee that + // this read won't cross the end, so we can skip the checks. + GOOGLE_DCHECK_EQ(*buffer, first_byte); + GOOGLE_DCHECK_EQ(first_byte & 0x80, 0x80) << first_byte; + const uint8_t* ptr = buffer; + uint32_t b; + uint32_t result = first_byte - 0x80; + ++ptr; // We just processed the first byte. Move on to the second. + b = *(ptr++); + result += b << 7; + if (!(b & 0x80)) goto done; + result -= 0x80 << 7; + b = *(ptr++); + result += b << 14; + if (!(b & 0x80)) goto done; + result -= 0x80 << 14; + b = *(ptr++); + result += b << 21; + if (!(b & 0x80)) goto done; + result -= 0x80 << 21; + b = *(ptr++); + result += b << 28; + if (!(b & 0x80)) goto done; + // "result -= 0x80 << 28" is irrelevant. + + // If the input is larger than 32 bits, we still need to read it all + // and discard the high-order bits. + for (int i = 0; i < kMaxVarintBytes - kMaxVarint32Bytes; i++) { + b = *(ptr++); + if (!(b & 0x80)) goto done; + } + + // We have overrun the maximum size of a varint (10 bytes). Assume + // the data is corrupt. + return std::make_pair(false, ptr); + +done: + *value = result; + return std::make_pair(true, ptr); +} + +PROTOBUF_ALWAYS_INLINE::std::pair<bool, const uint8_t*> ReadVarint64FromArray( + const uint8_t* buffer, uint64_t* value); +inline ::std::pair<bool, const uint8_t*> ReadVarint64FromArray( + const uint8_t* buffer, uint64_t* value) { + // Assumes varint64 is at least 2 bytes. + GOOGLE_DCHECK_GE(buffer[0], 128); + + const uint8_t* next; + if (buffer[1] < 128) { + next = DecodeVarint64KnownSize<2>(buffer, value); + } else if (buffer[2] < 128) { + next = DecodeVarint64KnownSize<3>(buffer, value); + } else if (buffer[3] < 128) { + next = DecodeVarint64KnownSize<4>(buffer, value); + } else if (buffer[4] < 128) { + next = DecodeVarint64KnownSize<5>(buffer, value); + } else if (buffer[5] < 128) { + next = DecodeVarint64KnownSize<6>(buffer, value); + } else if (buffer[6] < 128) { + next = DecodeVarint64KnownSize<7>(buffer, value); + } else if (buffer[7] < 128) { + next = DecodeVarint64KnownSize<8>(buffer, value); + } else if (buffer[8] < 128) { + next = DecodeVarint64KnownSize<9>(buffer, value); + } else if (buffer[9] < 128) { + next = DecodeVarint64KnownSize<10>(buffer, value); + } else { + // We have overrun the maximum size of a varint (10 bytes). Assume + // the data is corrupt. + return std::make_pair(false, buffer + 11); + } + + return std::make_pair(true, next); +} + +} // namespace + +bool CodedInputStream::ReadVarint32Slow(uint32_t* value) { + // Directly invoke ReadVarint64Fallback, since we already tried to optimize + // for one-byte varints. + std::pair<uint64_t, bool> p = ReadVarint64Fallback(); + *value = static_cast<uint32_t>(p.first); + return p.second; +} + +int64_t CodedInputStream::ReadVarint32Fallback(uint32_t first_byte_or_zero) { + if (BufferSize() >= kMaxVarintBytes || + // Optimization: We're also safe if the buffer is non-empty and it ends + // with a byte that would terminate a varint. + (buffer_end_ > buffer_ && !(buffer_end_[-1] & 0x80))) { + GOOGLE_DCHECK_NE(first_byte_or_zero, 0) + << "Caller should provide us with *buffer_ when buffer is non-empty"; + uint32_t temp; + ::std::pair<bool, const uint8_t*> p = + ReadVarint32FromArray(first_byte_or_zero, buffer_, &temp); + if (!p.first) return -1; + buffer_ = p.second; + return temp; + } else { + // Really slow case: we will incur the cost of an extra function call here, + // but moving this out of line reduces the size of this function, which + // improves the common case. In micro benchmarks, this is worth about 10-15% + uint32_t temp; + return ReadVarint32Slow(&temp) ? static_cast<int64_t>(temp) : -1; + } +} + +int CodedInputStream::ReadVarintSizeAsIntSlow() { + // Directly invoke ReadVarint64Fallback, since we already tried to optimize + // for one-byte varints. + std::pair<uint64_t, bool> p = ReadVarint64Fallback(); + if (!p.second || p.first > static_cast<uint64_t>(INT_MAX)) return -1; + return p.first; +} + +int CodedInputStream::ReadVarintSizeAsIntFallback() { + if (BufferSize() >= kMaxVarintBytes || + // Optimization: We're also safe if the buffer is non-empty and it ends + // with a byte that would terminate a varint. + (buffer_end_ > buffer_ && !(buffer_end_[-1] & 0x80))) { + uint64_t temp; + ::std::pair<bool, const uint8_t*> p = ReadVarint64FromArray(buffer_, &temp); + if (!p.first || temp > static_cast<uint64_t>(INT_MAX)) return -1; + buffer_ = p.second; + return temp; + } else { + // Really slow case: we will incur the cost of an extra function call here, + // but moving this out of line reduces the size of this function, which + // improves the common case. In micro benchmarks, this is worth about 10-15% + return ReadVarintSizeAsIntSlow(); + } +} + +uint32_t CodedInputStream::ReadTagSlow() { + if (buffer_ == buffer_end_) { + // Call refresh. + if (!Refresh()) { + // Refresh failed. Make sure that it failed due to EOF, not because + // we hit total_bytes_limit_, which, unlike normal limits, is not a + // valid place to end a message. + int current_position = total_bytes_read_ - buffer_size_after_limit_; + if (current_position >= total_bytes_limit_) { + // Hit total_bytes_limit_. But if we also hit the normal limit, + // we're still OK. + legitimate_message_end_ = current_limit_ == total_bytes_limit_; + } else { + legitimate_message_end_ = true; + } + return 0; + } + } + + // For the slow path, just do a 64-bit read. Try to optimize for one-byte tags + // again, since we have now refreshed the buffer. + uint64_t result = 0; + if (!ReadVarint64(&result)) return 0; + return static_cast<uint32_t>(result); +} + +uint32_t CodedInputStream::ReadTagFallback(uint32_t first_byte_or_zero) { + const int buf_size = BufferSize(); + if (buf_size >= kMaxVarintBytes || + // Optimization: We're also safe if the buffer is non-empty and it ends + // with a byte that would terminate a varint. + (buf_size > 0 && !(buffer_end_[-1] & 0x80))) { + GOOGLE_DCHECK_EQ(first_byte_or_zero, buffer_[0]); + if (first_byte_or_zero == 0) { + ++buffer_; + return 0; + } + uint32_t tag; + ::std::pair<bool, const uint8_t*> p = + ReadVarint32FromArray(first_byte_or_zero, buffer_, &tag); + if (!p.first) { + return 0; + } + buffer_ = p.second; + return tag; + } else { + // We are commonly at a limit when attempting to read tags. Try to quickly + // detect this case without making another function call. + if ((buf_size == 0) && + ((buffer_size_after_limit_ > 0) || + (total_bytes_read_ == current_limit_)) && + // Make sure that the limit we hit is not total_bytes_limit_, since + // in that case we still need to call Refresh() so that it prints an + // error. + total_bytes_read_ - buffer_size_after_limit_ < total_bytes_limit_) { + // We hit a byte limit. + legitimate_message_end_ = true; + return 0; + } + return ReadTagSlow(); + } +} + +bool CodedInputStream::ReadVarint64Slow(uint64_t* value) { + // Slow path: This read might cross the end of the buffer, so we + // need to check and refresh the buffer if and when it does. + + uint64_t result = 0; + int count = 0; + uint32_t b; + + do { + if (count == kMaxVarintBytes) { + *value = 0; + return false; + } + while (buffer_ == buffer_end_) { + if (!Refresh()) { + *value = 0; + return false; + } + } + b = *buffer_; + result |= static_cast<uint64_t>(b & 0x7F) << (7 * count); + Advance(1); + ++count; + } while (b & 0x80); + + *value = result; + return true; +} + +std::pair<uint64_t, bool> CodedInputStream::ReadVarint64Fallback() { + if (BufferSize() >= kMaxVarintBytes || + // Optimization: We're also safe if the buffer is non-empty and it ends + // with a byte that would terminate a varint. + (buffer_end_ > buffer_ && !(buffer_end_[-1] & 0x80))) { + uint64_t temp; + ::std::pair<bool, const uint8_t*> p = ReadVarint64FromArray(buffer_, &temp); + if (!p.first) { + return std::make_pair(0, false); + } + buffer_ = p.second; + return std::make_pair(temp, true); + } else { + uint64_t temp; + bool success = ReadVarint64Slow(&temp); + return std::make_pair(temp, success); + } +} + +bool CodedInputStream::Refresh() { + GOOGLE_DCHECK_EQ(0, BufferSize()); + + if (buffer_size_after_limit_ > 0 || overflow_bytes_ > 0 || + total_bytes_read_ == current_limit_) { + // We've hit a limit. Stop. + int current_position = total_bytes_read_ - buffer_size_after_limit_; + + if (current_position >= total_bytes_limit_ && + total_bytes_limit_ != current_limit_) { + // Hit total_bytes_limit_. + PrintTotalBytesLimitError(); + } + + return false; + } + + const void* void_buffer; + int buffer_size; + if (NextNonEmpty(input_, &void_buffer, &buffer_size)) { + buffer_ = reinterpret_cast<const uint8_t*>(void_buffer); + buffer_end_ = buffer_ + buffer_size; + GOOGLE_CHECK_GE(buffer_size, 0); + + if (total_bytes_read_ <= INT_MAX - buffer_size) { + total_bytes_read_ += buffer_size; + } else { + // Overflow. Reset buffer_end_ to not include the bytes beyond INT_MAX. + // We can't get that far anyway, because total_bytes_limit_ is guaranteed + // to be less than it. We need to keep track of the number of bytes + // we discarded, though, so that we can call input_->BackUp() to back + // up over them on destruction. + + // The following line is equivalent to: + // overflow_bytes_ = total_bytes_read_ + buffer_size - INT_MAX; + // except that it avoids overflows. Signed integer overflow has + // undefined results according to the C standard. + overflow_bytes_ = total_bytes_read_ - (INT_MAX - buffer_size); + buffer_end_ -= overflow_bytes_; + total_bytes_read_ = INT_MAX; + } + + RecomputeBufferLimits(); + return true; + } else { + buffer_ = NULL; + buffer_end_ = NULL; + return false; + } +} + +// CodedOutputStream ================================================= + +void EpsCopyOutputStream::EnableAliasing(bool enabled) { + aliasing_enabled_ = enabled && stream_->AllowsAliasing(); +} + +int64_t EpsCopyOutputStream::ByteCount(uint8_t* ptr) const { + // Calculate the current offset relative to the end of the stream buffer. + int delta = (end_ - ptr) + (buffer_end_ ? 0 : kSlopBytes); + return stream_->ByteCount() - delta; +} + +// Flushes what's written out to the underlying ZeroCopyOutputStream buffers. +// Returns the size remaining in the buffer and sets buffer_end_ to the start +// of the remaining buffer, ie. [buffer_end_, buffer_end_ + return value) +int EpsCopyOutputStream::Flush(uint8_t* ptr) { + while (buffer_end_ && ptr > end_) { + int overrun = ptr - end_; + GOOGLE_DCHECK(!had_error_); + GOOGLE_DCHECK(overrun <= kSlopBytes); // NOLINT + ptr = Next() + overrun; + if (had_error_) return 0; + } + int s; + if (buffer_end_) { + std::memcpy(buffer_end_, buffer_, ptr - buffer_); + buffer_end_ += ptr - buffer_; + s = end_ - ptr; + } else { + // The stream is writing directly in the ZeroCopyOutputStream buffer. + s = end_ + kSlopBytes - ptr; + buffer_end_ = ptr; + } + GOOGLE_DCHECK(s >= 0); // NOLINT + return s; +} + +uint8_t* EpsCopyOutputStream::Trim(uint8_t* ptr) { + if (had_error_) return ptr; + int s = Flush(ptr); + stream_->BackUp(s); + // Reset to initial state (expecting new buffer) + buffer_end_ = end_ = buffer_; + return buffer_; +} + + +uint8_t* EpsCopyOutputStream::FlushAndResetBuffer(uint8_t* ptr) { + if (had_error_) return buffer_; + int s = Flush(ptr); + if (had_error_) return buffer_; + return SetInitialBuffer(buffer_end_, s); +} + +bool EpsCopyOutputStream::Skip(int count, uint8_t** pp) { + if (count < 0) return false; + if (had_error_) { + *pp = buffer_; + return false; + } + int size = Flush(*pp); + if (had_error_) { + *pp = buffer_; + return false; + } + void* data = buffer_end_; + while (count > size) { + count -= size; + if (!stream_->Next(&data, &size)) { + *pp = Error(); + return false; + } + } + *pp = SetInitialBuffer(static_cast<uint8_t*>(data) + count, size - count); + return true; +} + +bool EpsCopyOutputStream::GetDirectBufferPointer(void** data, int* size, + uint8_t** pp) { + if (had_error_) { + *pp = buffer_; + return false; + } + *size = Flush(*pp); + if (had_error_) { + *pp = buffer_; + return false; + } + *data = buffer_end_; + while (*size == 0) { + if (!stream_->Next(data, size)) { + *pp = Error(); + return false; + } + } + *pp = SetInitialBuffer(*data, *size); + return true; +} + +uint8_t* EpsCopyOutputStream::GetDirectBufferForNBytesAndAdvance(int size, + uint8_t** pp) { + if (had_error_) { + *pp = buffer_; + return nullptr; + } + int s = Flush(*pp); + if (had_error_) { + *pp = buffer_; + return nullptr; + } + if (s >= size) { + auto res = buffer_end_; + *pp = SetInitialBuffer(buffer_end_ + size, s - size); + return res; + } else { + *pp = SetInitialBuffer(buffer_end_, s); + return nullptr; + } +} + +uint8_t* EpsCopyOutputStream::Next() { + GOOGLE_DCHECK(!had_error_); // NOLINT + if (PROTOBUF_PREDICT_FALSE(stream_ == nullptr)) return Error(); + if (buffer_end_) { + // We're in the patch buffer and need to fill up the previous buffer. + std::memcpy(buffer_end_, buffer_, end_ - buffer_); + uint8_t* ptr; + int size; + do { + void* data; + if (PROTOBUF_PREDICT_FALSE(!stream_->Next(&data, &size))) { + // Stream has an error, we use the patch buffer to continue to be + // able to write. + return Error(); + } + ptr = static_cast<uint8_t*>(data); + } while (size == 0); + if (PROTOBUF_PREDICT_TRUE(size > kSlopBytes)) { + std::memcpy(ptr, end_, kSlopBytes); + end_ = ptr + size - kSlopBytes; + buffer_end_ = nullptr; + return ptr; + } else { + GOOGLE_DCHECK(size > 0); // NOLINT + // Buffer to small + std::memmove(buffer_, end_, kSlopBytes); + buffer_end_ = ptr; + end_ = buffer_ + size; + return buffer_; + } + } else { + std::memcpy(buffer_, end_, kSlopBytes); + buffer_end_ = end_; + end_ = buffer_ + kSlopBytes; + return buffer_; + } +} + +uint8_t* EpsCopyOutputStream::EnsureSpaceFallback(uint8_t* ptr) { + do { + if (PROTOBUF_PREDICT_FALSE(had_error_)) return buffer_; + int overrun = ptr - end_; + GOOGLE_DCHECK(overrun >= 0); // NOLINT + GOOGLE_DCHECK(overrun <= kSlopBytes); // NOLINT + ptr = Next() + overrun; + } while (ptr >= end_); + GOOGLE_DCHECK(ptr < end_); // NOLINT + return ptr; +} + +uint8_t* EpsCopyOutputStream::WriteRawFallback(const void* data, int size, + uint8_t* ptr) { + int s = GetSize(ptr); + while (s < size) { + std::memcpy(ptr, data, s); + size -= s; + data = static_cast<const uint8_t*>(data) + s; + ptr = EnsureSpaceFallback(ptr + s); + s = GetSize(ptr); + } + std::memcpy(ptr, data, size); + return ptr + size; +} + +uint8_t* EpsCopyOutputStream::WriteAliasedRaw(const void* data, int size, + uint8_t* ptr) { + if (size < GetSize(ptr) + ) { + return WriteRaw(data, size, ptr); + } else { + ptr = Trim(ptr); + if (stream_->WriteAliasedRaw(data, size)) return ptr; + return Error(); + } +} + +#ifndef PROTOBUF_LITTLE_ENDIAN +uint8_t* EpsCopyOutputStream::WriteRawLittleEndian32(const void* data, int size, + uint8_t* ptr) { + auto p = static_cast<const uint8_t*>(data); + auto end = p + size; + while (end - p >= kSlopBytes) { + ptr = EnsureSpace(ptr); + uint32_t buffer[4]; + static_assert(sizeof(buffer) == kSlopBytes, "Buffer must be kSlopBytes"); + std::memcpy(buffer, p, kSlopBytes); + p += kSlopBytes; + for (auto x : buffer) + ptr = CodedOutputStream::WriteLittleEndian32ToArray(x, ptr); + } + while (p < end) { + ptr = EnsureSpace(ptr); + uint32_t buffer; + std::memcpy(&buffer, p, 4); + p += 4; + ptr = CodedOutputStream::WriteLittleEndian32ToArray(buffer, ptr); + } + return ptr; +} + +uint8_t* EpsCopyOutputStream::WriteRawLittleEndian64(const void* data, int size, + uint8_t* ptr) { + auto p = static_cast<const uint8_t*>(data); + auto end = p + size; + while (end - p >= kSlopBytes) { + ptr = EnsureSpace(ptr); + uint64_t buffer[2]; + static_assert(sizeof(buffer) == kSlopBytes, "Buffer must be kSlopBytes"); + std::memcpy(buffer, p, kSlopBytes); + p += kSlopBytes; + for (auto x : buffer) + ptr = CodedOutputStream::WriteLittleEndian64ToArray(x, ptr); + } + while (p < end) { + ptr = EnsureSpace(ptr); + uint64_t buffer; + std::memcpy(&buffer, p, 8); + p += 8; + ptr = CodedOutputStream::WriteLittleEndian64ToArray(buffer, ptr); + } + return ptr; +} +#endif + + +uint8_t* EpsCopyOutputStream::WriteStringMaybeAliasedOutline(uint32_t num, + const std::string& s, + uint8_t* ptr) { + ptr = EnsureSpace(ptr); + uint32_t size = s.size(); + ptr = WriteLengthDelim(num, size, ptr); + return WriteRawMaybeAliased(s.data(), size, ptr); +} + +uint8_t* EpsCopyOutputStream::WriteStringOutline(uint32_t num, const std::string& s, + uint8_t* ptr) { + ptr = EnsureSpace(ptr); + uint32_t size = s.size(); + ptr = WriteLengthDelim(num, size, ptr); + return WriteRaw(s.data(), size, ptr); +} + +std::atomic<bool> CodedOutputStream::default_serialization_deterministic_{ + false}; + +CodedOutputStream::~CodedOutputStream() { Trim(); } + + +uint8_t* CodedOutputStream::WriteStringWithSizeToArray(const std::string& str, + uint8_t* target) { + GOOGLE_DCHECK_LE(str.size(), std::numeric_limits<uint32_t>::max()); + target = WriteVarint32ToArray(str.size(), target); + return WriteStringToArray(str, target); +} + +uint8_t* CodedOutputStream::WriteVarint32ToArrayOutOfLineHelper(uint32_t value, + uint8_t* target) { + GOOGLE_DCHECK_GE(value, 0x80); + target[0] |= static_cast<uint8_t>(0x80); + value >>= 7; + target[1] = static_cast<uint8_t>(value); + if (value < 0x80) { + return target + 2; + } + target += 2; + do { + // Turn on continuation bit in the byte we just wrote. + target[-1] |= static_cast<uint8_t>(0x80); + value >>= 7; + *target = static_cast<uint8_t>(value); + ++target; + } while (value >= 0x80); + return target; +} + +} // namespace io +} // namespace protobuf +} // namespace google + +#include <google/protobuf/port_undef.inc> diff --git a/toolkit/components/protobuf/src/google/protobuf/io/coded_stream.h b/toolkit/components/protobuf/src/google/protobuf/io/coded_stream.h new file mode 100644 index 0000000000..c8fc994f91 --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/io/coded_stream.h @@ -0,0 +1,1799 @@ +// 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. + +// Author: kenton@google.com (Kenton Varda) +// Based on original Protocol Buffers design by +// Sanjay Ghemawat, Jeff Dean, and others. +// +// This file contains the CodedInputStream and CodedOutputStream classes, +// which wrap a ZeroCopyInputStream or ZeroCopyOutputStream, respectively, +// and allow you to read or write individual pieces of data in various +// formats. In particular, these implement the varint encoding for +// integers, a simple variable-length encoding in which smaller numbers +// take fewer bytes. +// +// Typically these classes will only be used internally by the protocol +// buffer library in order to encode and decode protocol buffers. Clients +// of the library only need to know about this class if they wish to write +// custom message parsing or serialization procedures. +// +// CodedOutputStream example: +// // Write some data to "myfile". First we write a 4-byte "magic number" +// // to identify the file type, then write a length-delimited string. The +// // string is composed of a varint giving the length followed by the raw +// // bytes. +// int fd = open("myfile", O_CREAT | O_WRONLY); +// ZeroCopyOutputStream* raw_output = new FileOutputStream(fd); +// CodedOutputStream* coded_output = new CodedOutputStream(raw_output); +// +// int magic_number = 1234; +// char text[] = "Hello world!"; +// coded_output->WriteLittleEndian32(magic_number); +// coded_output->WriteVarint32(strlen(text)); +// coded_output->WriteRaw(text, strlen(text)); +// +// delete coded_output; +// delete raw_output; +// close(fd); +// +// CodedInputStream example: +// // Read a file created by the above code. +// int fd = open("myfile", O_RDONLY); +// ZeroCopyInputStream* raw_input = new FileInputStream(fd); +// CodedInputStream* coded_input = new CodedInputStream(raw_input); +// +// coded_input->ReadLittleEndian32(&magic_number); +// if (magic_number != 1234) { +// cerr << "File not in expected format." << endl; +// return; +// } +// +// uint32_t size; +// coded_input->ReadVarint32(&size); +// +// char* text = new char[size + 1]; +// coded_input->ReadRaw(buffer, size); +// text[size] = '\0'; +// +// delete coded_input; +// delete raw_input; +// close(fd); +// +// cout << "Text is: " << text << endl; +// delete [] text; +// +// For those who are interested, varint encoding is defined as follows: +// +// The encoding operates on unsigned integers of up to 64 bits in length. +// Each byte of the encoded value has the format: +// * bits 0-6: Seven bits of the number being encoded. +// * bit 7: Zero if this is the last byte in the encoding (in which +// case all remaining bits of the number are zero) or 1 if +// more bytes follow. +// The first byte contains the least-significant 7 bits of the number, the +// second byte (if present) contains the next-least-significant 7 bits, +// and so on. So, the binary number 1011000101011 would be encoded in two +// bytes as "10101011 00101100". +// +// In theory, varint could be used to encode integers of any length. +// However, for practicality we set a limit at 64 bits. The maximum encoded +// length of a number is thus 10 bytes. + +#ifndef GOOGLE_PROTOBUF_IO_CODED_STREAM_H__ +#define GOOGLE_PROTOBUF_IO_CODED_STREAM_H__ + + +#include <assert.h> + +#include <atomic> +#include <climits> +#include <cstddef> +#include <cstring> +#include <limits> +#include <string> +#include <type_traits> +#include <utility> + +#if defined(_MSC_VER) && _MSC_VER >= 1300 && !defined(__INTEL_COMPILER) +// If MSVC has "/RTCc" set, it will complain about truncating casts at +// runtime. This file contains some intentional truncating casts. +#pragma runtime_checks("c", off) +#endif + + +#include <google/protobuf/stubs/common.h> +#include <google/protobuf/stubs/logging.h> +#include <google/protobuf/stubs/strutil.h> +#include <google/protobuf/port.h> +#include <google/protobuf/stubs/port.h> + + +// Must be included last. +#include <google/protobuf/port_def.inc> + +namespace google { +namespace protobuf { + +class DescriptorPool; +class MessageFactory; +class ZeroCopyCodedInputStream; + +namespace internal { +void MapTestForceDeterministic(); +class EpsCopyByteStream; +} // namespace internal + +namespace io { + +// Defined in this file. +class CodedInputStream; +class CodedOutputStream; + +// Defined in other files. +class ZeroCopyInputStream; // zero_copy_stream.h +class ZeroCopyOutputStream; // zero_copy_stream.h + +// Class which reads and decodes binary data which is composed of varint- +// encoded integers and fixed-width pieces. Wraps a ZeroCopyInputStream. +// Most users will not need to deal with CodedInputStream. +// +// Most methods of CodedInputStream that return a bool return false if an +// underlying I/O error occurs or if the data is malformed. Once such a +// failure occurs, the CodedInputStream is broken and is no longer useful. +// After a failure, callers also should assume writes to "out" args may have +// occurred, though nothing useful can be determined from those writes. +class PROTOBUF_EXPORT CodedInputStream { + public: + // Create a CodedInputStream that reads from the given ZeroCopyInputStream. + explicit CodedInputStream(ZeroCopyInputStream* input); + + // Create a CodedInputStream that reads from the given flat array. This is + // faster than using an ArrayInputStream. PushLimit(size) is implied by + // this constructor. + explicit CodedInputStream(const uint8_t* buffer, int size); + + // Destroy the CodedInputStream and position the underlying + // ZeroCopyInputStream at the first unread byte. If an error occurred while + // reading (causing a method to return false), then the exact position of + // the input stream may be anywhere between the last value that was read + // successfully and the stream's byte limit. + ~CodedInputStream(); + + // Return true if this CodedInputStream reads from a flat array instead of + // a ZeroCopyInputStream. + inline bool IsFlat() const; + + // Skips a number of bytes. Returns false if an underlying read error + // occurs. + inline bool Skip(int count); + + // Sets *data to point directly at the unread part of the CodedInputStream's + // underlying buffer, and *size to the size of that buffer, but does not + // advance the stream's current position. This will always either produce + // a non-empty buffer or return false. If the caller consumes any of + // this data, it should then call Skip() to skip over the consumed bytes. + // This may be useful for implementing external fast parsing routines for + // types of data not covered by the CodedInputStream interface. + bool GetDirectBufferPointer(const void** data, int* size); + + // Like GetDirectBufferPointer, but this method is inlined, and does not + // attempt to Refresh() if the buffer is currently empty. + PROTOBUF_ALWAYS_INLINE + void GetDirectBufferPointerInline(const void** data, int* size); + + // Read raw bytes, copying them into the given buffer. + bool ReadRaw(void* buffer, int size); + + // Like ReadRaw, but reads into a string. + bool ReadString(std::string* buffer, int size); + + + // Read a 32-bit little-endian integer. + bool ReadLittleEndian32(uint32_t* value); + // Read a 64-bit little-endian integer. + bool ReadLittleEndian64(uint64_t* value); + + // These methods read from an externally provided buffer. The caller is + // responsible for ensuring that the buffer has sufficient space. + // Read a 32-bit little-endian integer. + static const uint8_t* ReadLittleEndian32FromArray(const uint8_t* buffer, + uint32_t* value); + // Read a 64-bit little-endian integer. + static const uint8_t* ReadLittleEndian64FromArray(const uint8_t* buffer, + uint64_t* value); + + // Read an unsigned integer with Varint encoding, truncating to 32 bits. + // Reading a 32-bit value is equivalent to reading a 64-bit one and casting + // it to uint32_t, but may be more efficient. + bool ReadVarint32(uint32_t* value); + // Read an unsigned integer with Varint encoding. + bool ReadVarint64(uint64_t* value); + + // Reads a varint off the wire into an "int". This should be used for reading + // sizes off the wire (sizes of strings, submessages, bytes fields, etc). + // + // The value from the wire is interpreted as unsigned. If its value exceeds + // the representable value of an integer on this platform, instead of + // truncating we return false. Truncating (as performed by ReadVarint32() + // above) is an acceptable approach for fields representing an integer, but + // when we are parsing a size from the wire, truncating the value would result + // in us misparsing the payload. + bool ReadVarintSizeAsInt(int* value); + + // Read a tag. This calls ReadVarint32() and returns the result, or returns + // zero (which is not a valid tag) if ReadVarint32() fails. Also, ReadTag + // (but not ReadTagNoLastTag) updates the last tag value, which can be checked + // with LastTagWas(). + // + // Always inline because this is only called in one place per parse loop + // but it is called for every iteration of said loop, so it should be fast. + // GCC doesn't want to inline this by default. + PROTOBUF_ALWAYS_INLINE uint32_t ReadTag() { + return last_tag_ = ReadTagNoLastTag(); + } + + PROTOBUF_ALWAYS_INLINE uint32_t ReadTagNoLastTag(); + + // This usually a faster alternative to ReadTag() when cutoff is a manifest + // constant. It does particularly well for cutoff >= 127. The first part + // of the return value is the tag that was read, though it can also be 0 in + // the cases where ReadTag() would return 0. If the second part is true + // then the tag is known to be in [0, cutoff]. If not, the tag either is + // above cutoff or is 0. (There's intentional wiggle room when tag is 0, + // because that can arise in several ways, and for best performance we want + // to avoid an extra "is tag == 0?" check here.) + PROTOBUF_ALWAYS_INLINE + std::pair<uint32_t, bool> ReadTagWithCutoff(uint32_t cutoff) { + std::pair<uint32_t, bool> result = ReadTagWithCutoffNoLastTag(cutoff); + last_tag_ = result.first; + return result; + } + + PROTOBUF_ALWAYS_INLINE + std::pair<uint32_t, bool> ReadTagWithCutoffNoLastTag(uint32_t cutoff); + + // Usually returns true if calling ReadVarint32() now would produce the given + // value. Will always return false if ReadVarint32() would not return the + // given value. If ExpectTag() returns true, it also advances past + // the varint. For best performance, use a compile-time constant as the + // parameter. + // Always inline because this collapses to a small number of instructions + // when given a constant parameter, but GCC doesn't want to inline by default. + PROTOBUF_ALWAYS_INLINE bool ExpectTag(uint32_t expected); + + // Like above, except this reads from the specified buffer. The caller is + // responsible for ensuring that the buffer is large enough to read a varint + // of the expected size. For best performance, use a compile-time constant as + // the expected tag parameter. + // + // Returns a pointer beyond the expected tag if it was found, or NULL if it + // was not. + PROTOBUF_ALWAYS_INLINE + static const uint8_t* ExpectTagFromArray(const uint8_t* buffer, + uint32_t expected); + + // Usually returns true if no more bytes can be read. Always returns false + // if more bytes can be read. If ExpectAtEnd() returns true, a subsequent + // call to LastTagWas() will act as if ReadTag() had been called and returned + // zero, and ConsumedEntireMessage() will return true. + bool ExpectAtEnd(); + + // If the last call to ReadTag() or ReadTagWithCutoff() returned the given + // value, returns true. Otherwise, returns false. + // ReadTagNoLastTag/ReadTagWithCutoffNoLastTag do not preserve the last + // returned value. + // + // This is needed because parsers for some types of embedded messages + // (with field type TYPE_GROUP) don't actually know that they've reached the + // end of a message until they see an ENDGROUP tag, which was actually part + // of the enclosing message. The enclosing message would like to check that + // tag to make sure it had the right number, so it calls LastTagWas() on + // return from the embedded parser to check. + bool LastTagWas(uint32_t expected); + void SetLastTag(uint32_t tag) { last_tag_ = tag; } + + // When parsing message (but NOT a group), this method must be called + // immediately after MergeFromCodedStream() returns (if it returns true) + // to further verify that the message ended in a legitimate way. For + // example, this verifies that parsing did not end on an end-group tag. + // It also checks for some cases where, due to optimizations, + // MergeFromCodedStream() can incorrectly return true. + bool ConsumedEntireMessage(); + void SetConsumed() { legitimate_message_end_ = true; } + + // Limits ---------------------------------------------------------- + // Limits are used when parsing length-delimited embedded messages. + // After the message's length is read, PushLimit() is used to prevent + // the CodedInputStream from reading beyond that length. Once the + // embedded message has been parsed, PopLimit() is called to undo the + // limit. + + // Opaque type used with PushLimit() and PopLimit(). Do not modify + // values of this type yourself. The only reason that this isn't a + // struct with private internals is for efficiency. + typedef int Limit; + + // Places a limit on the number of bytes that the stream may read, + // starting from the current position. Once the stream hits this limit, + // it will act like the end of the input has been reached until PopLimit() + // is called. + // + // As the names imply, the stream conceptually has a stack of limits. The + // shortest limit on the stack is always enforced, even if it is not the + // top limit. + // + // The value returned by PushLimit() is opaque to the caller, and must + // be passed unchanged to the corresponding call to PopLimit(). + Limit PushLimit(int byte_limit); + + // Pops the last limit pushed by PushLimit(). The input must be the value + // returned by that call to PushLimit(). + void PopLimit(Limit limit); + + // Returns the number of bytes left until the nearest limit on the + // stack is hit, or -1 if no limits are in place. + int BytesUntilLimit() const; + + // Returns current position relative to the beginning of the input stream. + int CurrentPosition() const; + + // Total Bytes Limit ----------------------------------------------- + // To prevent malicious users from sending excessively large messages + // and causing memory exhaustion, CodedInputStream imposes a hard limit on + // the total number of bytes it will read. + + // Sets the maximum number of bytes that this CodedInputStream will read + // before refusing to continue. To prevent servers from allocating enormous + // amounts of memory to hold parsed messages, the maximum message length + // should be limited to the shortest length that will not harm usability. + // The default limit is INT_MAX (~2GB) and apps should set shorter limits + // if possible. An error will always be printed to stderr if the limit is + // reached. + // + // Note: setting a limit less than the current read position is interpreted + // as a limit on the current position. + // + // This is unrelated to PushLimit()/PopLimit(). + void SetTotalBytesLimit(int total_bytes_limit); + + // The Total Bytes Limit minus the Current Position, or -1 if the total bytes + // limit is INT_MAX. + int BytesUntilTotalBytesLimit() const; + + // Recursion Limit ------------------------------------------------- + // To prevent corrupt or malicious messages from causing stack overflows, + // we must keep track of the depth of recursion when parsing embedded + // messages and groups. CodedInputStream keeps track of this because it + // is the only object that is passed down the stack during parsing. + + // Sets the maximum recursion depth. The default is 100. + void SetRecursionLimit(int limit); + int RecursionBudget() { return recursion_budget_; } + + static int GetDefaultRecursionLimit() { return default_recursion_limit_; } + + // Increments the current recursion depth. Returns true if the depth is + // under the limit, false if it has gone over. + bool IncrementRecursionDepth(); + + // Decrements the recursion depth if possible. + void DecrementRecursionDepth(); + + // Decrements the recursion depth blindly. This is faster than + // DecrementRecursionDepth(). It should be used only if all previous + // increments to recursion depth were successful. + void UnsafeDecrementRecursionDepth(); + + // Shorthand for make_pair(PushLimit(byte_limit), --recursion_budget_). + // Using this can reduce code size and complexity in some cases. The caller + // is expected to check that the second part of the result is non-negative (to + // bail out if the depth of recursion is too high) and, if all is well, to + // later pass the first part of the result to PopLimit() or similar. + std::pair<CodedInputStream::Limit, int> IncrementRecursionDepthAndPushLimit( + int byte_limit); + + // Shorthand for PushLimit(ReadVarint32(&length) ? length : 0). + Limit ReadLengthAndPushLimit(); + + // Helper that is equivalent to: { + // bool result = ConsumedEntireMessage(); + // PopLimit(limit); + // UnsafeDecrementRecursionDepth(); + // return result; } + // Using this can reduce code size and complexity in some cases. + // Do not use unless the current recursion depth is greater than zero. + bool DecrementRecursionDepthAndPopLimit(Limit limit); + + // Helper that is equivalent to: { + // bool result = ConsumedEntireMessage(); + // PopLimit(limit); + // return result; } + // Using this can reduce code size and complexity in some cases. + bool CheckEntireMessageConsumedAndPopLimit(Limit limit); + + // Extension Registry ---------------------------------------------- + // ADVANCED USAGE: 99.9% of people can ignore this section. + // + // By default, when parsing extensions, the parser looks for extension + // definitions in the pool which owns the outer message's Descriptor. + // However, you may call SetExtensionRegistry() to provide an alternative + // pool instead. This makes it possible, for example, to parse a message + // using a generated class, but represent some extensions using + // DynamicMessage. + + // Set the pool used to look up extensions. Most users do not need to call + // this as the correct pool will be chosen automatically. + // + // WARNING: It is very easy to misuse this. Carefully read the requirements + // below. Do not use this unless you are sure you need it. Almost no one + // does. + // + // Let's say you are parsing a message into message object m, and you want + // to take advantage of SetExtensionRegistry(). You must follow these + // requirements: + // + // The given DescriptorPool must contain m->GetDescriptor(). It is not + // sufficient for it to simply contain a descriptor that has the same name + // and content -- it must be the *exact object*. In other words: + // assert(pool->FindMessageTypeByName(m->GetDescriptor()->full_name()) == + // m->GetDescriptor()); + // There are two ways to satisfy this requirement: + // 1) Use m->GetDescriptor()->pool() as the pool. This is generally useless + // because this is the pool that would be used anyway if you didn't call + // SetExtensionRegistry() at all. + // 2) Use a DescriptorPool which has m->GetDescriptor()->pool() as an + // "underlay". Read the documentation for DescriptorPool for more + // information about underlays. + // + // You must also provide a MessageFactory. This factory will be used to + // construct Message objects representing extensions. The factory's + // GetPrototype() MUST return non-NULL for any Descriptor which can be found + // through the provided pool. + // + // If the provided factory might return instances of protocol-compiler- + // generated (i.e. compiled-in) types, or if the outer message object m is + // a generated type, then the given factory MUST have this property: If + // GetPrototype() is given a Descriptor which resides in + // DescriptorPool::generated_pool(), the factory MUST return the same + // prototype which MessageFactory::generated_factory() would return. That + // is, given a descriptor for a generated type, the factory must return an + // instance of the generated class (NOT DynamicMessage). However, when + // given a descriptor for a type that is NOT in generated_pool, the factory + // is free to return any implementation. + // + // The reason for this requirement is that generated sub-objects may be + // accessed via the standard (non-reflection) extension accessor methods, + // and these methods will down-cast the object to the generated class type. + // If the object is not actually of that type, the results would be undefined. + // On the other hand, if an extension is not compiled in, then there is no + // way the code could end up accessing it via the standard accessors -- the + // only way to access the extension is via reflection. When using reflection, + // DynamicMessage and generated messages are indistinguishable, so it's fine + // if these objects are represented using DynamicMessage. + // + // Using DynamicMessageFactory on which you have called + // SetDelegateToGeneratedFactory(true) should be sufficient to satisfy the + // above requirement. + // + // If either pool or factory is NULL, both must be NULL. + // + // Note that this feature is ignored when parsing "lite" messages as they do + // not have descriptors. + void SetExtensionRegistry(const DescriptorPool* pool, + MessageFactory* factory); + + // Get the DescriptorPool set via SetExtensionRegistry(), or NULL if no pool + // has been provided. + const DescriptorPool* GetExtensionPool(); + + // Get the MessageFactory set via SetExtensionRegistry(), or NULL if no + // factory has been provided. + MessageFactory* GetExtensionFactory(); + + private: + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(CodedInputStream); + + const uint8_t* buffer_; + const uint8_t* buffer_end_; // pointer to the end of the buffer. + ZeroCopyInputStream* input_; + int total_bytes_read_; // total bytes read from input_, including + // the current buffer + + // If total_bytes_read_ surpasses INT_MAX, we record the extra bytes here + // so that we can BackUp() on destruction. + int overflow_bytes_; + + // LastTagWas() stuff. + uint32_t last_tag_; // result of last ReadTag() or ReadTagWithCutoff(). + + // This is set true by ReadTag{Fallback/Slow}() if it is called when exactly + // at EOF, or by ExpectAtEnd() when it returns true. This happens when we + // reach the end of a message and attempt to read another tag. + bool legitimate_message_end_; + + // See EnableAliasing(). + bool aliasing_enabled_; + + // Limits + Limit current_limit_; // if position = -1, no limit is applied + + // For simplicity, if the current buffer crosses a limit (either a normal + // limit created by PushLimit() or the total bytes limit), buffer_size_ + // only tracks the number of bytes before that limit. This field + // contains the number of bytes after it. Note that this implies that if + // buffer_size_ == 0 and buffer_size_after_limit_ > 0, we know we've + // hit a limit. However, if both are zero, it doesn't necessarily mean + // we aren't at a limit -- the buffer may have ended exactly at the limit. + int buffer_size_after_limit_; + + // Maximum number of bytes to read, period. This is unrelated to + // current_limit_. Set using SetTotalBytesLimit(). + int total_bytes_limit_; + + // Current recursion budget, controlled by IncrementRecursionDepth() and + // similar. Starts at recursion_limit_ and goes down: if this reaches + // -1 we are over budget. + int recursion_budget_; + // Recursion depth limit, set by SetRecursionLimit(). + int recursion_limit_; + + // See SetExtensionRegistry(). + const DescriptorPool* extension_pool_; + MessageFactory* extension_factory_; + + // Private member functions. + + // Fallback when Skip() goes past the end of the current buffer. + bool SkipFallback(int count, int original_buffer_size); + + // Advance the buffer by a given number of bytes. + void Advance(int amount); + + // Back up input_ to the current buffer position. + void BackUpInputToCurrentPosition(); + + // Recomputes the value of buffer_size_after_limit_. Must be called after + // current_limit_ or total_bytes_limit_ changes. + void RecomputeBufferLimits(); + + // Writes an error message saying that we hit total_bytes_limit_. + void PrintTotalBytesLimitError(); + + // Called when the buffer runs out to request more data. Implies an + // Advance(BufferSize()). + bool Refresh(); + + // When parsing varints, we optimize for the common case of small values, and + // then optimize for the case when the varint fits within the current buffer + // piece. The Fallback method is used when we can't use the one-byte + // optimization. The Slow method is yet another fallback when the buffer is + // not large enough. Making the slow path out-of-line speeds up the common + // case by 10-15%. The slow path is fairly uncommon: it only triggers when a + // message crosses multiple buffers. Note: ReadVarint32Fallback() and + // ReadVarint64Fallback() are called frequently and generally not inlined, so + // they have been optimized to avoid "out" parameters. The former returns -1 + // if it fails and the uint32_t it read otherwise. The latter has a bool + // indicating success or failure as part of its return type. + int64_t ReadVarint32Fallback(uint32_t first_byte_or_zero); + int ReadVarintSizeAsIntFallback(); + std::pair<uint64_t, bool> ReadVarint64Fallback(); + bool ReadVarint32Slow(uint32_t* value); + bool ReadVarint64Slow(uint64_t* value); + int ReadVarintSizeAsIntSlow(); + bool ReadLittleEndian32Fallback(uint32_t* value); + bool ReadLittleEndian64Fallback(uint64_t* value); + + // Fallback/slow methods for reading tags. These do not update last_tag_, + // but will set legitimate_message_end_ if we are at the end of the input + // stream. + uint32_t ReadTagFallback(uint32_t first_byte_or_zero); + uint32_t ReadTagSlow(); + bool ReadStringFallback(std::string* buffer, int size); + + // Return the size of the buffer. + int BufferSize() const; + + static const int kDefaultTotalBytesLimit = INT_MAX; + + static int default_recursion_limit_; // 100 by default. + + friend class google::protobuf::ZeroCopyCodedInputStream; + friend class google::protobuf::internal::EpsCopyByteStream; +}; + +// EpsCopyOutputStream wraps a ZeroCopyOutputStream and exposes a new stream, +// which has the property you can write kSlopBytes (16 bytes) from the current +// position without bounds checks. The cursor into the stream is managed by +// the user of the class and is an explicit parameter in the methods. Careful +// use of this class, ie. keep ptr a local variable, eliminates the need to +// for the compiler to sync the ptr value between register and memory. +class PROTOBUF_EXPORT EpsCopyOutputStream { + public: + enum { kSlopBytes = 16 }; + + // Initialize from a stream. + EpsCopyOutputStream(ZeroCopyOutputStream* stream, bool deterministic, + uint8_t** pp) + : end_(buffer_), + stream_(stream), + is_serialization_deterministic_(deterministic) { + *pp = buffer_; + } + + // Only for array serialization. No overflow protection, end_ will be the + // pointed to the end of the array. When using this the total size is already + // known, so no need to maintain the slop region. + EpsCopyOutputStream(void* data, int size, bool deterministic) + : end_(static_cast<uint8_t*>(data) + size), + buffer_end_(nullptr), + stream_(nullptr), + is_serialization_deterministic_(deterministic) {} + + // Initialize from stream but with the first buffer already given (eager). + EpsCopyOutputStream(void* data, int size, ZeroCopyOutputStream* stream, + bool deterministic, uint8_t** pp) + : stream_(stream), is_serialization_deterministic_(deterministic) { + *pp = SetInitialBuffer(data, size); + } + + // Flush everything that's written into the underlying ZeroCopyOutputStream + // and trims the underlying stream to the location of ptr. + uint8_t* Trim(uint8_t* ptr); + + // After this it's guaranteed you can safely write kSlopBytes to ptr. This + // will never fail! The underlying stream can produce an error. Use HadError + // to check for errors. + PROTOBUF_NODISCARD uint8_t* EnsureSpace(uint8_t* ptr) { + if (PROTOBUF_PREDICT_FALSE(ptr >= end_)) { + return EnsureSpaceFallback(ptr); + } + return ptr; + } + + uint8_t* WriteRaw(const void* data, int size, uint8_t* ptr) { + if (PROTOBUF_PREDICT_FALSE(end_ - ptr < size)) { + return WriteRawFallback(data, size, ptr); + } + std::memcpy(ptr, data, size); + return ptr + size; + } + // Writes the buffer specified by data, size to the stream. Possibly by + // aliasing the buffer (ie. not copying the data). The caller is responsible + // to make sure the buffer is alive for the duration of the + // ZeroCopyOutputStream. +#ifndef NDEBUG + PROTOBUF_NOINLINE +#endif + uint8_t* WriteRawMaybeAliased(const void* data, int size, uint8_t* ptr) { + if (aliasing_enabled_) { + return WriteAliasedRaw(data, size, ptr); + } else { + return WriteRaw(data, size, ptr); + } + } + + +#ifndef NDEBUG + PROTOBUF_NOINLINE +#endif + uint8_t* WriteStringMaybeAliased(uint32_t num, const std::string& s, + uint8_t* ptr) { + std::ptrdiff_t size = s.size(); + if (PROTOBUF_PREDICT_FALSE( + size >= 128 || end_ - ptr + 16 - TagSize(num << 3) - 1 < size)) { + return WriteStringMaybeAliasedOutline(num, s, ptr); + } + ptr = UnsafeVarint((num << 3) | 2, ptr); + *ptr++ = static_cast<uint8_t>(size); + std::memcpy(ptr, s.data(), size); + return ptr + size; + } + uint8_t* WriteBytesMaybeAliased(uint32_t num, const std::string& s, + uint8_t* ptr) { + return WriteStringMaybeAliased(num, s, ptr); + } + + template <typename T> + PROTOBUF_ALWAYS_INLINE uint8_t* WriteString(uint32_t num, const T& s, + uint8_t* ptr) { + std::ptrdiff_t size = s.size(); + if (PROTOBUF_PREDICT_FALSE( + size >= 128 || end_ - ptr + 16 - TagSize(num << 3) - 1 < size)) { + return WriteStringOutline(num, s, ptr); + } + ptr = UnsafeVarint((num << 3) | 2, ptr); + *ptr++ = static_cast<uint8_t>(size); + std::memcpy(ptr, s.data(), size); + return ptr + size; + } + template <typename T> +#ifndef NDEBUG + PROTOBUF_NOINLINE +#endif + uint8_t* WriteBytes(uint32_t num, const T& s, uint8_t* ptr) { + return WriteString(num, s, ptr); + } + + template <typename T> + PROTOBUF_ALWAYS_INLINE uint8_t* WriteInt32Packed(int num, const T& r, + int size, uint8_t* ptr) { + return WriteVarintPacked(num, r, size, ptr, Encode64); + } + template <typename T> + PROTOBUF_ALWAYS_INLINE uint8_t* WriteUInt32Packed(int num, const T& r, + int size, uint8_t* ptr) { + return WriteVarintPacked(num, r, size, ptr, Encode32); + } + template <typename T> + PROTOBUF_ALWAYS_INLINE uint8_t* WriteSInt32Packed(int num, const T& r, + int size, uint8_t* ptr) { + return WriteVarintPacked(num, r, size, ptr, ZigZagEncode32); + } + template <typename T> + PROTOBUF_ALWAYS_INLINE uint8_t* WriteInt64Packed(int num, const T& r, + int size, uint8_t* ptr) { + return WriteVarintPacked(num, r, size, ptr, Encode64); + } + template <typename T> + PROTOBUF_ALWAYS_INLINE uint8_t* WriteUInt64Packed(int num, const T& r, + int size, uint8_t* ptr) { + return WriteVarintPacked(num, r, size, ptr, Encode64); + } + template <typename T> + PROTOBUF_ALWAYS_INLINE uint8_t* WriteSInt64Packed(int num, const T& r, + int size, uint8_t* ptr) { + return WriteVarintPacked(num, r, size, ptr, ZigZagEncode64); + } + template <typename T> + PROTOBUF_ALWAYS_INLINE uint8_t* WriteEnumPacked(int num, const T& r, int size, + uint8_t* ptr) { + return WriteVarintPacked(num, r, size, ptr, Encode64); + } + + template <typename T> + PROTOBUF_ALWAYS_INLINE uint8_t* WriteFixedPacked(int num, const T& r, + uint8_t* ptr) { + ptr = EnsureSpace(ptr); + constexpr auto element_size = sizeof(typename T::value_type); + auto size = r.size() * element_size; + ptr = WriteLengthDelim(num, size, ptr); + return WriteRawLittleEndian<element_size>(r.data(), static_cast<int>(size), + ptr); + } + + // Returns true if there was an underlying I/O error since this object was + // created. + bool HadError() const { return had_error_; } + + // Instructs the EpsCopyOutputStream to allow the underlying + // ZeroCopyOutputStream to hold pointers to the original structure instead of + // copying, if it supports it (i.e. output->AllowsAliasing() is true). If the + // underlying stream does not support aliasing, then enabling it has no + // affect. For now, this only affects the behavior of + // WriteRawMaybeAliased(). + // + // NOTE: It is caller's responsibility to ensure that the chunk of memory + // remains live until all of the data has been consumed from the stream. + void EnableAliasing(bool enabled); + + // See documentation on CodedOutputStream::SetSerializationDeterministic. + void SetSerializationDeterministic(bool value) { + is_serialization_deterministic_ = value; + } + + // See documentation on CodedOutputStream::IsSerializationDeterministic. + bool IsSerializationDeterministic() const { + return is_serialization_deterministic_; + } + + // The number of bytes written to the stream at position ptr, relative to the + // stream's overall position. + int64_t ByteCount(uint8_t* ptr) const; + + + private: + uint8_t* end_; + uint8_t* buffer_end_ = buffer_; + uint8_t buffer_[2 * kSlopBytes]; + ZeroCopyOutputStream* stream_; + bool had_error_ = false; + bool aliasing_enabled_ = false; // See EnableAliasing(). + bool is_serialization_deterministic_; + bool skip_check_consistency = false; + + uint8_t* EnsureSpaceFallback(uint8_t* ptr); + inline uint8_t* Next(); + int Flush(uint8_t* ptr); + std::ptrdiff_t GetSize(uint8_t* ptr) const { + GOOGLE_DCHECK(ptr <= end_ + kSlopBytes); // NOLINT + return end_ + kSlopBytes - ptr; + } + + uint8_t* Error() { + had_error_ = true; + // We use the patch buffer to always guarantee space to write to. + end_ = buffer_ + kSlopBytes; + return buffer_; + } + + static constexpr int TagSize(uint32_t tag) { + return (tag < (1 << 7)) ? 1 + : (tag < (1 << 14)) ? 2 + : (tag < (1 << 21)) ? 3 + : (tag < (1 << 28)) ? 4 + : 5; + } + + PROTOBUF_ALWAYS_INLINE uint8_t* WriteTag(uint32_t num, uint32_t wt, + uint8_t* ptr) { + GOOGLE_DCHECK(ptr < end_); // NOLINT + return UnsafeVarint((num << 3) | wt, ptr); + } + + PROTOBUF_ALWAYS_INLINE uint8_t* WriteLengthDelim(int num, uint32_t size, + uint8_t* ptr) { + ptr = WriteTag(num, 2, ptr); + return UnsafeWriteSize(size, ptr); + } + + uint8_t* WriteRawFallback(const void* data, int size, uint8_t* ptr); + + uint8_t* WriteAliasedRaw(const void* data, int size, uint8_t* ptr); + + uint8_t* WriteStringMaybeAliasedOutline(uint32_t num, const std::string& s, + uint8_t* ptr); + uint8_t* WriteStringOutline(uint32_t num, const std::string& s, uint8_t* ptr); + + template <typename T, typename E> + PROTOBUF_ALWAYS_INLINE uint8_t* WriteVarintPacked(int num, const T& r, + int size, uint8_t* ptr, + const E& encode) { + ptr = EnsureSpace(ptr); + ptr = WriteLengthDelim(num, size, ptr); + auto it = r.data(); + auto end = it + r.size(); + do { + ptr = EnsureSpace(ptr); + ptr = UnsafeVarint(encode(*it++), ptr); + } while (it < end); + return ptr; + } + + static uint32_t Encode32(uint32_t v) { return v; } + static uint64_t Encode64(uint64_t v) { return v; } + static uint32_t ZigZagEncode32(int32_t v) { + return (static_cast<uint32_t>(v) << 1) ^ static_cast<uint32_t>(v >> 31); + } + static uint64_t ZigZagEncode64(int64_t v) { + return (static_cast<uint64_t>(v) << 1) ^ static_cast<uint64_t>(v >> 63); + } + + template <typename T> + PROTOBUF_ALWAYS_INLINE static uint8_t* UnsafeVarint(T value, uint8_t* ptr) { + static_assert(std::is_unsigned<T>::value, + "Varint serialization must be unsigned"); + ptr[0] = static_cast<uint8_t>(value); + if (value < 0x80) { + return ptr + 1; + } + // Turn on continuation bit in the byte we just wrote. + ptr[0] |= static_cast<uint8_t>(0x80); + value >>= 7; + ptr[1] = static_cast<uint8_t>(value); + if (value < 0x80) { + return ptr + 2; + } + ptr += 2; + do { + // Turn on continuation bit in the byte we just wrote. + ptr[-1] |= static_cast<uint8_t>(0x80); + value >>= 7; + *ptr = static_cast<uint8_t>(value); + ++ptr; + } while (value >= 0x80); + return ptr; + } + + PROTOBUF_ALWAYS_INLINE static uint8_t* UnsafeWriteSize(uint32_t value, + uint8_t* ptr) { + while (PROTOBUF_PREDICT_FALSE(value >= 0x80)) { + *ptr = static_cast<uint8_t>(value | 0x80); + value >>= 7; + ++ptr; + } + *ptr++ = static_cast<uint8_t>(value); + return ptr; + } + + template <int S> + uint8_t* WriteRawLittleEndian(const void* data, int size, uint8_t* ptr); +#if !defined(PROTOBUF_LITTLE_ENDIAN) || \ + defined(PROTOBUF_DISABLE_LITTLE_ENDIAN_OPT_FOR_TEST) + uint8_t* WriteRawLittleEndian32(const void* data, int size, uint8_t* ptr); + uint8_t* WriteRawLittleEndian64(const void* data, int size, uint8_t* ptr); +#endif + + // These methods are for CodedOutputStream. Ideally they should be private + // but to match current behavior of CodedOutputStream as close as possible + // we allow it some functionality. + public: + uint8_t* SetInitialBuffer(void* data, int size) { + auto ptr = static_cast<uint8_t*>(data); + if (size > kSlopBytes) { + end_ = ptr + size - kSlopBytes; + buffer_end_ = nullptr; + return ptr; + } else { + end_ = buffer_ + size; + buffer_end_ = ptr; + return buffer_; + } + } + + private: + // Needed by CodedOutputStream HadError. HadError needs to flush the patch + // buffers to ensure there is no error as of yet. + uint8_t* FlushAndResetBuffer(uint8_t*); + + // The following functions mimic the old CodedOutputStream behavior as close + // as possible. They flush the current state to the stream, behave as + // the old CodedOutputStream and then return to normal operation. + bool Skip(int count, uint8_t** pp); + bool GetDirectBufferPointer(void** data, int* size, uint8_t** pp); + uint8_t* GetDirectBufferForNBytesAndAdvance(int size, uint8_t** pp); + + friend class CodedOutputStream; +}; + +template <> +inline uint8_t* EpsCopyOutputStream::WriteRawLittleEndian<1>(const void* data, + int size, + uint8_t* ptr) { + return WriteRaw(data, size, ptr); +} +template <> +inline uint8_t* EpsCopyOutputStream::WriteRawLittleEndian<4>(const void* data, + int size, + uint8_t* ptr) { +#if defined(PROTOBUF_LITTLE_ENDIAN) && \ + !defined(PROTOBUF_DISABLE_LITTLE_ENDIAN_OPT_FOR_TEST) + return WriteRaw(data, size, ptr); +#else + return WriteRawLittleEndian32(data, size, ptr); +#endif +} +template <> +inline uint8_t* EpsCopyOutputStream::WriteRawLittleEndian<8>(const void* data, + int size, + uint8_t* ptr) { +#if defined(PROTOBUF_LITTLE_ENDIAN) && \ + !defined(PROTOBUF_DISABLE_LITTLE_ENDIAN_OPT_FOR_TEST) + return WriteRaw(data, size, ptr); +#else + return WriteRawLittleEndian64(data, size, ptr); +#endif +} + +// Class which encodes and writes binary data which is composed of varint- +// encoded integers and fixed-width pieces. Wraps a ZeroCopyOutputStream. +// Most users will not need to deal with CodedOutputStream. +// +// Most methods of CodedOutputStream which return a bool return false if an +// underlying I/O error occurs. Once such a failure occurs, the +// CodedOutputStream is broken and is no longer useful. The Write* methods do +// not return the stream status, but will invalidate the stream if an error +// occurs. The client can probe HadError() to determine the status. +// +// Note that every method of CodedOutputStream which writes some data has +// a corresponding static "ToArray" version. These versions write directly +// to the provided buffer, returning a pointer past the last written byte. +// They require that the buffer has sufficient capacity for the encoded data. +// This allows an optimization where we check if an output stream has enough +// space for an entire message before we start writing and, if there is, we +// call only the ToArray methods to avoid doing bound checks for each +// individual value. +// i.e., in the example above: +// +// CodedOutputStream* coded_output = new CodedOutputStream(raw_output); +// int magic_number = 1234; +// char text[] = "Hello world!"; +// +// int coded_size = sizeof(magic_number) + +// CodedOutputStream::VarintSize32(strlen(text)) + +// strlen(text); +// +// uint8_t* buffer = +// coded_output->GetDirectBufferForNBytesAndAdvance(coded_size); +// if (buffer != nullptr) { +// // The output stream has enough space in the buffer: write directly to +// // the array. +// buffer = CodedOutputStream::WriteLittleEndian32ToArray(magic_number, +// buffer); +// buffer = CodedOutputStream::WriteVarint32ToArray(strlen(text), buffer); +// buffer = CodedOutputStream::WriteRawToArray(text, strlen(text), buffer); +// } else { +// // Make bound-checked writes, which will ask the underlying stream for +// // more space as needed. +// coded_output->WriteLittleEndian32(magic_number); +// coded_output->WriteVarint32(strlen(text)); +// coded_output->WriteRaw(text, strlen(text)); +// } +// +// delete coded_output; +class PROTOBUF_EXPORT CodedOutputStream { + public: + // Creates a CodedOutputStream that writes to the given `stream`. + // The provided stream must publicly derive from `ZeroCopyOutputStream`. + template <class Stream, class = typename std::enable_if<std::is_base_of< + ZeroCopyOutputStream, Stream>::value>::type> + explicit CodedOutputStream(Stream* stream); + + // Creates a CodedOutputStream that writes to the given `stream`, and does + // an 'eager initialization' of the internal state if `eager_init` is true. + // The provided stream must publicly derive from `ZeroCopyOutputStream`. + template <class Stream, class = typename std::enable_if<std::is_base_of< + ZeroCopyOutputStream, Stream>::value>::type> + CodedOutputStream(Stream* stream, bool eager_init); + + // Destroy the CodedOutputStream and position the underlying + // ZeroCopyOutputStream immediately after the last byte written. + ~CodedOutputStream(); + + // Returns true if there was an underlying I/O error since this object was + // created. On should call Trim before this function in order to catch all + // errors. + bool HadError() { + cur_ = impl_.FlushAndResetBuffer(cur_); + GOOGLE_DCHECK(cur_); + return impl_.HadError(); + } + + // Trims any unused space in the underlying buffer so that its size matches + // the number of bytes written by this stream. The underlying buffer will + // automatically be trimmed when this stream is destroyed; this call is only + // necessary if the underlying buffer is accessed *before* the stream is + // destroyed. + void Trim() { cur_ = impl_.Trim(cur_); } + + // Skips a number of bytes, leaving the bytes unmodified in the underlying + // buffer. Returns false if an underlying write error occurs. This is + // mainly useful with GetDirectBufferPointer(). + // Note of caution, the skipped bytes may contain uninitialized data. The + // caller must make sure that the skipped bytes are properly initialized, + // otherwise you might leak bytes from your heap. + bool Skip(int count) { return impl_.Skip(count, &cur_); } + + // Sets *data to point directly at the unwritten part of the + // CodedOutputStream's underlying buffer, and *size to the size of that + // buffer, but does not advance the stream's current position. This will + // always either produce a non-empty buffer or return false. If the caller + // writes any data to this buffer, it should then call Skip() to skip over + // the consumed bytes. This may be useful for implementing external fast + // serialization routines for types of data not covered by the + // CodedOutputStream interface. + bool GetDirectBufferPointer(void** data, int* size) { + return impl_.GetDirectBufferPointer(data, size, &cur_); + } + + // If there are at least "size" bytes available in the current buffer, + // returns a pointer directly into the buffer and advances over these bytes. + // The caller may then write directly into this buffer (e.g. using the + // *ToArray static methods) rather than go through CodedOutputStream. If + // there are not enough bytes available, returns NULL. The return pointer is + // invalidated as soon as any other non-const method of CodedOutputStream + // is called. + inline uint8_t* GetDirectBufferForNBytesAndAdvance(int size) { + return impl_.GetDirectBufferForNBytesAndAdvance(size, &cur_); + } + + // Write raw bytes, copying them from the given buffer. + void WriteRaw(const void* buffer, int size) { + cur_ = impl_.WriteRaw(buffer, size, cur_); + } + // Like WriteRaw() but will try to write aliased data if aliasing is + // turned on. + void WriteRawMaybeAliased(const void* data, int size); + // Like WriteRaw() but writing directly to the target array. + // This is _not_ inlined, as the compiler often optimizes memcpy into inline + // copy loops. Since this gets called by every field with string or bytes + // type, inlining may lead to a significant amount of code bloat, with only a + // minor performance gain. + static uint8_t* WriteRawToArray(const void* buffer, int size, + uint8_t* target); + + // Equivalent to WriteRaw(str.data(), str.size()). + void WriteString(const std::string& str); + // Like WriteString() but writing directly to the target array. + static uint8_t* WriteStringToArray(const std::string& str, uint8_t* target); + // Write the varint-encoded size of str followed by str. + static uint8_t* WriteStringWithSizeToArray(const std::string& str, + uint8_t* target); + + + // Write a 32-bit little-endian integer. + void WriteLittleEndian32(uint32_t value) { + cur_ = impl_.EnsureSpace(cur_); + SetCur(WriteLittleEndian32ToArray(value, Cur())); + } + // Like WriteLittleEndian32() but writing directly to the target array. + static uint8_t* WriteLittleEndian32ToArray(uint32_t value, uint8_t* target); + // Write a 64-bit little-endian integer. + void WriteLittleEndian64(uint64_t value) { + cur_ = impl_.EnsureSpace(cur_); + SetCur(WriteLittleEndian64ToArray(value, Cur())); + } + // Like WriteLittleEndian64() but writing directly to the target array. + static uint8_t* WriteLittleEndian64ToArray(uint64_t value, uint8_t* target); + + // Write an unsigned integer with Varint encoding. Writing a 32-bit value + // is equivalent to casting it to uint64_t and writing it as a 64-bit value, + // but may be more efficient. + void WriteVarint32(uint32_t value); + // Like WriteVarint32() but writing directly to the target array. + static uint8_t* WriteVarint32ToArray(uint32_t value, uint8_t* target); + // Like WriteVarint32() but writing directly to the target array, and with + // the less common-case paths being out of line rather than inlined. + static uint8_t* WriteVarint32ToArrayOutOfLine(uint32_t value, + uint8_t* target); + // Write an unsigned integer with Varint encoding. + void WriteVarint64(uint64_t value); + // Like WriteVarint64() but writing directly to the target array. + static uint8_t* WriteVarint64ToArray(uint64_t value, uint8_t* target); + + // Equivalent to WriteVarint32() except when the value is negative, + // in which case it must be sign-extended to a full 10 bytes. + void WriteVarint32SignExtended(int32_t value); + // Like WriteVarint32SignExtended() but writing directly to the target array. + static uint8_t* WriteVarint32SignExtendedToArray(int32_t value, + uint8_t* target); + + // This is identical to WriteVarint32(), but optimized for writing tags. + // In particular, if the input is a compile-time constant, this method + // compiles down to a couple instructions. + // Always inline because otherwise the aforementioned optimization can't work, + // but GCC by default doesn't want to inline this. + void WriteTag(uint32_t value); + // Like WriteTag() but writing directly to the target array. + PROTOBUF_ALWAYS_INLINE + static uint8_t* WriteTagToArray(uint32_t value, uint8_t* target); + + // Returns the number of bytes needed to encode the given value as a varint. + static size_t VarintSize32(uint32_t value); + // Returns the number of bytes needed to encode the given value as a varint. + static size_t VarintSize64(uint64_t value); + + // If negative, 10 bytes. Otherwise, same as VarintSize32(). + static size_t VarintSize32SignExtended(int32_t value); + + // Same as above, plus one. The additional one comes at no compute cost. + static size_t VarintSize32PlusOne(uint32_t value); + static size_t VarintSize64PlusOne(uint64_t value); + static size_t VarintSize32SignExtendedPlusOne(int32_t value); + + // Compile-time equivalent of VarintSize32(). + template <uint32_t Value> + struct StaticVarintSize32 { + static const size_t value = (Value < (1 << 7)) ? 1 + : (Value < (1 << 14)) ? 2 + : (Value < (1 << 21)) ? 3 + : (Value < (1 << 28)) ? 4 + : 5; + }; + + // Returns the total number of bytes written since this object was created. + int ByteCount() const { + return static_cast<int>(impl_.ByteCount(cur_) - start_count_); + } + + // Instructs the CodedOutputStream to allow the underlying + // ZeroCopyOutputStream to hold pointers to the original structure instead of + // copying, if it supports it (i.e. output->AllowsAliasing() is true). If the + // underlying stream does not support aliasing, then enabling it has no + // affect. For now, this only affects the behavior of + // WriteRawMaybeAliased(). + // + // NOTE: It is caller's responsibility to ensure that the chunk of memory + // remains live until all of the data has been consumed from the stream. + void EnableAliasing(bool enabled) { impl_.EnableAliasing(enabled); } + + // Indicate to the serializer whether the user wants deterministic + // serialization. The default when this is not called comes from the global + // default, controlled by SetDefaultSerializationDeterministic. + // + // What deterministic serialization means is entirely up to the driver of the + // serialization process (i.e. the caller of methods like WriteVarint32). In + // the case of serializing a proto buffer message using one of the methods of + // MessageLite, this means that for a given binary equal messages will always + // be serialized to the same bytes. This implies: + // + // * Repeated serialization of a message will return the same bytes. + // + // * Different processes running the same binary (including on different + // machines) will serialize equal messages to the same bytes. + // + // Note that this is *not* canonical across languages. It is also unstable + // across different builds with intervening message definition changes, due to + // unknown fields. Users who need canonical serialization (e.g. persistent + // storage in a canonical form, fingerprinting) should define their own + // canonicalization specification and implement the serializer using + // reflection APIs rather than relying on this API. + void SetSerializationDeterministic(bool value) { + impl_.SetSerializationDeterministic(value); + } + + // Return whether the user wants deterministic serialization. See above. + bool IsSerializationDeterministic() const { + return impl_.IsSerializationDeterministic(); + } + + static bool IsDefaultSerializationDeterministic() { + return default_serialization_deterministic_.load( + std::memory_order_relaxed) != 0; + } + + template <typename Func> + void Serialize(const Func& func); + + uint8_t* Cur() const { return cur_; } + void SetCur(uint8_t* ptr) { cur_ = ptr; } + EpsCopyOutputStream* EpsCopy() { return &impl_; } + + private: + template <class Stream> + void InitEagerly(Stream* stream); + + EpsCopyOutputStream impl_; + uint8_t* cur_; + int64_t start_count_; + static std::atomic<bool> default_serialization_deterministic_; + + // See above. Other projects may use "friend" to allow them to call this. + // After SetDefaultSerializationDeterministic() completes, all protocol + // buffer serializations will be deterministic by default. Thread safe. + // However, the meaning of "after" is subtle here: to be safe, each thread + // that wants deterministic serialization by default needs to call + // SetDefaultSerializationDeterministic() or ensure on its own that another + // thread has done so. + friend void internal::MapTestForceDeterministic(); + static void SetDefaultSerializationDeterministic() { + default_serialization_deterministic_.store(true, std::memory_order_relaxed); + } + // REQUIRES: value >= 0x80, and that (value & 7f) has been written to *target. + static uint8_t* WriteVarint32ToArrayOutOfLineHelper(uint32_t value, + uint8_t* target); + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(CodedOutputStream); +}; + +// inline methods ==================================================== +// The vast majority of varints are only one byte. These inline +// methods optimize for that case. + +inline bool CodedInputStream::ReadVarint32(uint32_t* value) { + uint32_t v = 0; + if (PROTOBUF_PREDICT_TRUE(buffer_ < buffer_end_)) { + v = *buffer_; + if (v < 0x80) { + *value = v; + Advance(1); + return true; + } + } + int64_t result = ReadVarint32Fallback(v); + *value = static_cast<uint32_t>(result); + return result >= 0; +} + +inline bool CodedInputStream::ReadVarint64(uint64_t* value) { + if (PROTOBUF_PREDICT_TRUE(buffer_ < buffer_end_) && *buffer_ < 0x80) { + *value = *buffer_; + Advance(1); + return true; + } + std::pair<uint64_t, bool> p = ReadVarint64Fallback(); + *value = p.first; + return p.second; +} + +inline bool CodedInputStream::ReadVarintSizeAsInt(int* value) { + if (PROTOBUF_PREDICT_TRUE(buffer_ < buffer_end_)) { + int v = *buffer_; + if (v < 0x80) { + *value = v; + Advance(1); + return true; + } + } + *value = ReadVarintSizeAsIntFallback(); + return *value >= 0; +} + +// static +inline const uint8_t* CodedInputStream::ReadLittleEndian32FromArray( + const uint8_t* buffer, uint32_t* value) { +#if defined(PROTOBUF_LITTLE_ENDIAN) && \ + !defined(PROTOBUF_DISABLE_LITTLE_ENDIAN_OPT_FOR_TEST) + memcpy(value, buffer, sizeof(*value)); + return buffer + sizeof(*value); +#else + *value = (static_cast<uint32_t>(buffer[0])) | + (static_cast<uint32_t>(buffer[1]) << 8) | + (static_cast<uint32_t>(buffer[2]) << 16) | + (static_cast<uint32_t>(buffer[3]) << 24); + return buffer + sizeof(*value); +#endif +} +// static +inline const uint8_t* CodedInputStream::ReadLittleEndian64FromArray( + const uint8_t* buffer, uint64_t* value) { +#if defined(PROTOBUF_LITTLE_ENDIAN) && \ + !defined(PROTOBUF_DISABLE_LITTLE_ENDIAN_OPT_FOR_TEST) + memcpy(value, buffer, sizeof(*value)); + return buffer + sizeof(*value); +#else + uint32_t part0 = (static_cast<uint32_t>(buffer[0])) | + (static_cast<uint32_t>(buffer[1]) << 8) | + (static_cast<uint32_t>(buffer[2]) << 16) | + (static_cast<uint32_t>(buffer[3]) << 24); + uint32_t part1 = (static_cast<uint32_t>(buffer[4])) | + (static_cast<uint32_t>(buffer[5]) << 8) | + (static_cast<uint32_t>(buffer[6]) << 16) | + (static_cast<uint32_t>(buffer[7]) << 24); + *value = static_cast<uint64_t>(part0) | (static_cast<uint64_t>(part1) << 32); + return buffer + sizeof(*value); +#endif +} + +inline bool CodedInputStream::ReadLittleEndian32(uint32_t* value) { +#if defined(PROTOBUF_LITTLE_ENDIAN) && \ + !defined(PROTOBUF_DISABLE_LITTLE_ENDIAN_OPT_FOR_TEST) + if (PROTOBUF_PREDICT_TRUE(BufferSize() >= static_cast<int>(sizeof(*value)))) { + buffer_ = ReadLittleEndian32FromArray(buffer_, value); + return true; + } else { + return ReadLittleEndian32Fallback(value); + } +#else + return ReadLittleEndian32Fallback(value); +#endif +} + +inline bool CodedInputStream::ReadLittleEndian64(uint64_t* value) { +#if defined(PROTOBUF_LITTLE_ENDIAN) && \ + !defined(PROTOBUF_DISABLE_LITTLE_ENDIAN_OPT_FOR_TEST) + if (PROTOBUF_PREDICT_TRUE(BufferSize() >= static_cast<int>(sizeof(*value)))) { + buffer_ = ReadLittleEndian64FromArray(buffer_, value); + return true; + } else { + return ReadLittleEndian64Fallback(value); + } +#else + return ReadLittleEndian64Fallback(value); +#endif +} + +inline uint32_t CodedInputStream::ReadTagNoLastTag() { + uint32_t v = 0; + if (PROTOBUF_PREDICT_TRUE(buffer_ < buffer_end_)) { + v = *buffer_; + if (v < 0x80) { + Advance(1); + return v; + } + } + v = ReadTagFallback(v); + return v; +} + +inline std::pair<uint32_t, bool> CodedInputStream::ReadTagWithCutoffNoLastTag( + uint32_t cutoff) { + // In performance-sensitive code we can expect cutoff to be a compile-time + // constant, and things like "cutoff >= kMax1ByteVarint" to be evaluated at + // compile time. + uint32_t first_byte_or_zero = 0; + if (PROTOBUF_PREDICT_TRUE(buffer_ < buffer_end_)) { + // Hot case: buffer_ non_empty, buffer_[0] in [1, 128). + // TODO(gpike): Is it worth rearranging this? E.g., if the number of fields + // is large enough then is it better to check for the two-byte case first? + first_byte_or_zero = buffer_[0]; + if (static_cast<int8_t>(buffer_[0]) > 0) { + const uint32_t kMax1ByteVarint = 0x7f; + uint32_t tag = buffer_[0]; + Advance(1); + return std::make_pair(tag, cutoff >= kMax1ByteVarint || tag <= cutoff); + } + // Other hot case: cutoff >= 0x80, buffer_ has at least two bytes available, + // and tag is two bytes. The latter is tested by bitwise-and-not of the + // first byte and the second byte. + if (cutoff >= 0x80 && PROTOBUF_PREDICT_TRUE(buffer_ + 1 < buffer_end_) && + PROTOBUF_PREDICT_TRUE((buffer_[0] & ~buffer_[1]) >= 0x80)) { + const uint32_t kMax2ByteVarint = (0x7f << 7) + 0x7f; + uint32_t tag = (1u << 7) * buffer_[1] + (buffer_[0] - 0x80); + Advance(2); + // It might make sense to test for tag == 0 now, but it is so rare that + // that we don't bother. A varint-encoded 0 should be one byte unless + // the encoder lost its mind. The second part of the return value of + // this function is allowed to be either true or false if the tag is 0, + // so we don't have to check for tag == 0. We may need to check whether + // it exceeds cutoff. + bool at_or_below_cutoff = cutoff >= kMax2ByteVarint || tag <= cutoff; + return std::make_pair(tag, at_or_below_cutoff); + } + } + // Slow path + const uint32_t tag = ReadTagFallback(first_byte_or_zero); + return std::make_pair(tag, static_cast<uint32_t>(tag - 1) < cutoff); +} + +inline bool CodedInputStream::LastTagWas(uint32_t expected) { + return last_tag_ == expected; +} + +inline bool CodedInputStream::ConsumedEntireMessage() { + return legitimate_message_end_; +} + +inline bool CodedInputStream::ExpectTag(uint32_t expected) { + if (expected < (1 << 7)) { + if (PROTOBUF_PREDICT_TRUE(buffer_ < buffer_end_) && + buffer_[0] == expected) { + Advance(1); + return true; + } else { + return false; + } + } else if (expected < (1 << 14)) { + if (PROTOBUF_PREDICT_TRUE(BufferSize() >= 2) && + buffer_[0] == static_cast<uint8_t>(expected | 0x80) && + buffer_[1] == static_cast<uint8_t>(expected >> 7)) { + Advance(2); + return true; + } else { + return false; + } + } else { + // Don't bother optimizing for larger values. + return false; + } +} + +inline const uint8_t* CodedInputStream::ExpectTagFromArray( + const uint8_t* buffer, uint32_t expected) { + if (expected < (1 << 7)) { + if (buffer[0] == expected) { + return buffer + 1; + } + } else if (expected < (1 << 14)) { + if (buffer[0] == static_cast<uint8_t>(expected | 0x80) && + buffer[1] == static_cast<uint8_t>(expected >> 7)) { + return buffer + 2; + } + } + return nullptr; +} + +inline void CodedInputStream::GetDirectBufferPointerInline(const void** data, + int* size) { + *data = buffer_; + *size = static_cast<int>(buffer_end_ - buffer_); +} + +inline bool CodedInputStream::ExpectAtEnd() { + // If we are at a limit we know no more bytes can be read. Otherwise, it's + // hard to say without calling Refresh(), and we'd rather not do that. + + if (buffer_ == buffer_end_ && ((buffer_size_after_limit_ != 0) || + (total_bytes_read_ == current_limit_))) { + last_tag_ = 0; // Pretend we called ReadTag()... + legitimate_message_end_ = true; // ... and it hit EOF. + return true; + } else { + return false; + } +} + +inline int CodedInputStream::CurrentPosition() const { + return total_bytes_read_ - (BufferSize() + buffer_size_after_limit_); +} + +inline void CodedInputStream::Advance(int amount) { buffer_ += amount; } + +inline void CodedInputStream::SetRecursionLimit(int limit) { + recursion_budget_ += limit - recursion_limit_; + recursion_limit_ = limit; +} + +inline bool CodedInputStream::IncrementRecursionDepth() { + --recursion_budget_; + return recursion_budget_ >= 0; +} + +inline void CodedInputStream::DecrementRecursionDepth() { + if (recursion_budget_ < recursion_limit_) ++recursion_budget_; +} + +inline void CodedInputStream::UnsafeDecrementRecursionDepth() { + assert(recursion_budget_ < recursion_limit_); + ++recursion_budget_; +} + +inline void CodedInputStream::SetExtensionRegistry(const DescriptorPool* pool, + MessageFactory* factory) { + extension_pool_ = pool; + extension_factory_ = factory; +} + +inline const DescriptorPool* CodedInputStream::GetExtensionPool() { + return extension_pool_; +} + +inline MessageFactory* CodedInputStream::GetExtensionFactory() { + return extension_factory_; +} + +inline int CodedInputStream::BufferSize() const { + return static_cast<int>(buffer_end_ - buffer_); +} + +inline CodedInputStream::CodedInputStream(ZeroCopyInputStream* input) + : buffer_(nullptr), + buffer_end_(nullptr), + input_(input), + total_bytes_read_(0), + overflow_bytes_(0), + last_tag_(0), + legitimate_message_end_(false), + aliasing_enabled_(false), + current_limit_(std::numeric_limits<int32_t>::max()), + buffer_size_after_limit_(0), + total_bytes_limit_(kDefaultTotalBytesLimit), + recursion_budget_(default_recursion_limit_), + recursion_limit_(default_recursion_limit_), + extension_pool_(nullptr), + extension_factory_(nullptr) { + // Eagerly Refresh() so buffer space is immediately available. + Refresh(); +} + +inline CodedInputStream::CodedInputStream(const uint8_t* buffer, int size) + : buffer_(buffer), + buffer_end_(buffer + size), + input_(nullptr), + total_bytes_read_(size), + overflow_bytes_(0), + last_tag_(0), + legitimate_message_end_(false), + aliasing_enabled_(false), + current_limit_(size), + buffer_size_after_limit_(0), + total_bytes_limit_(kDefaultTotalBytesLimit), + recursion_budget_(default_recursion_limit_), + recursion_limit_(default_recursion_limit_), + extension_pool_(nullptr), + extension_factory_(nullptr) { + // Note that setting current_limit_ == size is important to prevent some + // code paths from trying to access input_ and segfaulting. +} + +inline bool CodedInputStream::IsFlat() const { return input_ == nullptr; } + +inline bool CodedInputStream::Skip(int count) { + if (count < 0) return false; // security: count is often user-supplied + + const int original_buffer_size = BufferSize(); + + if (count <= original_buffer_size) { + // Just skipping within the current buffer. Easy. + Advance(count); + return true; + } + + return SkipFallback(count, original_buffer_size); +} + +template <class Stream, class> +inline CodedOutputStream::CodedOutputStream(Stream* stream) + : impl_(stream, IsDefaultSerializationDeterministic(), &cur_), + start_count_(stream->ByteCount()) { + InitEagerly(stream); +} + +template <class Stream, class> +inline CodedOutputStream::CodedOutputStream(Stream* stream, bool eager_init) + : impl_(stream, IsDefaultSerializationDeterministic(), &cur_), + start_count_(stream->ByteCount()) { + if (eager_init) { + InitEagerly(stream); + } +} + +template <class Stream> +inline void CodedOutputStream::InitEagerly(Stream* stream) { + void* data; + int size; + if (PROTOBUF_PREDICT_TRUE(stream->Next(&data, &size) && size > 0)) { + cur_ = impl_.SetInitialBuffer(data, size); + } +} + +inline uint8_t* CodedOutputStream::WriteVarint32ToArray(uint32_t value, + uint8_t* target) { + return EpsCopyOutputStream::UnsafeVarint(value, target); +} + +inline uint8_t* CodedOutputStream::WriteVarint32ToArrayOutOfLine( + uint32_t value, uint8_t* target) { + target[0] = static_cast<uint8_t>(value); + if (value < 0x80) { + return target + 1; + } else { + return WriteVarint32ToArrayOutOfLineHelper(value, target); + } +} + +inline uint8_t* CodedOutputStream::WriteVarint64ToArray(uint64_t value, + uint8_t* target) { + return EpsCopyOutputStream::UnsafeVarint(value, target); +} + +inline void CodedOutputStream::WriteVarint32SignExtended(int32_t value) { + WriteVarint64(static_cast<uint64_t>(value)); +} + +inline uint8_t* CodedOutputStream::WriteVarint32SignExtendedToArray( + int32_t value, uint8_t* target) { + return WriteVarint64ToArray(static_cast<uint64_t>(value), target); +} + +inline uint8_t* CodedOutputStream::WriteLittleEndian32ToArray(uint32_t value, + uint8_t* target) { +#if defined(PROTOBUF_LITTLE_ENDIAN) && \ + !defined(PROTOBUF_DISABLE_LITTLE_ENDIAN_OPT_FOR_TEST) + memcpy(target, &value, sizeof(value)); +#else + target[0] = static_cast<uint8_t>(value); + target[1] = static_cast<uint8_t>(value >> 8); + target[2] = static_cast<uint8_t>(value >> 16); + target[3] = static_cast<uint8_t>(value >> 24); +#endif + return target + sizeof(value); +} + +inline uint8_t* CodedOutputStream::WriteLittleEndian64ToArray(uint64_t value, + uint8_t* target) { +#if defined(PROTOBUF_LITTLE_ENDIAN) && \ + !defined(PROTOBUF_DISABLE_LITTLE_ENDIAN_OPT_FOR_TEST) + memcpy(target, &value, sizeof(value)); +#else + uint32_t part0 = static_cast<uint32_t>(value); + uint32_t part1 = static_cast<uint32_t>(value >> 32); + + target[0] = static_cast<uint8_t>(part0); + target[1] = static_cast<uint8_t>(part0 >> 8); + target[2] = static_cast<uint8_t>(part0 >> 16); + target[3] = static_cast<uint8_t>(part0 >> 24); + target[4] = static_cast<uint8_t>(part1); + target[5] = static_cast<uint8_t>(part1 >> 8); + target[6] = static_cast<uint8_t>(part1 >> 16); + target[7] = static_cast<uint8_t>(part1 >> 24); +#endif + return target + sizeof(value); +} + +inline void CodedOutputStream::WriteVarint32(uint32_t value) { + cur_ = impl_.EnsureSpace(cur_); + SetCur(WriteVarint32ToArray(value, Cur())); +} + +inline void CodedOutputStream::WriteVarint64(uint64_t value) { + cur_ = impl_.EnsureSpace(cur_); + SetCur(WriteVarint64ToArray(value, Cur())); +} + +inline void CodedOutputStream::WriteTag(uint32_t value) { + WriteVarint32(value); +} + +inline uint8_t* CodedOutputStream::WriteTagToArray(uint32_t value, + uint8_t* target) { + return WriteVarint32ToArray(value, target); +} + +inline size_t CodedOutputStream::VarintSize32(uint32_t value) { + // This computes value == 0 ? 1 : floor(log2(value)) / 7 + 1 + // Use an explicit multiplication to implement the divide of + // a number in the 1..31 range. + // Explicit OR 0x1 to avoid calling Bits::Log2FloorNonZero(0), which is + // undefined. + uint32_t log2value = Bits::Log2FloorNonZero(value | 0x1); + return static_cast<size_t>((log2value * 9 + 73) / 64); +} + +inline size_t CodedOutputStream::VarintSize32PlusOne(uint32_t value) { + // Same as above, but one more. + uint32_t log2value = Bits::Log2FloorNonZero(value | 0x1); + return static_cast<size_t>((log2value * 9 + 73 + 64) / 64); +} + +inline size_t CodedOutputStream::VarintSize64(uint64_t value) { + // This computes value == 0 ? 1 : floor(log2(value)) / 7 + 1 + // Use an explicit multiplication to implement the divide of + // a number in the 1..63 range. + // Explicit OR 0x1 to avoid calling Bits::Log2FloorNonZero(0), which is + // undefined. + uint32_t log2value = Bits::Log2FloorNonZero64(value | 0x1); + return static_cast<size_t>((log2value * 9 + 73) / 64); +} + +inline size_t CodedOutputStream::VarintSize64PlusOne(uint64_t value) { + // Same as above, but one more. + uint32_t log2value = Bits::Log2FloorNonZero64(value | 0x1); + return static_cast<size_t>((log2value * 9 + 73 + 64) / 64); +} + +inline size_t CodedOutputStream::VarintSize32SignExtended(int32_t value) { + return VarintSize64(static_cast<uint64_t>(int64_t{value})); +} + +inline size_t CodedOutputStream::VarintSize32SignExtendedPlusOne( + int32_t value) { + return VarintSize64PlusOne(static_cast<uint64_t>(int64_t{value})); +} + +inline void CodedOutputStream::WriteString(const std::string& str) { + WriteRaw(str.data(), static_cast<int>(str.size())); +} + +inline void CodedOutputStream::WriteRawMaybeAliased(const void* data, + int size) { + cur_ = impl_.WriteRawMaybeAliased(data, size, cur_); +} + +inline uint8_t* CodedOutputStream::WriteRawToArray(const void* data, int size, + uint8_t* target) { + memcpy(target, data, size); + return target + size; +} + +inline uint8_t* CodedOutputStream::WriteStringToArray(const std::string& str, + uint8_t* target) { + return WriteRawToArray(str.data(), static_cast<int>(str.size()), target); +} + +} // namespace io +} // namespace protobuf +} // namespace google + +#if defined(_MSC_VER) && _MSC_VER >= 1300 && !defined(__INTEL_COMPILER) +#pragma runtime_checks("c", restore) +#endif // _MSC_VER && !defined(__INTEL_COMPILER) + +#include <google/protobuf/port_undef.inc> + +#endif // GOOGLE_PROTOBUF_IO_CODED_STREAM_H__ diff --git a/toolkit/components/protobuf/src/google/protobuf/io/gzip_stream.cc b/toolkit/components/protobuf/src/google/protobuf/io/gzip_stream.cc new file mode 100644 index 0000000000..a5284b3e12 --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/io/gzip_stream.cc @@ -0,0 +1,334 @@ +// 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. + +// Author: brianolson@google.com (Brian Olson) +// +// This file contains the implementation of classes GzipInputStream and +// GzipOutputStream. + + +#if HAVE_ZLIB +#include <google/protobuf/io/gzip_stream.h> +#include <google/protobuf/port.h> + +#include <google/protobuf/stubs/common.h> +#include <google/protobuf/stubs/logging.h> + +namespace google { +namespace protobuf { +namespace io { + +static const int kDefaultBufferSize = 65536; + +GzipInputStream::GzipInputStream(ZeroCopyInputStream* sub_stream, Format format, + int buffer_size) + : format_(format), sub_stream_(sub_stream), zerror_(Z_OK), byte_count_(0) { + zcontext_.state = Z_NULL; + zcontext_.zalloc = Z_NULL; + zcontext_.zfree = Z_NULL; + zcontext_.opaque = Z_NULL; + zcontext_.total_out = 0; + zcontext_.next_in = NULL; + zcontext_.avail_in = 0; + zcontext_.total_in = 0; + zcontext_.msg = NULL; + if (buffer_size == -1) { + output_buffer_length_ = kDefaultBufferSize; + } else { + output_buffer_length_ = buffer_size; + } + output_buffer_ = operator new(output_buffer_length_); + GOOGLE_CHECK(output_buffer_ != NULL); + zcontext_.next_out = static_cast<Bytef*>(output_buffer_); + zcontext_.avail_out = output_buffer_length_; + output_position_ = output_buffer_; +} +GzipInputStream::~GzipInputStream() { + internal::SizedDelete(output_buffer_, output_buffer_length_); + zerror_ = inflateEnd(&zcontext_); +} + +static inline int internalInflateInit2(z_stream* zcontext, + GzipInputStream::Format format) { + int windowBitsFormat = 0; + switch (format) { + case GzipInputStream::GZIP: + windowBitsFormat = 16; + break; + case GzipInputStream::AUTO: + windowBitsFormat = 32; + break; + case GzipInputStream::ZLIB: + windowBitsFormat = 0; + break; + } + return inflateInit2(zcontext, /* windowBits */ 15 | windowBitsFormat); +} + +int GzipInputStream::Inflate(int flush) { + if ((zerror_ == Z_OK) && (zcontext_.avail_out == 0)) { + // previous inflate filled output buffer. don't change input params yet. + } else if (zcontext_.avail_in == 0) { + const void* in; + int in_size; + bool first = zcontext_.next_in == NULL; + bool ok = sub_stream_->Next(&in, &in_size); + if (!ok) { + zcontext_.next_out = NULL; + zcontext_.avail_out = 0; + return Z_STREAM_END; + } + zcontext_.next_in = static_cast<Bytef*>(const_cast<void*>(in)); + zcontext_.avail_in = in_size; + if (first) { + int error = internalInflateInit2(&zcontext_, format_); + if (error != Z_OK) { + return error; + } + } + } + zcontext_.next_out = static_cast<Bytef*>(output_buffer_); + zcontext_.avail_out = output_buffer_length_; + output_position_ = output_buffer_; + int error = inflate(&zcontext_, flush); + return error; +} + +void GzipInputStream::DoNextOutput(const void** data, int* size) { + *data = output_position_; + *size = ((uintptr_t)zcontext_.next_out) - ((uintptr_t)output_position_); + output_position_ = zcontext_.next_out; +} + +// implements ZeroCopyInputStream ---------------------------------- +bool GzipInputStream::Next(const void** data, int* size) { + bool ok = (zerror_ == Z_OK) || (zerror_ == Z_STREAM_END) || + (zerror_ == Z_BUF_ERROR); + if ((!ok) || (zcontext_.next_out == NULL)) { + return false; + } + if (zcontext_.next_out != output_position_) { + DoNextOutput(data, size); + return true; + } + if (zerror_ == Z_STREAM_END) { + if (zcontext_.next_out != NULL) { + // sub_stream_ may have concatenated streams to follow + zerror_ = inflateEnd(&zcontext_); + byte_count_ += zcontext_.total_out; + if (zerror_ != Z_OK) { + return false; + } + zerror_ = internalInflateInit2(&zcontext_, format_); + if (zerror_ != Z_OK) { + return false; + } + } else { + *data = NULL; + *size = 0; + return false; + } + } + zerror_ = Inflate(Z_NO_FLUSH); + if ((zerror_ == Z_STREAM_END) && (zcontext_.next_out == NULL)) { + // The underlying stream's Next returned false inside Inflate. + return false; + } + ok = (zerror_ == Z_OK) || (zerror_ == Z_STREAM_END) || + (zerror_ == Z_BUF_ERROR); + if (!ok) { + return false; + } + DoNextOutput(data, size); + return true; +} +void GzipInputStream::BackUp(int count) { + output_position_ = reinterpret_cast<void*>( + reinterpret_cast<uintptr_t>(output_position_) - count); +} +bool GzipInputStream::Skip(int count) { + const void* data; + int size = 0; + bool ok = Next(&data, &size); + while (ok && (size < count)) { + count -= size; + ok = Next(&data, &size); + } + if (size > count) { + BackUp(size - count); + } + return ok; +} +int64_t GzipInputStream::ByteCount() const { + int64_t ret = byte_count_ + zcontext_.total_out; + if (zcontext_.next_out != NULL && output_position_ != NULL) { + ret += reinterpret_cast<uintptr_t>(zcontext_.next_out) - + reinterpret_cast<uintptr_t>(output_position_); + } + return ret; +} + +// ========================================================================= + +GzipOutputStream::Options::Options() + : format(GZIP), + buffer_size(kDefaultBufferSize), + compression_level(Z_DEFAULT_COMPRESSION), + compression_strategy(Z_DEFAULT_STRATEGY) {} + +GzipOutputStream::GzipOutputStream(ZeroCopyOutputStream* sub_stream) { + Init(sub_stream, Options()); +} + +GzipOutputStream::GzipOutputStream(ZeroCopyOutputStream* sub_stream, + const Options& options) { + Init(sub_stream, options); +} + +void GzipOutputStream::Init(ZeroCopyOutputStream* sub_stream, + const Options& options) { + sub_stream_ = sub_stream; + sub_data_ = NULL; + sub_data_size_ = 0; + + input_buffer_length_ = options.buffer_size; + input_buffer_ = operator new(input_buffer_length_); + GOOGLE_CHECK(input_buffer_ != NULL); + + zcontext_.zalloc = Z_NULL; + zcontext_.zfree = Z_NULL; + zcontext_.opaque = Z_NULL; + zcontext_.next_out = NULL; + zcontext_.avail_out = 0; + zcontext_.total_out = 0; + zcontext_.next_in = NULL; + zcontext_.avail_in = 0; + zcontext_.total_in = 0; + zcontext_.msg = NULL; + // default to GZIP format + int windowBitsFormat = 16; + if (options.format == ZLIB) { + windowBitsFormat = 0; + } + zerror_ = + deflateInit2(&zcontext_, options.compression_level, Z_DEFLATED, + /* windowBits */ 15 | windowBitsFormat, + /* memLevel (default) */ 8, options.compression_strategy); +} + +GzipOutputStream::~GzipOutputStream() { + Close(); + internal::SizedDelete(input_buffer_, input_buffer_length_); +} + +// private +int GzipOutputStream::Deflate(int flush) { + int error = Z_OK; + do { + if ((sub_data_ == NULL) || (zcontext_.avail_out == 0)) { + bool ok = sub_stream_->Next(&sub_data_, &sub_data_size_); + if (!ok) { + sub_data_ = NULL; + sub_data_size_ = 0; + return Z_BUF_ERROR; + } + GOOGLE_CHECK_GT(sub_data_size_, 0); + zcontext_.next_out = static_cast<Bytef*>(sub_data_); + zcontext_.avail_out = sub_data_size_; + } + error = deflate(&zcontext_, flush); + } while (error == Z_OK && zcontext_.avail_out == 0); + if ((flush == Z_FULL_FLUSH) || (flush == Z_FINISH)) { + // Notify lower layer of data. + sub_stream_->BackUp(zcontext_.avail_out); + // We don't own the buffer anymore. + sub_data_ = NULL; + sub_data_size_ = 0; + } + return error; +} + +// implements ZeroCopyOutputStream --------------------------------- +bool GzipOutputStream::Next(void** data, int* size) { + if ((zerror_ != Z_OK) && (zerror_ != Z_BUF_ERROR)) { + return false; + } + if (zcontext_.avail_in != 0) { + zerror_ = Deflate(Z_NO_FLUSH); + if (zerror_ != Z_OK) { + return false; + } + } + if (zcontext_.avail_in == 0) { + // all input was consumed. reset the buffer. + zcontext_.next_in = static_cast<Bytef*>(input_buffer_); + zcontext_.avail_in = input_buffer_length_; + *data = input_buffer_; + *size = input_buffer_length_; + } else { + // The loop in Deflate should consume all avail_in + GOOGLE_LOG(DFATAL) << "Deflate left bytes unconsumed"; + } + return true; +} +void GzipOutputStream::BackUp(int count) { + GOOGLE_CHECK_GE(zcontext_.avail_in, static_cast<uInt>(count)); + zcontext_.avail_in -= count; +} +int64_t GzipOutputStream::ByteCount() const { + return zcontext_.total_in + zcontext_.avail_in; +} + +bool GzipOutputStream::Flush() { + zerror_ = Deflate(Z_FULL_FLUSH); + // Return true if the flush succeeded or if it was a no-op. + return (zerror_ == Z_OK) || + (zerror_ == Z_BUF_ERROR && zcontext_.avail_in == 0 && + zcontext_.avail_out != 0); +} + +bool GzipOutputStream::Close() { + if ((zerror_ != Z_OK) && (zerror_ != Z_BUF_ERROR)) { + return false; + } + do { + zerror_ = Deflate(Z_FINISH); + } while (zerror_ == Z_OK); + zerror_ = deflateEnd(&zcontext_); + bool ok = zerror_ == Z_OK; + zerror_ = Z_STREAM_END; + return ok; +} + +} // namespace io +} // namespace protobuf +} // namespace google + +#endif // HAVE_ZLIB diff --git a/toolkit/components/protobuf/src/google/protobuf/io/gzip_stream.h b/toolkit/components/protobuf/src/google/protobuf/io/gzip_stream.h new file mode 100644 index 0000000000..4cf71b6c32 --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/io/gzip_stream.h @@ -0,0 +1,205 @@ +// 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. + +// Author: brianolson@google.com (Brian Olson) +// +// This file contains the definition for classes GzipInputStream and +// GzipOutputStream. +// +// GzipInputStream decompresses data from an underlying +// ZeroCopyInputStream and provides the decompressed data as a +// ZeroCopyInputStream. +// +// GzipOutputStream is an ZeroCopyOutputStream that compresses data to +// an underlying ZeroCopyOutputStream. + +#ifndef GOOGLE_PROTOBUF_IO_GZIP_STREAM_H__ +#define GOOGLE_PROTOBUF_IO_GZIP_STREAM_H__ + + +#include <google/protobuf/stubs/common.h> +#include <google/protobuf/io/zero_copy_stream.h> +#include <google/protobuf/port.h> +#include "zlib.h" + +// Must be included last. +#include <google/protobuf/port_def.inc> + +namespace google { +namespace protobuf { +namespace io { + +// A ZeroCopyInputStream that reads compressed data through zlib +class PROTOBUF_EXPORT GzipInputStream PROTOBUF_FUTURE_FINAL + : public ZeroCopyInputStream { + public: + // Format key for constructor + enum Format { + // zlib will autodetect gzip header or deflate stream + AUTO = 0, + + // GZIP streams have some extra header data for file attributes. + GZIP = 1, + + // Simpler zlib stream format. + ZLIB = 2, + }; + + // buffer_size and format may be -1 for default of 64kB and GZIP format + explicit GzipInputStream(ZeroCopyInputStream* sub_stream, + Format format = AUTO, int buffer_size = -1); + virtual ~GzipInputStream(); + + // Return last error message or NULL if no error. + inline const char* ZlibErrorMessage() const { return zcontext_.msg; } + inline int ZlibErrorCode() const { return zerror_; } + + // implements ZeroCopyInputStream ---------------------------------- + bool Next(const void** data, int* size) override; + void BackUp(int count) override; + bool Skip(int count) override; + int64_t ByteCount() const override; + + private: + Format format_; + + ZeroCopyInputStream* sub_stream_; + + z_stream zcontext_; + int zerror_; + + void* output_buffer_; + void* output_position_; + size_t output_buffer_length_; + int64_t byte_count_; + + int Inflate(int flush); + void DoNextOutput(const void** data, int* size); + + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(GzipInputStream); +}; + +class PROTOBUF_EXPORT GzipOutputStream PROTOBUF_FUTURE_FINAL + : public ZeroCopyOutputStream { + public: + // Format key for constructor + enum Format { + // GZIP streams have some extra header data for file attributes. + GZIP = 1, + + // Simpler zlib stream format. + ZLIB = 2, + }; + + struct PROTOBUF_EXPORT Options { + // Defaults to GZIP. + Format format; + + // What size buffer to use internally. Defaults to 64kB. + int buffer_size; + + // A number between 0 and 9, where 0 is no compression and 9 is best + // compression. Defaults to Z_DEFAULT_COMPRESSION (see zlib.h). + int compression_level; + + // Defaults to Z_DEFAULT_STRATEGY. Can also be set to Z_FILTERED, + // Z_HUFFMAN_ONLY, or Z_RLE. See the documentation for deflateInit2 in + // zlib.h for definitions of these constants. + int compression_strategy; + + Options(); // Initializes with default values. + }; + + // Create a GzipOutputStream with default options. + explicit GzipOutputStream(ZeroCopyOutputStream* sub_stream); + + // Create a GzipOutputStream with the given options. + GzipOutputStream(ZeroCopyOutputStream* sub_stream, const Options& options); + + virtual ~GzipOutputStream(); + + // Return last error message or NULL if no error. + inline const char* ZlibErrorMessage() const { return zcontext_.msg; } + inline int ZlibErrorCode() const { return zerror_; } + + // Flushes data written so far to zipped data in the underlying stream. + // It is the caller's responsibility to flush the underlying stream if + // necessary. + // Compression may be less efficient stopping and starting around flushes. + // Returns true if no error. + // + // Please ensure that block size is > 6. Here is an excerpt from the zlib + // doc that explains why: + // + // In the case of a Z_FULL_FLUSH or Z_SYNC_FLUSH, make sure that avail_out + // is greater than six to avoid repeated flush markers due to + // avail_out == 0 on return. + bool Flush(); + + // Writes out all data and closes the gzip stream. + // It is the caller's responsibility to close the underlying stream if + // necessary. + // Returns true if no error. + bool Close(); + + // implements ZeroCopyOutputStream --------------------------------- + bool Next(void** data, int* size) override; + void BackUp(int count) override; + int64_t ByteCount() const override; + + private: + ZeroCopyOutputStream* sub_stream_; + // Result from calling Next() on sub_stream_ + void* sub_data_; + int sub_data_size_; + + z_stream zcontext_; + int zerror_; + void* input_buffer_; + size_t input_buffer_length_; + + // Shared constructor code. + void Init(ZeroCopyOutputStream* sub_stream, const Options& options); + + // Do some compression. + // Takes zlib flush mode. + // Returns zlib error code. + int Deflate(int flush); + + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(GzipOutputStream); +}; + +} // namespace io +} // namespace protobuf +} // namespace google + +#include <google/protobuf/port_undef.inc> + +#endif // GOOGLE_PROTOBUF_IO_GZIP_STREAM_H__ diff --git a/toolkit/components/protobuf/src/google/protobuf/io/io_win32.cc b/toolkit/components/protobuf/src/google/protobuf/io/io_win32.cc new file mode 100644 index 0000000000..4e81908809 --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/io/io_win32.cc @@ -0,0 +1,471 @@ +// 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. + +// Author: laszlocsomor@google.com (Laszlo Csomor) +// Based on original Protocol Buffers design by +// Sanjay Ghemawat, Jeff Dean, and others. + +// Implementation for long-path-aware open/mkdir/access/etc. on Windows, as well +// as for the supporting utility functions. +// +// These functions convert the input path to an absolute Windows path +// with "\\?\" prefix, then pass that to _wopen/_wmkdir/_waccess/etc. +// (declared in <io.h>) respectively. This allows working with files/directories +// whose paths are longer than MAX_PATH (260 chars). +// +// This file is only used on Windows, it's empty on other platforms. + +#if defined(_WIN32) && !defined(_XBOX_ONE) + +// Comment this out to fall back to using the ANSI versions (open, mkdir, ...) +// instead of the Unicode ones (_wopen, _wmkdir, ...). Doing so can be useful to +// debug failing tests if that's caused by the long path support. +#define SUPPORT_LONGPATHS + +#include <google/protobuf/io/io_win32.h> + +#include <ctype.h> +#include <direct.h> +#include <errno.h> +#include <fcntl.h> +#include <io.h> +#include <sys/stat.h> +#include <sys/types.h> +#include <wctype.h> + +#ifndef WIN32_LEAN_AND_MEAN +#define WIN32_LEAN_AND_MEAN 1 +#endif + +#include <windows.h> + +#include <memory> +#include <sstream> +#include <string> +#include <vector> + +namespace google { +namespace protobuf { +namespace io { +namespace win32 { +namespace { + +using std::string; +using std::wstring; + +template <typename char_type> +struct CharTraits { + static bool is_alpha(char_type ch); +}; + +template <> +struct CharTraits<char> { + static bool is_alpha(char ch) { return isalpha(ch); } +}; + +template <> +struct CharTraits<wchar_t> { + static bool is_alpha(wchar_t ch) { return iswalpha(ch); } +}; + +template <typename char_type> +bool null_or_empty(const char_type* s) { + return s == nullptr || *s == 0; +} + +// Returns true if the path starts with a drive letter, e.g. "c:". +// Note that this won't check for the "\" after the drive letter, so this also +// returns true for "c:foo" (which is "c:\${PWD}\foo"). +// This check requires that a path not have a longpath prefix ("\\?\"). +template <typename char_type> +bool has_drive_letter(const char_type* ch) { + return CharTraits<char_type>::is_alpha(ch[0]) && ch[1] == ':'; +} + +// Returns true if the path starts with a longpath prefix ("\\?\"). +template <typename char_type> +bool has_longpath_prefix(const char_type* path) { + return path[0] == '\\' && path[1] == '\\' && path[2] == '?' && + path[3] == '\\'; +} + +template <typename char_type> +bool is_separator(char_type c) { + return c == '/' || c == '\\'; +} + +// Returns true if the path starts with a drive specifier (e.g. "c:\"). +template <typename char_type> +bool is_path_absolute(const char_type* path) { + return has_drive_letter(path) && is_separator(path[2]); +} + +template <typename char_type> +bool is_drive_relative(const char_type* path) { + return has_drive_letter(path) && (path[2] == 0 || !is_separator(path[2])); +} + +wstring join_paths(const wstring& path1, const wstring& path2) { + if (path1.empty() || is_path_absolute(path2.c_str()) || + has_longpath_prefix(path2.c_str())) { + return path2; + } + if (path2.empty()) { + return path1; + } + + if (is_separator(path1[path1.size() - 1])) { + return is_separator(path2[0]) ? (path1 + path2.substr(1)) + : (path1 + path2); + } else { + return is_separator(path2[0]) ? (path1 + path2) + : (path1 + L'\\' + path2); + } +} + +wstring normalize(wstring path) { + if (has_longpath_prefix(path.c_str())) { + path = path.substr(4); + } + + static const wstring dot(L"."); + static const wstring dotdot(L".."); + const WCHAR* p = path.c_str(); + + std::vector<wstring> segments; + int segment_start = -1; + // Find the path segments in `path` (separated by "/"). + for (int i = 0;; ++i) { + if (!is_separator(p[i]) && p[i] != L'\0') { + // The current character does not end a segment, so start one unless it's + // already started. + if (segment_start < 0) { + segment_start = i; + } + } else if (segment_start >= 0 && i > segment_start) { + // The current character is "/" or "\0", so this ends a segment. + // Add that to `segments` if there's anything to add; handle "." and "..". + wstring segment(p, segment_start, i - segment_start); + segment_start = -1; + if (segment == dotdot) { + if (!segments.empty() && + (!has_drive_letter(segments[0].c_str()) || segments.size() > 1)) { + segments.pop_back(); + } + } else if (segment != dot && !segment.empty()) { + segments.push_back(segment); + } + } + if (p[i] == L'\0') { + break; + } + } + + // Handle the case when `path` is just a drive specifier (or some degenerate + // form of it, e.g. "c:\.."). + if (segments.size() == 1 && segments[0].size() == 2 && + has_drive_letter(segments[0].c_str())) { + return segments[0] + L'\\'; + } + + // Join all segments. + bool first = true; + std::wstringstream result; + for (int i = 0; i < segments.size(); ++i) { + if (!first) { + result << L'\\'; + } + first = false; + result << segments[i]; + } + // Preserve trailing separator if the input contained it. + if (!path.empty() && is_separator(p[path.size() - 1])) { + result << L'\\'; + } + return result.str(); +} + +bool as_windows_path(const char* path, wstring* result) { + if (null_or_empty(path)) { + result->clear(); + return true; + } + wstring wpath; + if (!strings::utf8_to_wcs(path, &wpath)) { + return false; + } + if (has_longpath_prefix(wpath.c_str())) { + *result = wpath; + return true; + } + if (is_separator(path[0]) || is_drive_relative(path)) { + return false; + } + + + if (!is_path_absolute(wpath.c_str())) { + int size = ::GetCurrentDirectoryW(0, nullptr); + if (size == 0 && GetLastError() != ERROR_INSUFFICIENT_BUFFER) { + return false; + } + std::unique_ptr<WCHAR[]> wcwd(new WCHAR[size]); + ::GetCurrentDirectoryW(size, wcwd.get()); + wpath = join_paths(wcwd.get(), wpath); + } + wpath = normalize(wpath); + if (!has_longpath_prefix(wpath.c_str())) { + // Add the "\\?\" prefix unconditionally. This way we prevent the Win32 API + // from processing the path and "helpfully" removing trailing dots from the + // path, for example. + // See https://github.com/bazelbuild/bazel/issues/2935 + wpath = wstring(L"\\\\?\\") + wpath; + } + *result = wpath; + return true; +} + +} // namespace + +int open(const char* path, int flags, int mode) { +#ifdef SUPPORT_LONGPATHS + wstring wpath; + if (!as_windows_path(path, &wpath)) { + errno = ENOENT; + return -1; + } + return ::_wopen(wpath.c_str(), flags, mode); +#else + return ::_open(path, flags, mode); +#endif +} + +int mkdir(const char* path, int /*_mode*/) { +#ifdef SUPPORT_LONGPATHS + wstring wpath; + if (!as_windows_path(path, &wpath)) { + errno = ENOENT; + return -1; + } + return ::_wmkdir(wpath.c_str()); +#else // not SUPPORT_LONGPATHS + return ::_mkdir(path); +#endif // not SUPPORT_LONGPATHS +} + +int access(const char* path, int mode) { +#ifdef SUPPORT_LONGPATHS + wstring wpath; + if (!as_windows_path(path, &wpath)) { + errno = ENOENT; + return -1; + } + return ::_waccess(wpath.c_str(), mode); +#else + return ::_access(path, mode); +#endif +} + +int chdir(const char* path) { +#ifdef SUPPORT_LONGPATHS + wstring wpath; + if (!as_windows_path(path, &wpath)) { + errno = ENOENT; + return -1; + } + return ::_wchdir(wpath.c_str()); +#else + return ::_chdir(path); +#endif +} + +int stat(const char* path, struct _stat* buffer) { +#ifdef SUPPORT_LONGPATHS + wstring wpath; + if (!as_windows_path(path, &wpath)) { + errno = ENOENT; + return -1; + } + return ::_wstat(wpath.c_str(), buffer); +#else // not SUPPORT_LONGPATHS + return ::_stat(path, buffer); +#endif // not SUPPORT_LONGPATHS +} + +FILE* fopen(const char* path, const char* mode) { +#ifdef SUPPORT_LONGPATHS + if (null_or_empty(path)) { + errno = EINVAL; + return nullptr; + } + wstring wpath; + if (!as_windows_path(path, &wpath)) { + errno = ENOENT; + return nullptr; + } + wstring wmode; + if (!strings::utf8_to_wcs(mode, &wmode)) { + errno = EINVAL; + return nullptr; + } + return ::_wfopen(wpath.c_str(), wmode.c_str()); +#else + return ::fopen(path, mode); +#endif +} + +int close(int fd) { return ::_close(fd); } + +int dup(int fd) { return ::_dup(fd); } + +int dup2(int fd1, int fd2) { return ::_dup2(fd1, fd2); } + +int read(int fd, void* buffer, size_t size) { + return ::_read(fd, buffer, size); +} + +int setmode(int fd, int mode) { return ::_setmode(fd, mode); } + +int write(int fd, const void* buffer, size_t size) { + return ::_write(fd, buffer, size); +} + +wstring testonly_utf8_to_winpath(const char* path) { + wstring wpath; + return as_windows_path(path, &wpath) ? wpath : wstring(); +} + +ExpandWildcardsResult ExpandWildcards( + const string& path, std::function<void(const string&)> consume) { + if (path.find_first_of("*?") == string::npos) { + // There are no wildcards in the path, we don't need to expand it. + consume(path); + return ExpandWildcardsResult::kSuccess; + } + + wstring wpath; + if (!as_windows_path(path.c_str(), &wpath)) { + return ExpandWildcardsResult::kErrorInputPathConversion; + } + + static const wstring kDot = L"."; + static const wstring kDotDot = L".."; + WIN32_FIND_DATAW metadata; + HANDLE handle = ::FindFirstFileW(wpath.c_str(), &metadata); + if (handle == INVALID_HANDLE_VALUE) { + // The pattern does not match any files (or directories). + return ExpandWildcardsResult::kErrorNoMatchingFile; + } + + string::size_type pos = path.find_last_of("\\/"); + string dirname; + if (pos != string::npos) { + dirname = path.substr(0, pos + 1); + } + + ExpandWildcardsResult matched = ExpandWildcardsResult::kErrorNoMatchingFile; + do { + // Ignore ".", "..", and directories. + if ((metadata.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0 && + kDot != metadata.cFileName && kDotDot != metadata.cFileName) { + matched = ExpandWildcardsResult::kSuccess; + string filename; + if (!strings::wcs_to_utf8(metadata.cFileName, &filename)) { + matched = ExpandWildcardsResult::kErrorOutputPathConversion; + break; + } + + if (dirname.empty()) { + consume(filename); + } else { + consume(dirname + filename); + } + } + } while (::FindNextFileW(handle, &metadata)); + FindClose(handle); + return matched; +} + +namespace strings { + +bool wcs_to_mbs(const WCHAR* s, string* out, bool outUtf8) { + if (null_or_empty(s)) { + out->clear(); + return true; + } + BOOL usedDefaultChar = FALSE; + SetLastError(0); + int size = WideCharToMultiByte( + outUtf8 ? CP_UTF8 : CP_ACP, 0, s, -1, nullptr, 0, nullptr, + outUtf8 ? nullptr : &usedDefaultChar); + if ((size == 0 && GetLastError() != ERROR_INSUFFICIENT_BUFFER) + || usedDefaultChar) { + return false; + } + std::unique_ptr<CHAR[]> astr(new CHAR[size]); + WideCharToMultiByte( + outUtf8 ? CP_UTF8 : CP_ACP, 0, s, -1, astr.get(), size, nullptr, nullptr); + out->assign(astr.get()); + return true; +} + +bool mbs_to_wcs(const char* s, wstring* out, bool inUtf8) { + if (null_or_empty(s)) { + out->clear(); + return true; + } + + SetLastError(0); + int size = + MultiByteToWideChar(inUtf8 ? CP_UTF8 : CP_ACP, 0, s, -1, nullptr, 0); + if (size == 0 && GetLastError() != ERROR_INSUFFICIENT_BUFFER) { + return false; + } + std::unique_ptr<WCHAR[]> wstr(new WCHAR[size]); + MultiByteToWideChar( + inUtf8 ? CP_UTF8 : CP_ACP, 0, s, -1, wstr.get(), size + 1); + out->assign(wstr.get()); + return true; +} + +bool utf8_to_wcs(const char* input, wstring* out) { + return mbs_to_wcs(input, out, true); +} + +bool wcs_to_utf8(const wchar_t* input, string* out) { + return wcs_to_mbs(input, out, true); +} + +} // namespace strings +} // namespace win32 +} // namespace io +} // namespace protobuf +} // namespace google + +#endif // defined(_WIN32) diff --git a/toolkit/components/protobuf/src/google/protobuf/io/io_win32.h b/toolkit/components/protobuf/src/google/protobuf/io/io_win32.h new file mode 100644 index 0000000000..a72b4ea3cf --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/io/io_win32.h @@ -0,0 +1,141 @@ +// 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. + +// Author: laszlocsomor@google.com (Laszlo Csomor) +// Based on original Protocol Buffers design by +// Sanjay Ghemawat, Jeff Dean, and others. + +// This file contains the declarations for Windows implementations of +// commonly used POSIX functions such as open(2) and access(2), as well +// as macro definitions for flags of these functions. +// +// By including this file you'll redefine open/access/etc. to +// ::google::protobuf::io::win32::{open/access/etc.}. +// Make sure you don't include a header that attempts to redeclare or +// redefine these functions, that'll lead to confusing compilation +// errors. It's best to #include this file as the last one to ensure that. +// +// This file is only used on Windows, it's empty on other platforms. + +#ifndef GOOGLE_PROTOBUF_IO_IO_WIN32_H__ +#define GOOGLE_PROTOBUF_IO_IO_WIN32_H__ + +#if defined(_WIN32) + +#include <functional> +#include <string> + +#include <google/protobuf/port.h> + +// Must be included last. +#include <google/protobuf/port_def.inc> + +// Compilers on Windows other than MSVC (e.g. Cygwin, MinGW32) define the +// following functions already, except for mkdir. +namespace google { +namespace protobuf { +namespace io { +namespace win32 { + +PROTOBUF_EXPORT FILE* fopen(const char* path, const char* mode); +PROTOBUF_EXPORT int access(const char* path, int mode); +PROTOBUF_EXPORT int chdir(const char* path); +PROTOBUF_EXPORT int close(int fd); +PROTOBUF_EXPORT int dup(int fd); +PROTOBUF_EXPORT int dup2(int fd1, int fd2); +PROTOBUF_EXPORT int mkdir(const char* path, int _mode); +PROTOBUF_EXPORT int open(const char* path, int flags, int mode = 0); +PROTOBUF_EXPORT int read(int fd, void* buffer, size_t size); +PROTOBUF_EXPORT int setmode(int fd, int mode); +PROTOBUF_EXPORT int stat(const char* path, struct _stat* buffer); +PROTOBUF_EXPORT int write(int fd, const void* buffer, size_t size); +PROTOBUF_EXPORT std::wstring testonly_utf8_to_winpath(const char* path); + +enum class ExpandWildcardsResult { + kSuccess = 0, + kErrorNoMatchingFile = 1, + kErrorInputPathConversion = 2, + kErrorOutputPathConversion = 3, +}; + +// Expand wildcards in a path pattern, feed the result to a consumer function. +// +// `path` must be a valid, Windows-style path. It may be absolute, or relative +// to the current working directory, and it may contain wildcards ("*" and "?") +// in the last path segment. This function passes all matching file names to +// `consume`. The resulting paths may not be absolute nor normalized. +// +// The function returns a value from `ExpandWildcardsResult`. +PROTOBUF_EXPORT ExpandWildcardsResult ExpandWildcards( + const std::string& path, std::function<void(const std::string&)> consume); + +namespace strings { + +// Convert from UTF-16 to Active-Code-Page-encoded or to UTF-8-encoded text. +PROTOBUF_EXPORT bool wcs_to_mbs(const wchar_t* s, std::string* out, + bool outUtf8); + +// Convert from Active-Code-Page-encoded or UTF-8-encoded text to UTF-16. +PROTOBUF_EXPORT bool mbs_to_wcs(const char* s, std::wstring* out, bool inUtf8); + +// Convert from UTF-8-encoded text to UTF-16. +PROTOBUF_EXPORT bool utf8_to_wcs(const char* input, std::wstring* out); + +// Convert from UTF-16-encoded text to UTF-8. +PROTOBUF_EXPORT bool wcs_to_utf8(const wchar_t* input, std::string* out); + +} // namespace strings + +} // namespace win32 +} // namespace io +} // namespace protobuf +} // namespace google + +#ifndef W_OK +#define W_OK 02 // not defined by MSVC for whatever reason +#endif + +#ifndef F_OK +#define F_OK 00 // not defined by MSVC for whatever reason +#endif + +#ifndef STDIN_FILENO +#define STDIN_FILENO 0 +#endif + +#ifndef STDOUT_FILENO +#define STDOUT_FILENO 1 +#endif + +#include <google/protobuf/port_undef.inc> + +#endif // defined(_WIN32) + +#endif // GOOGLE_PROTOBUF_IO_IO_WIN32_H__ diff --git a/toolkit/components/protobuf/src/google/protobuf/io/package_info.h b/toolkit/components/protobuf/src/google/protobuf/io/package_info.h new file mode 100644 index 0000000000..46c3dac917 --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/io/package_info.h @@ -0,0 +1,53 @@ +// 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. + +// Author: kenton@google.com (Kenton Varda) +// Based on original Protocol Buffers design by +// Sanjay Ghemawat, Jeff Dean, and others. +// +// This file exists solely to document the google::protobuf::io namespace. +// It is not compiled into anything, but it may be read by an automated +// documentation generator. + +namespace google { +namespace protobuf { + +// Auxiliary classes used for I/O. +// +// The Protocol Buffer library uses the classes in this package to deal with +// I/O and encoding/decoding raw bytes. Most users will not need to +// deal with this package. However, users who want to adapt the system to +// work with their own I/O abstractions -- e.g., to allow Protocol Buffers +// to be read from a different kind of input stream without the need for a +// temporary buffer -- should take a closer look. +namespace io {} + +} // namespace protobuf +} // namespace google diff --git a/toolkit/components/protobuf/src/google/protobuf/io/printer.cc b/toolkit/components/protobuf/src/google/protobuf/io/printer.cc new file mode 100644 index 0000000000..47bd00b50a --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/io/printer.cc @@ -0,0 +1,403 @@ +// 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. + +// Author: kenton@google.com (Kenton Varda) +// Based on original Protocol Buffers design by +// Sanjay Ghemawat, Jeff Dean, and others. + +#include <google/protobuf/io/printer.h> + +#include <cctype> + +#include <google/protobuf/stubs/logging.h> +#include <google/protobuf/stubs/common.h> +#include <google/protobuf/io/zero_copy_stream.h> + +namespace google { +namespace protobuf { +namespace io { + +Printer::Printer(ZeroCopyOutputStream* output, char variable_delimiter) + : variable_delimiter_(variable_delimiter), + output_(output), + buffer_(NULL), + buffer_size_(0), + offset_(0), + at_start_of_line_(true), + failed_(false), + annotation_collector_(NULL) {} + +Printer::Printer(ZeroCopyOutputStream* output, char variable_delimiter, + AnnotationCollector* annotation_collector) + : variable_delimiter_(variable_delimiter), + output_(output), + buffer_(NULL), + buffer_size_(0), + offset_(0), + at_start_of_line_(true), + failed_(false), + annotation_collector_(annotation_collector) {} + +Printer::~Printer() { + // Only BackUp() if we invoked Next() at least once, and we have never failed. + // Note that we always call `Backup`, i.e. we call BackUp(0) as some output + // streams have buffered output, and BackUp() serves as a flush event in such + // implementations. + if (buffer_ != nullptr && !failed_) { + output_->BackUp(buffer_size_); + } +} + +bool Printer::GetSubstitutionRange(const char* varname, + std::pair<size_t, size_t>* range) { + std::map<std::string, std::pair<size_t, size_t> >::const_iterator iter = + substitutions_.find(varname); + if (iter == substitutions_.end()) { + GOOGLE_LOG(DFATAL) << " Undefined variable in annotation: " << varname; + return false; + } + if (iter->second.first > iter->second.second) { + GOOGLE_LOG(DFATAL) << " Variable used for annotation used multiple times: " + << varname; + return false; + } + *range = iter->second; + return true; +} + +void Printer::Annotate(const char* begin_varname, const char* end_varname, + const std::string& file_path, + const std::vector<int>& path) { + if (annotation_collector_ == NULL) { + // Can't generate signatures with this Printer. + return; + } + std::pair<size_t, size_t> begin, end; + if (!GetSubstitutionRange(begin_varname, &begin) || + !GetSubstitutionRange(end_varname, &end)) { + return; + } + if (begin.first > end.second) { + GOOGLE_LOG(DFATAL) << " Annotation has negative length from " << begin_varname + << " to " << end_varname; + } else { + annotation_collector_->AddAnnotation(begin.first, end.second, file_path, + path); + } +} + +void Printer::Print(const std::map<std::string, std::string>& variables, + const char* text) { + int size = strlen(text); + int pos = 0; // The number of bytes we've written so far. + substitutions_.clear(); + line_start_variables_.clear(); + + for (int i = 0; i < size; i++) { + if (text[i] == '\n') { + // Saw newline. If there is more text, we may need to insert an indent + // here. So, write what we have so far, including the '\n'. + WriteRaw(text + pos, i - pos + 1); + pos = i + 1; + + // Setting this true will cause the next WriteRaw() to insert an indent + // first. + at_start_of_line_ = true; + line_start_variables_.clear(); + + } else if (text[i] == variable_delimiter_) { + // Saw the start of a variable name. + + // Write what we have so far. + WriteRaw(text + pos, i - pos); + pos = i + 1; + + // Find closing delimiter. + const char* end = strchr(text + pos, variable_delimiter_); + if (end == NULL) { + GOOGLE_LOG(DFATAL) << " Unclosed variable name."; + end = text + pos; + } + int endpos = end - text; + + std::string varname(text + pos, endpos - pos); + if (varname.empty()) { + // Two delimiters in a row reduce to a literal delimiter character. + WriteRaw(&variable_delimiter_, 1); + } else { + // Replace with the variable's value. + std::map<std::string, std::string>::const_iterator iter = + variables.find(varname); + if (iter == variables.end()) { + GOOGLE_LOG(DFATAL) << " Undefined variable: " << varname; + } else { + if (at_start_of_line_ && iter->second.empty()) { + line_start_variables_.push_back(varname); + } + WriteRaw(iter->second.data(), iter->second.size()); + std::pair<std::map<std::string, std::pair<size_t, size_t> >::iterator, + bool> + inserted = substitutions_.insert(std::make_pair( + varname, + std::make_pair(offset_ - iter->second.size(), offset_))); + if (!inserted.second) { + // This variable was used multiple times. Make its span have + // negative length so we can detect it if it gets used in an + // annotation. + inserted.first->second = std::make_pair(1, 0); + } + } + } + + // Advance past this variable. + i = endpos; + pos = endpos + 1; + } + } + + // Write the rest. + WriteRaw(text + pos, size - pos); +} + +void Printer::Indent() { indent_ += " "; } + +void Printer::Outdent() { + if (indent_.empty()) { + GOOGLE_LOG(DFATAL) << " Outdent() without matching Indent()."; + return; + } + + indent_.resize(indent_.size() - 2); +} + +void Printer::PrintRaw(const std::string& data) { + WriteRaw(data.data(), data.size()); +} + +void Printer::PrintRaw(const char* data) { + if (failed_) return; + WriteRaw(data, strlen(data)); +} + +void Printer::WriteRaw(const char* data, int size) { + if (failed_) return; + if (size == 0) return; + + if (at_start_of_line_ && (size > 0) && (data[0] != '\n')) { + // Insert an indent. + at_start_of_line_ = false; + CopyToBuffer(indent_.data(), indent_.size()); + if (failed_) return; + // Fix up empty variables (e.g., "{") that should be annotated as + // coming after the indent. + for (std::vector<std::string>::iterator i = line_start_variables_.begin(); + i != line_start_variables_.end(); ++i) { + substitutions_[*i].first += indent_.size(); + substitutions_[*i].second += indent_.size(); + } + } + + // If we're going to write any data, clear line_start_variables_, since + // we've either updated them in the block above or they no longer refer to + // the current line. + line_start_variables_.clear(); + + CopyToBuffer(data, size); +} + +bool Printer::Next() { + do { + void* void_buffer; + if (!output_->Next(&void_buffer, &buffer_size_)) { + failed_ = true; + return false; + } + buffer_ = reinterpret_cast<char*>(void_buffer); + } while (buffer_size_ == 0); + return true; +} + +void Printer::CopyToBuffer(const char* data, int size) { + if (failed_) return; + if (size == 0) return; + + while (size > buffer_size_) { + // Data exceeds space in the buffer. Copy what we can and request a + // new buffer. + if (buffer_size_ > 0) { + memcpy(buffer_, data, buffer_size_); + offset_ += buffer_size_; + data += buffer_size_; + size -= buffer_size_; + } + void* void_buffer; + failed_ = !output_->Next(&void_buffer, &buffer_size_); + if (failed_) return; + buffer_ = reinterpret_cast<char*>(void_buffer); + } + + // Buffer is big enough to receive the data; copy it. + memcpy(buffer_, data, size); + buffer_ += size; + buffer_size_ -= size; + offset_ += size; +} + +void Printer::IndentIfAtStart() { + if (at_start_of_line_) { + CopyToBuffer(indent_.data(), indent_.size()); + at_start_of_line_ = false; + } +} + +void Printer::FormatInternal(const std::vector<std::string>& args, + const std::map<std::string, std::string>& vars, + const char* format) { + auto save = format; + int arg_index = 0; + std::vector<AnnotationCollector::Annotation> annotations; + while (*format) { + char c = *format++; + switch (c) { + case '$': + format = WriteVariable(args, vars, format, &arg_index, &annotations); + continue; + case '\n': + at_start_of_line_ = true; + line_start_variables_.clear(); + break; + default: + IndentIfAtStart(); + break; + } + push_back(c); + } + if (arg_index != static_cast<int>(args.size())) { + GOOGLE_LOG(FATAL) << " Unused arguments. " << save; + } + if (!annotations.empty()) { + GOOGLE_LOG(FATAL) << " Annotation range is not-closed, expect $}$. " << save; + } +} + +const char* Printer::WriteVariable( + const std::vector<std::string>& args, + const std::map<std::string, std::string>& vars, const char* format, + int* arg_index, std::vector<AnnotationCollector::Annotation>* annotations) { + auto start = format; + auto end = strchr(format, '$'); + if (!end) { + GOOGLE_LOG(FATAL) << " Unclosed variable name."; + } + format = end + 1; + if (end == start) { + // "$$" is an escape for just '$' + IndentIfAtStart(); + push_back('$'); + return format; + } + if (*start == '{') { + GOOGLE_CHECK(std::isdigit(start[1])); + GOOGLE_CHECK_EQ(end - start, 2); + int idx = start[1] - '1'; + if (idx < 0 || static_cast<size_t>(idx) >= args.size()) { + GOOGLE_LOG(FATAL) << "Annotation ${" << idx + 1 << "$ is out of bounds."; + } + if (idx > *arg_index) { + GOOGLE_LOG(FATAL) << "Annotation arg must be in correct order as given. Expected" + << " ${" << (*arg_index) + 1 << "$ got ${" << idx + 1 << "$."; + } else if (idx == *arg_index) { + (*arg_index)++; + } + IndentIfAtStart(); + annotations->push_back({{offset_, 0}, args[idx]}); + return format; + } else if (*start == '}') { + GOOGLE_CHECK(annotations); + if (annotations->empty()) { + GOOGLE_LOG(FATAL) << "Unexpected end of annotation found."; + } + auto& a = annotations->back(); + a.first.second = offset_; + if (annotation_collector_) annotation_collector_->AddAnnotationNew(a); + annotations->pop_back(); + return format; + } + auto start_var = start; + while (start_var < end && *start_var == ' ') start_var++; + if (start_var == end) { + GOOGLE_LOG(FATAL) << " Empty variable."; + } + auto end_var = end; + while (start_var < end_var && *(end_var - 1) == ' ') end_var--; + std::string var_name{ + start_var, static_cast<std::string::size_type>(end_var - start_var)}; + std::string sub; + if (std::isdigit(var_name[0])) { + GOOGLE_CHECK_EQ(var_name.size(), 1U); // No need for multi-digits + int idx = var_name[0] - '1'; // Start counting at 1 + GOOGLE_CHECK_GE(idx, 0); + if (static_cast<size_t>(idx) >= args.size()) { + GOOGLE_LOG(FATAL) << "Argument $" << idx + 1 << "$ is out of bounds."; + } + if (idx > *arg_index) { + GOOGLE_LOG(FATAL) << "Arguments must be used in same order as given. Expected $" + << (*arg_index) + 1 << "$ got $" << idx + 1 << "$."; + } else if (idx == *arg_index) { + (*arg_index)++; + } + sub = args[idx]; + } else { + auto it = vars.find(var_name); + if (it == vars.end()) { + GOOGLE_LOG(FATAL) << " Unknown variable: " << var_name << "."; + } + sub = it->second; + } + + // By returning here in case of empty we also skip possible spaces inside + // the $...$, i.e. "void$ dllexpor$ f();" -> "void f();" in the empty case. + if (sub.empty()) return format; + + // We're going to write something non-empty so we need a possible indent. + IndentIfAtStart(); + + // Write the possible spaces in front. + CopyToBuffer(start, start_var - start); + // Write a non-empty substituted variable. + CopyToBuffer(sub.c_str(), sub.size()); + // Finish off with writing possible trailing spaces. + CopyToBuffer(end_var, end - end_var); + return format; +} + +} // namespace io +} // namespace protobuf +} // namespace google diff --git a/toolkit/components/protobuf/src/google/protobuf/io/printer.h b/toolkit/components/protobuf/src/google/protobuf/io/printer.h new file mode 100644 index 0000000000..92a4321c04 --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/io/printer.h @@ -0,0 +1,387 @@ +// 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. + +// Author: kenton@google.com (Kenton Varda) +// Based on original Protocol Buffers design by +// Sanjay Ghemawat, Jeff Dean, and others. +// +// Utility class for writing text to a ZeroCopyOutputStream. + +#ifndef GOOGLE_PROTOBUF_IO_PRINTER_H__ +#define GOOGLE_PROTOBUF_IO_PRINTER_H__ + + +#include <map> +#include <string> +#include <vector> + +#include <google/protobuf/stubs/common.h> + +// Must be included last. +#include <google/protobuf/port_def.inc> + +namespace google { +namespace protobuf { +namespace io { + +class ZeroCopyOutputStream; // zero_copy_stream.h + +// Records annotations about a Printer's output. +class PROTOBUF_EXPORT AnnotationCollector { + public: + // Annotation is a offset range and a payload pair. + typedef std::pair<std::pair<size_t, size_t>, std::string> Annotation; + + // Records that the bytes in file_path beginning with begin_offset and ending + // before end_offset are associated with the SourceCodeInfo-style path. + virtual void AddAnnotation(size_t begin_offset, size_t end_offset, + const std::string& file_path, + const std::vector<int>& path) = 0; + + // TODO(gerbens) I don't see why we need virtuals here. Just a vector of + // range, payload pairs stored in a context should suffice. + virtual void AddAnnotationNew(Annotation& /* a */) {} + + virtual ~AnnotationCollector() {} +}; + +// Records annotations about a Printer's output to the given protocol buffer, +// assuming that the buffer has an ::Annotation message exposing path, +// source_file, begin and end fields. +template <typename AnnotationProto> +class AnnotationProtoCollector : public AnnotationCollector { + public: + // annotation_proto is the protocol buffer to which new Annotations should be + // added. It is not owned by the AnnotationProtoCollector. + explicit AnnotationProtoCollector(AnnotationProto* annotation_proto) + : annotation_proto_(annotation_proto) {} + + // Override for AnnotationCollector::AddAnnotation. + void AddAnnotation(size_t begin_offset, size_t end_offset, + const std::string& file_path, + const std::vector<int>& path) override { + typename AnnotationProto::Annotation* annotation = + annotation_proto_->add_annotation(); + for (int i = 0; i < path.size(); ++i) { + annotation->add_path(path[i]); + } + annotation->set_source_file(file_path); + annotation->set_begin(begin_offset); + annotation->set_end(end_offset); + } + // Override for AnnotationCollector::AddAnnotation. + void AddAnnotationNew(Annotation& a) override { + auto* annotation = annotation_proto_->add_annotation(); + annotation->ParseFromString(a.second); + annotation->set_begin(a.first.first); + annotation->set_end(a.first.second); + } + + private: + // The protocol buffer to which new annotations should be added. + AnnotationProto* const annotation_proto_; +}; + +// This simple utility class assists in code generation. It basically +// allows the caller to define a set of variables and then output some +// text with variable substitutions. Example usage: +// +// Printer printer(output, '$'); +// map<string, string> vars; +// vars["name"] = "Bob"; +// printer.Print(vars, "My name is $name$."); +// +// The above writes "My name is Bob." to the output stream. +// +// Printer aggressively enforces correct usage, crashing (with assert failures) +// in the case of undefined variables in debug builds. This helps greatly in +// debugging code which uses it. +// +// If a Printer is constructed with an AnnotationCollector, it will provide it +// with annotations that connect the Printer's output to paths that can identify +// various descriptors. In the above example, if person_ is a descriptor that +// identifies Bob, we can associate the output string "My name is Bob." with +// a source path pointing to that descriptor with: +// +// printer.Annotate("name", person_); +// +// The AnnotationCollector will be sent an annotation linking the output range +// covering "Bob" to the logical path provided by person_. Tools may use +// this association to (for example) link "Bob" in the output back to the +// source file that defined the person_ descriptor identifying Bob. +// +// Annotate can only examine variables substituted during the last call to +// Print. It is invalid to refer to a variable that was used multiple times +// in a single Print call. +// +// In full generality, one may specify a range of output text using a beginning +// substitution variable and an ending variable. The resulting annotation will +// span from the first character of the substituted value for the beginning +// variable to the last character of the substituted value for the ending +// variable. For example, the Annotate call above is equivalent to this one: +// +// printer.Annotate("name", "name", person_); +// +// This is useful if multiple variables combine to form a single span of output +// that should be annotated with the same source path. For example: +// +// Printer printer(output, '$'); +// map<string, string> vars; +// vars["first"] = "Alice"; +// vars["last"] = "Smith"; +// printer.Print(vars, "My name is $first$ $last$."); +// printer.Annotate("first", "last", person_); +// +// This code would associate the span covering "Alice Smith" in the output with +// the person_ descriptor. +// +// Note that the beginning variable must come before (or overlap with, in the +// case of zero-sized substitution values) the ending variable. +// +// It is also sometimes useful to use variables with zero-sized values as +// markers. This avoids issues with multiple references to the same variable +// and also allows annotation ranges to span literal text from the Print +// templates: +// +// Printer printer(output, '$'); +// map<string, string> vars; +// vars["foo"] = "bar"; +// vars["function"] = "call"; +// vars["mark"] = ""; +// printer.Print(vars, "$function$($foo$,$foo$)$mark$"); +// printer.Annotate("function", "mark", call_); +// +// This code associates the span covering "call(bar,bar)" in the output with the +// call_ descriptor. + +class PROTOBUF_EXPORT Printer { + public: + // Create a printer that writes text to the given output stream. Use the + // given character as the delimiter for variables. + Printer(ZeroCopyOutputStream* output, char variable_delimiter); + + // Create a printer that writes text to the given output stream. Use the + // given character as the delimiter for variables. If annotation_collector + // is not null, Printer will provide it with annotations about code written + // to the stream. annotation_collector is not owned by Printer. + Printer(ZeroCopyOutputStream* output, char variable_delimiter, + AnnotationCollector* annotation_collector); + + ~Printer(); + + // Link a substitution variable emitted by the last call to Print to the + // object described by descriptor. + template <typename SomeDescriptor> + void Annotate(const char* varname, const SomeDescriptor* descriptor) { + Annotate(varname, varname, descriptor); + } + + // Link the output range defined by the substitution variables as emitted by + // the last call to Print to the object described by descriptor. The range + // begins at begin_varname's value and ends after the last character of the + // value substituted for end_varname. + template <typename SomeDescriptor> + void Annotate(const char* begin_varname, const char* end_varname, + const SomeDescriptor* descriptor) { + if (annotation_collector_ == NULL) { + // Annotations aren't turned on for this Printer, so don't pay the cost + // of building the location path. + return; + } + std::vector<int> path; + descriptor->GetLocationPath(&path); + Annotate(begin_varname, end_varname, descriptor->file()->name(), path); + } + + // Link a substitution variable emitted by the last call to Print to the file + // with path file_name. + void Annotate(const char* varname, const std::string& file_name) { + Annotate(varname, varname, file_name); + } + + // Link the output range defined by the substitution variables as emitted by + // the last call to Print to the file with path file_name. The range begins + // at begin_varname's value and ends after the last character of the value + // substituted for end_varname. + void Annotate(const char* begin_varname, const char* end_varname, + const std::string& file_name) { + if (annotation_collector_ == NULL) { + // Annotations aren't turned on for this Printer. + return; + } + std::vector<int> empty_path; + Annotate(begin_varname, end_varname, file_name, empty_path); + } + + // Print some text after applying variable substitutions. If a particular + // variable in the text is not defined, this will crash. Variables to be + // substituted are identified by their names surrounded by delimiter + // characters (as given to the constructor). The variable bindings are + // defined by the given map. + void Print(const std::map<std::string, std::string>& variables, + const char* text); + + // Like the first Print(), except the substitutions are given as parameters. + template <typename... Args> + void Print(const char* text, const Args&... args) { + std::map<std::string, std::string> vars; + PrintInternal(&vars, text, args...); + } + + // Indent text by two spaces. After calling Indent(), two spaces will be + // inserted at the beginning of each line of text. Indent() may be called + // multiple times to produce deeper indents. + void Indent(); + + // Reduces the current indent level by two spaces, or crashes if the indent + // level is zero. + void Outdent(); + + // Write a string to the output buffer. + // This method does not look for newlines to add indentation. + void PrintRaw(const std::string& data); + + // Write a zero-delimited string to output buffer. + // This method does not look for newlines to add indentation. + void PrintRaw(const char* data); + + // Write some bytes to the output buffer. + // This method does not look for newlines to add indentation. + void WriteRaw(const char* data, int size); + + // FormatInternal is a helper function not meant to use directly, use + // compiler::cpp::Formatter instead. This function is meant to support + // formatting text using named variables (eq. "$foo$) from a lookup map (vars) + // and variables directly supplied by arguments (eq "$1$" meaning first + // argument which is the zero index element of args). + void FormatInternal(const std::vector<std::string>& args, + const std::map<std::string, std::string>& vars, + const char* format); + + // True if any write to the underlying stream failed. (We don't just + // crash in this case because this is an I/O failure, not a programming + // error.) + bool failed() const { return failed_; } + + private: + // Link the output range defined by the substitution variables as emitted by + // the last call to Print to the object found at the SourceCodeInfo-style path + // in a file with path file_path. The range begins at the start of + // begin_varname's value and ends after the last character of the value + // substituted for end_varname. Note that begin_varname and end_varname + // may refer to the same variable. + void Annotate(const char* begin_varname, const char* end_varname, + const std::string& file_path, const std::vector<int>& path); + + // Base case + void PrintInternal(std::map<std::string, std::string>* vars, + const char* text) { + Print(*vars, text); + } + + template <typename... Args> + void PrintInternal(std::map<std::string, std::string>* vars, const char* text, + const char* key, const std::string& value, + const Args&... args) { + (*vars)[key] = value; + PrintInternal(vars, text, args...); + } + + // Copy size worth of bytes from data to buffer_. + void CopyToBuffer(const char* data, int size); + + void push_back(char c) { + if (failed_) return; + if (buffer_size_ == 0) { + if (!Next()) return; + } + *buffer_++ = c; + buffer_size_--; + offset_++; + } + + bool Next(); + + inline void IndentIfAtStart(); + const char* WriteVariable( + const std::vector<std::string>& args, + const std::map<std::string, std::string>& vars, const char* format, + int* arg_index, + std::vector<AnnotationCollector::Annotation>* annotations); + + const char variable_delimiter_; + + ZeroCopyOutputStream* const output_; + char* buffer_; + int buffer_size_; + // The current position, in bytes, in the output stream. This is equivalent + // to the total number of bytes that have been written so far. This value is + // used to calculate annotation ranges in the substitutions_ map below. + size_t offset_; + + std::string indent_; + bool at_start_of_line_; + bool failed_; + + // A map from variable name to [start, end) offsets in the output buffer. + // These refer to the offsets used for a variable after the last call to + // Print. If a variable was used more than once, the entry used in + // this map is set to a negative-length span. For singly-used variables, the + // start offset is the beginning of the substitution; the end offset is the + // last byte of the substitution plus one (such that (end - start) is the + // length of the substituted string). + std::map<std::string, std::pair<size_t, size_t> > substitutions_; + + // Keeps track of the keys in substitutions_ that need to be updated when + // indents are inserted. These are keys that refer to the beginning of the + // current line. + std::vector<std::string> line_start_variables_; + + // Returns true and sets range to the substitution range in the output for + // varname if varname was used once in the last call to Print. If varname + // was not used, or if it was used multiple times, returns false (and + // fails a debug assertion). + bool GetSubstitutionRange(const char* varname, + std::pair<size_t, size_t>* range); + + // If non-null, annotation_collector_ is used to store annotations about + // generated code. + AnnotationCollector* const annotation_collector_; + + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Printer); +}; + +} // namespace io +} // namespace protobuf +} // namespace google + +#include <google/protobuf/port_undef.inc> + +#endif // GOOGLE_PROTOBUF_IO_PRINTER_H__ diff --git a/toolkit/components/protobuf/src/google/protobuf/io/strtod.cc b/toolkit/components/protobuf/src/google/protobuf/io/strtod.cc new file mode 100644 index 0000000000..03acb5b294 --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/io/strtod.cc @@ -0,0 +1,82 @@ +// 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. + +#include <google/protobuf/io/strtod.h> + +#include <cstdio> +#include <cstring> +#include <limits> +#include <string> + +#include <google/protobuf/stubs/logging.h> +#include <google/protobuf/stubs/common.h> + +#include <google/protobuf/stubs/strutil.h> + +namespace google { +namespace protobuf { +namespace io { + +// This approximately 0x1.ffffffp127, but we don't use 0x1.ffffffp127 because +// it won't compile in MSVC. +const double MAX_FLOAT_AS_DOUBLE_ROUNDED = 3.4028235677973366e+38; + +float SafeDoubleToFloat(double value) { + // static_cast<float> on a number larger than float can result in illegal + // instruction error, so we need to manually convert it to infinity or max. + if (value > std::numeric_limits<float>::max()) { + // Max float value is about 3.4028234664E38 when represented as a double. + // However, when printing float as text, it will be rounded as + // 3.4028235e+38. If we parse the value of 3.4028235e+38 from text and + // compare it to 3.4028234664E38, we may think that it is larger, but + // actually, any number between these two numbers could only be represented + // as the same max float number in float, so we should treat them the same + // as max float. + if (value <= MAX_FLOAT_AS_DOUBLE_ROUNDED) { + return std::numeric_limits<float>::max(); + } + return std::numeric_limits<float>::infinity(); + } else if (value < -std::numeric_limits<float>::max()) { + if (value >= -MAX_FLOAT_AS_DOUBLE_ROUNDED) { + return -std::numeric_limits<float>::max(); + } + return -std::numeric_limits<float>::infinity(); + } else { + return static_cast<float>(value); + } +} + +double NoLocaleStrtod(const char* str, char** endptr) { + return google::protobuf::internal::NoLocaleStrtod(str, endptr); +} + +} // namespace io +} // namespace protobuf +} // namespace google diff --git a/toolkit/components/protobuf/src/google/protobuf/io/strtod.h b/toolkit/components/protobuf/src/google/protobuf/io/strtod.h new file mode 100644 index 0000000000..38f544af34 --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/io/strtod.h @@ -0,0 +1,55 @@ +// 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. + +// A locale-independent version of strtod(), used to parse floating +// point default values in .proto files, where the decimal separator +// is always a dot. + +#ifndef GOOGLE_PROTOBUF_IO_STRTOD_H__ +#define GOOGLE_PROTOBUF_IO_STRTOD_H__ + +namespace google { +namespace protobuf { +namespace io { + +// A locale-independent version of the standard strtod(), which always +// uses a dot as the decimal separator. +double NoLocaleStrtod(const char* str, char** endptr); + +// Casts a double value to a float value. If the value is outside of the +// representable range of float, it will be converted to positive or negative +// infinity. +float SafeDoubleToFloat(double value); + +} // namespace io +} // namespace protobuf +} // namespace google + +#endif // GOOGLE_PROTOBUF_IO_STRTOD_H__ diff --git a/toolkit/components/protobuf/src/google/protobuf/io/tokenizer.cc b/toolkit/components/protobuf/src/google/protobuf/io/tokenizer.cc new file mode 100644 index 0000000000..f9e07763e7 --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/io/tokenizer.cc @@ -0,0 +1,1239 @@ +// 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. + +// Author: kenton@google.com (Kenton Varda) +// Based on original Protocol Buffers design by +// Sanjay Ghemawat, Jeff Dean, and others. +// +// Here we have a hand-written lexer. At first you might ask yourself, +// "Hand-written text processing? Is Kenton crazy?!" Well, first of all, +// yes I am crazy, but that's beside the point. There are actually reasons +// why I ended up writing this this way. +// +// The traditional approach to lexing is to use lex to generate a lexer for +// you. Unfortunately, lex's output is ridiculously ugly and difficult to +// integrate cleanly with C++ code, especially abstract code or code meant +// as a library. Better parser-generators exist but would add dependencies +// which most users won't already have, which we'd like to avoid. (GNU flex +// has a C++ output option, but it's still ridiculously ugly, non-abstract, +// and not library-friendly.) +// +// The next approach that any good software engineer should look at is to +// use regular expressions. And, indeed, I did. I have code which +// implements this same class using regular expressions. It's about 200 +// lines shorter. However: +// - Rather than error messages telling you "This string has an invalid +// escape sequence at line 5, column 45", you get error messages like +// "Parse error on line 5". Giving more precise errors requires adding +// a lot of code that ends up basically as complex as the hand-coded +// version anyway. +// - The regular expression to match a string literal looks like this: +// kString = new RE("(\"([^\"\\\\]|" // non-escaped +// "\\\\[abfnrtv?\"'\\\\0-7]|" // normal escape +// "\\\\x[0-9a-fA-F])*\"|" // hex escape +// "\'([^\'\\\\]|" // Also support single-quotes. +// "\\\\[abfnrtv?\"'\\\\0-7]|" +// "\\\\x[0-9a-fA-F])*\')"); +// Verifying the correctness of this line noise is actually harder than +// verifying the correctness of ConsumeString(), defined below. I'm not +// even confident that the above is correct, after staring at it for some +// time. +// - PCRE is fast, but there's still more overhead involved than the code +// below. +// - Sadly, regular expressions are not part of the C standard library, so +// using them would require depending on some other library. For the +// open source release, this could be really annoying. Nobody likes +// downloading one piece of software just to find that they need to +// download something else to make it work, and in all likelihood +// people downloading Protocol Buffers will already be doing so just +// to make something else work. We could include a copy of PCRE with +// our code, but that obligates us to keep it up-to-date and just seems +// like a big waste just to save 200 lines of code. +// +// On a similar but unrelated note, I'm even scared to use ctype.h. +// Apparently functions like isalpha() are locale-dependent. So, if we used +// that, then if this code is being called from some program that doesn't +// have its locale set to "C", it would behave strangely. We can't just set +// the locale to "C" ourselves since we might break the calling program that +// way, particularly if it is multi-threaded. WTF? Someone please let me +// (Kenton) know if I'm missing something here... +// +// I'd love to hear about other alternatives, though, as this code isn't +// exactly pretty. + +#include <google/protobuf/io/tokenizer.h> + +#include <google/protobuf/stubs/common.h> +#include <google/protobuf/stubs/logging.h> +#include <google/protobuf/stubs/strutil.h> +#include <google/protobuf/stubs/stringprintf.h> +#include <google/protobuf/io/strtod.h> +#include <google/protobuf/io/zero_copy_stream.h> +#include <google/protobuf/stubs/stl_util.h> + +// Must be included last. +#include <google/protobuf/port_def.inc> + +namespace google { +namespace protobuf { +namespace io { +namespace { + +// As mentioned above, I don't trust ctype.h due to the presence of "locales". +// So, I have written replacement functions here. Someone please smack me if +// this is a bad idea or if there is some way around this. +// +// These "character classes" are designed to be used in template methods. +// For instance, Tokenizer::ConsumeZeroOrMore<Whitespace>() will eat +// whitespace. + +// Note: No class is allowed to contain '\0', since this is used to mark end- +// of-input and is handled specially. + +#define CHARACTER_CLASS(NAME, EXPRESSION) \ + class NAME { \ + public: \ + static inline bool InClass(char c) { return EXPRESSION; } \ + } + +CHARACTER_CLASS(Whitespace, c == ' ' || c == '\n' || c == '\t' || c == '\r' || + c == '\v' || c == '\f'); +CHARACTER_CLASS(WhitespaceNoNewline, + c == ' ' || c == '\t' || c == '\r' || c == '\v' || c == '\f'); + +CHARACTER_CLASS(Unprintable, c<' ' && c> '\0'); + +CHARACTER_CLASS(Digit, '0' <= c && c <= '9'); +CHARACTER_CLASS(OctalDigit, '0' <= c && c <= '7'); +CHARACTER_CLASS(HexDigit, ('0' <= c && c <= '9') || ('a' <= c && c <= 'f') || + ('A' <= c && c <= 'F')); + +CHARACTER_CLASS(Letter, + ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z') || (c == '_')); + +CHARACTER_CLASS(Alphanumeric, ('a' <= c && c <= 'z') || + ('A' <= c && c <= 'Z') || + ('0' <= c && c <= '9') || (c == '_')); + +CHARACTER_CLASS(Escape, c == 'a' || c == 'b' || c == 'f' || c == 'n' || + c == 'r' || c == 't' || c == 'v' || c == '\\' || + c == '?' || c == '\'' || c == '\"'); + +#undef CHARACTER_CLASS + +// Given a char, interpret it as a numeric digit and return its value. +// This supports any number base up to 36. +// Represents integer values of digits. +// Uses 36 to indicate an invalid character since we support +// bases up to 36. +static const int8_t kAsciiToInt[256] = { + 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, // 00-0F + 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, // 10-1F + 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, // ' '-'/' + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, // '0'-'9' + 36, 36, 36, 36, 36, 36, 36, // ':'-'@' + 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, // 'A'-'P' + 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, // 'Q'-'Z' + 36, 36, 36, 36, 36, 36, // '['-'`' + 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, // 'a'-'p' + 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, // 'q'-'z' + 36, 36, 36, 36, 36, // '{'-DEL + 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, // 80-8F + 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, // 90-9F + 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, // A0-AF + 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, // B0-BF + 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, // C0-CF + 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, // D0-DF + 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, // E0-EF + 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, // F0-FF +}; + +inline int DigitValue(char digit) { return kAsciiToInt[digit & 0xFF]; } + +// Inline because it's only used in one place. +inline char TranslateEscape(char c) { + switch (c) { + case 'a': + return '\a'; + case 'b': + return '\b'; + case 'f': + return '\f'; + case 'n': + return '\n'; + case 'r': + return '\r'; + case 't': + return '\t'; + case 'v': + return '\v'; + case '\\': + return '\\'; + case '?': + return '\?'; // Trigraphs = :( + case '\'': + return '\''; + case '"': + return '\"'; + + // We expect escape sequences to have been validated separately. + default: + return '?'; + } +} + +} // anonymous namespace + +ErrorCollector::~ErrorCollector() {} + +// =================================================================== + +Tokenizer::Tokenizer(ZeroCopyInputStream* input, + ErrorCollector* error_collector) + : input_(input), + error_collector_(error_collector), + buffer_(NULL), + buffer_size_(0), + buffer_pos_(0), + read_error_(false), + line_(0), + column_(0), + record_target_(NULL), + record_start_(-1), + allow_f_after_float_(false), + comment_style_(CPP_COMMENT_STYLE), + require_space_after_number_(true), + allow_multiline_strings_(false) { + current_.line = 0; + current_.column = 0; + current_.end_column = 0; + current_.type = TYPE_START; + + Refresh(); +} + +Tokenizer::~Tokenizer() { + // If we had any buffer left unread, return it to the underlying stream + // so that someone else can read it. + if (buffer_size_ > buffer_pos_) { + input_->BackUp(buffer_size_ - buffer_pos_); + } +} + +bool Tokenizer::report_whitespace() const { return report_whitespace_; } +// Note: `set_report_whitespace(false)` implies `set_report_newlines(false)`. +void Tokenizer::set_report_whitespace(bool report) { + report_whitespace_ = report; + report_newlines_ &= report; +} + +// If true, newline tokens are reported by Next(). +bool Tokenizer::report_newlines() const { return report_newlines_; } +// Note: `set_report_newlines(true)` implies `set_report_whitespace(true)`. +void Tokenizer::set_report_newlines(bool report) { + report_newlines_ = report; + report_whitespace_ |= report; // enable report_whitespace if necessary +} + +// ------------------------------------------------------------------- +// Internal helpers. + +void Tokenizer::NextChar() { + // Update our line and column counters based on the character being + // consumed. + if (current_char_ == '\n') { + ++line_; + column_ = 0; + } else if (current_char_ == '\t') { + column_ += kTabWidth - column_ % kTabWidth; + } else { + ++column_; + } + + // Advance to the next character. + ++buffer_pos_; + if (buffer_pos_ < buffer_size_) { + current_char_ = buffer_[buffer_pos_]; + } else { + Refresh(); + } +} + +void Tokenizer::Refresh() { + if (read_error_) { + current_char_ = '\0'; + return; + } + + // If we're in a token, append the rest of the buffer to it. + if (record_target_ != NULL && record_start_ < buffer_size_) { + record_target_->append(buffer_ + record_start_, + buffer_size_ - record_start_); + record_start_ = 0; + } + + const void* data = NULL; + buffer_ = NULL; + buffer_pos_ = 0; + do { + if (!input_->Next(&data, &buffer_size_)) { + // end of stream (or read error) + buffer_size_ = 0; + read_error_ = true; + current_char_ = '\0'; + return; + } + } while (buffer_size_ == 0); + + buffer_ = static_cast<const char*>(data); + + current_char_ = buffer_[0]; +} + +inline void Tokenizer::RecordTo(std::string* target) { + record_target_ = target; + record_start_ = buffer_pos_; +} + +inline void Tokenizer::StopRecording() { + // Note: The if() is necessary because some STL implementations crash when + // you call string::append(NULL, 0), presumably because they are trying to + // be helpful by detecting the NULL pointer, even though there's nothing + // wrong with reading zero bytes from NULL. + if (buffer_pos_ != record_start_) { + record_target_->append(buffer_ + record_start_, + buffer_pos_ - record_start_); + } + record_target_ = NULL; + record_start_ = -1; +} + +inline void Tokenizer::StartToken() { + current_.type = TYPE_START; // Just for the sake of initializing it. + current_.text.clear(); + current_.line = line_; + current_.column = column_; + RecordTo(¤t_.text); +} + +inline void Tokenizer::EndToken() { + StopRecording(); + current_.end_column = column_; +} + +// ------------------------------------------------------------------- +// Helper methods that consume characters. + +template <typename CharacterClass> +inline bool Tokenizer::LookingAt() { + return CharacterClass::InClass(current_char_); +} + +template <typename CharacterClass> +inline bool Tokenizer::TryConsumeOne() { + if (CharacterClass::InClass(current_char_)) { + NextChar(); + return true; + } else { + return false; + } +} + +inline bool Tokenizer::TryConsume(char c) { + if (current_char_ == c) { + NextChar(); + return true; + } else { + return false; + } +} + +template <typename CharacterClass> +inline void Tokenizer::ConsumeZeroOrMore() { + while (CharacterClass::InClass(current_char_)) { + NextChar(); + } +} + +template <typename CharacterClass> +inline void Tokenizer::ConsumeOneOrMore(const char* error) { + if (!CharacterClass::InClass(current_char_)) { + AddError(error); + } else { + do { + NextChar(); + } while (CharacterClass::InClass(current_char_)); + } +} + +// ------------------------------------------------------------------- +// Methods that read whole patterns matching certain kinds of tokens +// or comments. + +void Tokenizer::ConsumeString(char delimiter) { + while (true) { + switch (current_char_) { + case '\0': + AddError("Unexpected end of string."); + return; + + case '\n': { + if (!allow_multiline_strings_) { + AddError("String literals cannot cross line boundaries."); + return; + } + NextChar(); + break; + } + + case '\\': { + // An escape sequence. + NextChar(); + if (TryConsumeOne<Escape>()) { + // Valid escape sequence. + } else if (TryConsumeOne<OctalDigit>()) { + // Possibly followed by two more octal digits, but these will + // just be consumed by the main loop anyway so we don't need + // to do so explicitly here. + } else if (TryConsume('x')) { + if (!TryConsumeOne<HexDigit>()) { + AddError("Expected hex digits for escape sequence."); + } + // Possibly followed by another hex digit, but again we don't care. + } else if (TryConsume('u')) { + if (!TryConsumeOne<HexDigit>() || !TryConsumeOne<HexDigit>() || + !TryConsumeOne<HexDigit>() || !TryConsumeOne<HexDigit>()) { + AddError("Expected four hex digits for \\u escape sequence."); + } + } else if (TryConsume('U')) { + // We expect 8 hex digits; but only the range up to 0x10ffff is + // legal. + if (!TryConsume('0') || !TryConsume('0') || + !(TryConsume('0') || TryConsume('1')) || + !TryConsumeOne<HexDigit>() || !TryConsumeOne<HexDigit>() || + !TryConsumeOne<HexDigit>() || !TryConsumeOne<HexDigit>() || + !TryConsumeOne<HexDigit>()) { + AddError( + "Expected eight hex digits up to 10ffff for \\U escape " + "sequence"); + } + } else { + AddError("Invalid escape sequence in string literal."); + } + break; + } + + default: { + if (current_char_ == delimiter) { + NextChar(); + return; + } + NextChar(); + break; + } + } + } +} + +Tokenizer::TokenType Tokenizer::ConsumeNumber(bool started_with_zero, + bool started_with_dot) { + bool is_float = false; + + if (started_with_zero && (TryConsume('x') || TryConsume('X'))) { + // A hex number (started with "0x"). + ConsumeOneOrMore<HexDigit>("\"0x\" must be followed by hex digits."); + + } else if (started_with_zero && LookingAt<Digit>()) { + // An octal number (had a leading zero). + ConsumeZeroOrMore<OctalDigit>(); + if (LookingAt<Digit>()) { + AddError("Numbers starting with leading zero must be in octal."); + ConsumeZeroOrMore<Digit>(); + } + + } else { + // A decimal number. + if (started_with_dot) { + is_float = true; + ConsumeZeroOrMore<Digit>(); + } else { + ConsumeZeroOrMore<Digit>(); + + if (TryConsume('.')) { + is_float = true; + ConsumeZeroOrMore<Digit>(); + } + } + + if (TryConsume('e') || TryConsume('E')) { + is_float = true; + TryConsume('-') || TryConsume('+'); + ConsumeOneOrMore<Digit>("\"e\" must be followed by exponent."); + } + + if (allow_f_after_float_ && (TryConsume('f') || TryConsume('F'))) { + is_float = true; + } + } + + if (LookingAt<Letter>() && require_space_after_number_) { + AddError("Need space between number and identifier."); + } else if (current_char_ == '.') { + if (is_float) { + AddError( + "Already saw decimal point or exponent; can't have another one."); + } else { + AddError("Hex and octal numbers must be integers."); + } + } + + return is_float ? TYPE_FLOAT : TYPE_INTEGER; +} + +void Tokenizer::ConsumeLineComment(std::string* content) { + if (content != NULL) RecordTo(content); + + while (current_char_ != '\0' && current_char_ != '\n') { + NextChar(); + } + TryConsume('\n'); + + if (content != NULL) StopRecording(); +} + +void Tokenizer::ConsumeBlockComment(std::string* content) { + int start_line = line_; + int start_column = column_ - 2; + + if (content != NULL) RecordTo(content); + + while (true) { + while (current_char_ != '\0' && current_char_ != '*' && + current_char_ != '/' && current_char_ != '\n') { + NextChar(); + } + + if (TryConsume('\n')) { + if (content != NULL) StopRecording(); + + // Consume leading whitespace and asterisk; + ConsumeZeroOrMore<WhitespaceNoNewline>(); + if (TryConsume('*')) { + if (TryConsume('/')) { + // End of comment. + break; + } + } + + if (content != NULL) RecordTo(content); + } else if (TryConsume('*') && TryConsume('/')) { + // End of comment. + if (content != NULL) { + StopRecording(); + // Strip trailing "*/". + content->erase(content->size() - 2); + } + break; + } else if (TryConsume('/') && current_char_ == '*') { + // Note: We didn't consume the '*' because if there is a '/' after it + // we want to interpret that as the end of the comment. + AddError( + "\"/*\" inside block comment. Block comments cannot be nested."); + } else if (current_char_ == '\0') { + AddError("End-of-file inside block comment."); + error_collector_->AddError(start_line, start_column, + " Comment started here."); + if (content != NULL) StopRecording(); + break; + } + } +} + +Tokenizer::NextCommentStatus Tokenizer::TryConsumeCommentStart() { + if (comment_style_ == CPP_COMMENT_STYLE && TryConsume('/')) { + if (TryConsume('/')) { + return LINE_COMMENT; + } else if (TryConsume('*')) { + return BLOCK_COMMENT; + } else { + // Oops, it was just a slash. Return it. + current_.type = TYPE_SYMBOL; + current_.text = "/"; + current_.line = line_; + current_.column = column_ - 1; + current_.end_column = column_; + return SLASH_NOT_COMMENT; + } + } else if (comment_style_ == SH_COMMENT_STYLE && TryConsume('#')) { + return LINE_COMMENT; + } else { + return NO_COMMENT; + } +} + +bool Tokenizer::TryConsumeWhitespace() { + if (report_newlines_) { + if (TryConsumeOne<WhitespaceNoNewline>()) { + ConsumeZeroOrMore<WhitespaceNoNewline>(); + current_.type = TYPE_WHITESPACE; + return true; + } + return false; + } + if (TryConsumeOne<Whitespace>()) { + ConsumeZeroOrMore<Whitespace>(); + current_.type = TYPE_WHITESPACE; + return report_whitespace_; + } + return false; +} + +bool Tokenizer::TryConsumeNewline() { + if (!report_whitespace_ || !report_newlines_) { + return false; + } + if (TryConsume('\n')) { + current_.type = TYPE_NEWLINE; + return true; + } + return false; +} + +// ------------------------------------------------------------------- + +bool Tokenizer::Next() { + previous_ = current_; + + while (!read_error_) { + StartToken(); + bool report_token = TryConsumeWhitespace() || TryConsumeNewline(); + EndToken(); + if (report_token) { + return true; + } + + switch (TryConsumeCommentStart()) { + case LINE_COMMENT: + ConsumeLineComment(NULL); + continue; + case BLOCK_COMMENT: + ConsumeBlockComment(NULL); + continue; + case SLASH_NOT_COMMENT: + return true; + case NO_COMMENT: + break; + } + + // Check for EOF before continuing. + if (read_error_) break; + + if (LookingAt<Unprintable>() || current_char_ == '\0') { + AddError("Invalid control characters encountered in text."); + NextChar(); + // Skip more unprintable characters, too. But, remember that '\0' is + // also what current_char_ is set to after EOF / read error. We have + // to be careful not to go into an infinite loop of trying to consume + // it, so make sure to check read_error_ explicitly before consuming + // '\0'. + while (TryConsumeOne<Unprintable>() || + (!read_error_ && TryConsume('\0'))) { + // Ignore. + } + + } else { + // Reading some sort of token. + StartToken(); + + if (TryConsumeOne<Letter>()) { + ConsumeZeroOrMore<Alphanumeric>(); + current_.type = TYPE_IDENTIFIER; + } else if (TryConsume('0')) { + current_.type = ConsumeNumber(true, false); + } else if (TryConsume('.')) { + // This could be the beginning of a floating-point number, or it could + // just be a '.' symbol. + + if (TryConsumeOne<Digit>()) { + // It's a floating-point number. + if (previous_.type == TYPE_IDENTIFIER && + current_.line == previous_.line && + current_.column == previous_.end_column) { + // We don't accept syntax like "blah.123". + error_collector_->AddError( + line_, column_ - 2, + "Need space between identifier and decimal point."); + } + current_.type = ConsumeNumber(false, true); + } else { + current_.type = TYPE_SYMBOL; + } + } else if (TryConsumeOne<Digit>()) { + current_.type = ConsumeNumber(false, false); + } else if (TryConsume('\"')) { + ConsumeString('\"'); + current_.type = TYPE_STRING; + } else if (TryConsume('\'')) { + ConsumeString('\''); + current_.type = TYPE_STRING; + } else { + // Check if the high order bit is set. + if (current_char_ & 0x80) { + error_collector_->AddError( + line_, column_, + StringPrintf("Interpreting non ascii codepoint %d.", + static_cast<unsigned char>(current_char_))); + } + NextChar(); + current_.type = TYPE_SYMBOL; + } + + EndToken(); + return true; + } + } + + // EOF + current_.type = TYPE_END; + current_.text.clear(); + current_.line = line_; + current_.column = column_; + current_.end_column = column_; + return false; +} + +namespace { + +// Helper class for collecting comments and putting them in the right places. +// +// This basically just buffers the most recent comment until it can be decided +// exactly where that comment should be placed. When Flush() is called, the +// current comment goes into either prev_trailing_comments or detached_comments. +// When the CommentCollector is destroyed, the last buffered comment goes into +// next_leading_comments. +class CommentCollector { + public: + CommentCollector(std::string* prev_trailing_comments, + std::vector<std::string>* detached_comments, + std::string* next_leading_comments) + : prev_trailing_comments_(prev_trailing_comments), + detached_comments_(detached_comments), + next_leading_comments_(next_leading_comments), + has_comment_(false), + is_line_comment_(false), + can_attach_to_prev_(true) { + if (prev_trailing_comments != NULL) prev_trailing_comments->clear(); + if (detached_comments != NULL) detached_comments->clear(); + if (next_leading_comments != NULL) next_leading_comments->clear(); + } + + ~CommentCollector() { + // Whatever is in the buffer is a leading comment. + if (next_leading_comments_ != NULL && has_comment_) { + comment_buffer_.swap(*next_leading_comments_); + } + } + + // About to read a line comment. Get the comment buffer pointer in order to + // read into it. + std::string* GetBufferForLineComment() { + // We want to combine with previous line comments, but not block comments. + if (has_comment_ && !is_line_comment_) { + Flush(); + } + has_comment_ = true; + is_line_comment_ = true; + return &comment_buffer_; + } + + // About to read a block comment. Get the comment buffer pointer in order to + // read into it. + std::string* GetBufferForBlockComment() { + if (has_comment_) { + Flush(); + } + has_comment_ = true; + is_line_comment_ = false; + return &comment_buffer_; + } + + void ClearBuffer() { + comment_buffer_.clear(); + has_comment_ = false; + } + + // Called once we know that the comment buffer is complete and is *not* + // connected to the next token. + void Flush() { + if (has_comment_) { + if (can_attach_to_prev_) { + if (prev_trailing_comments_ != NULL) { + prev_trailing_comments_->append(comment_buffer_); + } + can_attach_to_prev_ = false; + } else { + if (detached_comments_ != NULL) { + detached_comments_->push_back(comment_buffer_); + } + } + ClearBuffer(); + } + } + + void DetachFromPrev() { can_attach_to_prev_ = false; } + + private: + std::string* prev_trailing_comments_; + std::vector<std::string>* detached_comments_; + std::string* next_leading_comments_; + + std::string comment_buffer_; + + // True if any comments were read into comment_buffer_. This can be true even + // if comment_buffer_ is empty, namely if the comment was "/**/". + bool has_comment_; + + // Is the comment in the comment buffer a line comment? + bool is_line_comment_; + + // Is it still possible that we could be reading a comment attached to the + // previous token? + bool can_attach_to_prev_; +}; + +} // namespace + +bool Tokenizer::NextWithComments(std::string* prev_trailing_comments, + std::vector<std::string>* detached_comments, + std::string* next_leading_comments) { + CommentCollector collector(prev_trailing_comments, detached_comments, + next_leading_comments); + + if (current_.type == TYPE_START) { + // Ignore unicode byte order mark(BOM) if it appears at the file + // beginning. Only UTF-8 BOM (0xEF 0xBB 0xBF) is accepted. + if (TryConsume(static_cast<char>(0xEF))) { + if (!TryConsume(static_cast<char>(0xBB)) || + !TryConsume(static_cast<char>(0xBF))) { + AddError( + "Proto file starts with 0xEF but not UTF-8 BOM. " + "Only UTF-8 is accepted for proto file."); + return false; + } + } + collector.DetachFromPrev(); + } else { + // A comment appearing on the same line must be attached to the previous + // declaration. + ConsumeZeroOrMore<WhitespaceNoNewline>(); + switch (TryConsumeCommentStart()) { + case LINE_COMMENT: + ConsumeLineComment(collector.GetBufferForLineComment()); + + // Don't allow comments on subsequent lines to be attached to a trailing + // comment. + collector.Flush(); + break; + case BLOCK_COMMENT: + ConsumeBlockComment(collector.GetBufferForBlockComment()); + + ConsumeZeroOrMore<WhitespaceNoNewline>(); + if (!TryConsume('\n')) { + // Oops, the next token is on the same line. If we recorded a comment + // we really have no idea which token it should be attached to. + collector.ClearBuffer(); + return Next(); + } + + // Don't allow comments on subsequent lines to be attached to a trailing + // comment. + collector.Flush(); + break; + case SLASH_NOT_COMMENT: + return true; + case NO_COMMENT: + if (!TryConsume('\n')) { + // The next token is on the same line. There are no comments. + return Next(); + } + break; + } + } + + // OK, we are now on the line *after* the previous token. + while (true) { + ConsumeZeroOrMore<WhitespaceNoNewline>(); + + switch (TryConsumeCommentStart()) { + case LINE_COMMENT: + ConsumeLineComment(collector.GetBufferForLineComment()); + break; + case BLOCK_COMMENT: + ConsumeBlockComment(collector.GetBufferForBlockComment()); + + // Consume the rest of the line so that we don't interpret it as a + // blank line the next time around the loop. + ConsumeZeroOrMore<WhitespaceNoNewline>(); + TryConsume('\n'); + break; + case SLASH_NOT_COMMENT: + return true; + case NO_COMMENT: + if (TryConsume('\n')) { + // Completely blank line. + collector.Flush(); + collector.DetachFromPrev(); + } else { + bool result = Next(); + if (!result || current_.text == "}" || current_.text == "]" || + current_.text == ")") { + // It looks like we're at the end of a scope. In this case it + // makes no sense to attach a comment to the following token. + collector.Flush(); + } + return result; + } + break; + } + } +} + +// ------------------------------------------------------------------- +// Token-parsing helpers. Remember that these don't need to report +// errors since any errors should already have been reported while +// tokenizing. Also, these can assume that whatever text they +// are given is text that the tokenizer actually parsed as a token +// of the given type. + +bool Tokenizer::ParseInteger(const std::string& text, uint64_t max_value, + uint64_t* output) { + // We can't just use strtoull() because (a) it accepts negative numbers, + // (b) We want additional range checks, (c) it reports overflows via errno. + +#if 0 + const char *str_begin = text.c_str(); + if (*str_begin == '-') return false; + char *str_end = nullptr; + errno = 0; + *output = std::strtoull(str_begin, &str_end, 0); + return (errno == 0 && str_end && *str_end == '\0' && *output <= max_value); +#endif + + const char* ptr = text.c_str(); + int base = 10; + uint64_t overflow_if_mul_base = (kuint64max / 10) + 1; + if (ptr[0] == '0') { + if (ptr[1] == 'x' || ptr[1] == 'X') { + // This is hex. + base = 16; + overflow_if_mul_base = (kuint64max / 16) + 1; + ptr += 2; + } else { + // This is octal. + base = 8; + overflow_if_mul_base = (kuint64max / 8) + 1; + } + } + + uint64_t result = 0; + // For all the leading '0's, and also the first non-zero character, we + // don't need to multiply. + while (*ptr != '\0') { + int digit = DigitValue(*ptr++); + if (digit >= base) { + // The token provided by Tokenizer is invalid. i.e., 099 is an invalid + // token, but Tokenizer still think it's integer. + return false; + } + if (digit != 0) { + result = digit; + break; + } + } + for (; *ptr != '\0'; ptr++) { + int digit = DigitValue(*ptr); + if (digit < 0 || digit >= base) { + // The token provided by Tokenizer is invalid. i.e., 099 is an invalid + // token, but Tokenizer still think it's integer. + return false; + } + if (result >= overflow_if_mul_base) { + // We know the multiply we're about to do will overflow, so exit now. + return false; + } + // We know that result * base won't overflow, but adding digit might... + result = result * base + digit; + // C++ guarantees defined "wrap" semantics when unsigned integer + // operations overflow, making this a fast way to check if adding + // digit made result overflow, and thus, wrap around. + if (result < static_cast<uint64_t>(base)) return false; + } + if (result > max_value) return false; + + *output = result; + return true; +} + +double Tokenizer::ParseFloat(const std::string& text) { + const char* start = text.c_str(); + char* end; + double result = NoLocaleStrtod(start, &end); + + // "1e" is not a valid float, but if the tokenizer reads it, it will + // report an error but still return it as a valid token. We need to + // accept anything the tokenizer could possibly return, error or not. + if (*end == 'e' || *end == 'E') { + ++end; + if (*end == '-' || *end == '+') ++end; + } + + // If the Tokenizer had allow_f_after_float_ enabled, the float may be + // suffixed with the letter 'f'. + if (*end == 'f' || *end == 'F') { + ++end; + } + + GOOGLE_LOG_IF(DFATAL, + static_cast<size_t>(end - start) != text.size() || *start == '-') + << " Tokenizer::ParseFloat() passed text that could not have been" + " tokenized as a float: " + << CEscape(text); + return result; +} + +// Helper to append a Unicode code point to a string as UTF8, without bringing +// in any external dependencies. +static void AppendUTF8(uint32_t code_point, std::string* output) { + uint32_t tmp = 0; + int len = 0; + if (code_point <= 0x7f) { + tmp = code_point; + len = 1; + } else if (code_point <= 0x07ff) { + tmp = 0x0000c080 | ((code_point & 0x07c0) << 2) | (code_point & 0x003f); + len = 2; + } else if (code_point <= 0xffff) { + tmp = 0x00e08080 | ((code_point & 0xf000) << 4) | + ((code_point & 0x0fc0) << 2) | (code_point & 0x003f); + len = 3; + } else if (code_point <= 0x10ffff) { + tmp = 0xf0808080 | ((code_point & 0x1c0000) << 6) | + ((code_point & 0x03f000) << 4) | ((code_point & 0x000fc0) << 2) | + (code_point & 0x003f); + len = 4; + } else { + // Unicode code points end at 0x10FFFF, so this is out-of-range. + // ConsumeString permits hex values up to 0x1FFFFF, and FetchUnicodePoint + // doesn't perform a range check. + StringAppendF(output, "\\U%08x", code_point); + return; + } + tmp = ghtonl(tmp); + output->append(reinterpret_cast<const char*>(&tmp) + sizeof(tmp) - len, len); +} + +// Try to read <len> hex digits from ptr, and stuff the numeric result into +// *result. Returns true if that many digits were successfully consumed. +static bool ReadHexDigits(const char* ptr, int len, uint32_t* result) { + *result = 0; + if (len == 0) return false; + for (const char* end = ptr + len; ptr < end; ++ptr) { + if (*ptr == '\0') return false; + *result = (*result << 4) + DigitValue(*ptr); + } + return true; +} + +// Handling UTF-16 surrogate pairs. UTF-16 encodes code points in the range +// 0x10000...0x10ffff as a pair of numbers, a head surrogate followed by a trail +// surrogate. These numbers are in a reserved range of Unicode code points, so +// if we encounter such a pair we know how to parse it and convert it into a +// single code point. +static const uint32_t kMinHeadSurrogate = 0xd800; +static const uint32_t kMaxHeadSurrogate = 0xdc00; +static const uint32_t kMinTrailSurrogate = 0xdc00; +static const uint32_t kMaxTrailSurrogate = 0xe000; + +static inline bool IsHeadSurrogate(uint32_t code_point) { + return (code_point >= kMinHeadSurrogate) && (code_point < kMaxHeadSurrogate); +} + +static inline bool IsTrailSurrogate(uint32_t code_point) { + return (code_point >= kMinTrailSurrogate) && + (code_point < kMaxTrailSurrogate); +} + +// Combine a head and trail surrogate into a single Unicode code point. +static uint32_t AssembleUTF16(uint32_t head_surrogate, + uint32_t trail_surrogate) { + GOOGLE_DCHECK(IsHeadSurrogate(head_surrogate)); + GOOGLE_DCHECK(IsTrailSurrogate(trail_surrogate)); + return 0x10000 + (((head_surrogate - kMinHeadSurrogate) << 10) | + (trail_surrogate - kMinTrailSurrogate)); +} + +// Convert the escape sequence parameter to a number of expected hex digits. +static inline int UnicodeLength(char key) { + if (key == 'u') return 4; + if (key == 'U') return 8; + return 0; +} + +// Given a pointer to the 'u' or 'U' starting a Unicode escape sequence, attempt +// to parse that sequence. On success, returns a pointer to the first char +// beyond that sequence, and fills in *code_point. On failure, returns ptr +// itself. +static const char* FetchUnicodePoint(const char* ptr, uint32_t* code_point) { + const char* p = ptr; + // Fetch the code point. + const int len = UnicodeLength(*p++); + if (!ReadHexDigits(p, len, code_point)) return ptr; + p += len; + + // Check if the code point we read is a "head surrogate." If so, then we + // expect it to be immediately followed by another code point which is a valid + // "trail surrogate," and together they form a UTF-16 pair which decodes into + // a single Unicode point. Trail surrogates may only use \u, not \U. + if (IsHeadSurrogate(*code_point) && *p == '\\' && *(p + 1) == 'u') { + uint32_t trail_surrogate; + if (ReadHexDigits(p + 2, 4, &trail_surrogate) && + IsTrailSurrogate(trail_surrogate)) { + *code_point = AssembleUTF16(*code_point, trail_surrogate); + p += 6; + } + // If this failed, then we just emit the head surrogate as a code point. + // It's bogus, but so is the string. + } + + return p; +} + +// The text string must begin and end with single or double quote +// characters. +void Tokenizer::ParseStringAppend(const std::string& text, + std::string* output) { + // Reminder: text[0] is always a quote character. (If text is + // empty, it's invalid, so we'll just return). + const size_t text_size = text.size(); + if (text_size == 0) { + GOOGLE_LOG(DFATAL) << " Tokenizer::ParseStringAppend() passed text that could not" + " have been tokenized as a string: " + << CEscape(text); + return; + } + + // Reserve room for new string. The branch is necessary because if + // there is already space available the reserve() call might + // downsize the output. + const size_t new_len = text_size + output->size(); + if (new_len > output->capacity()) { + output->reserve(new_len); + } + + // Loop through the string copying characters to "output" and + // interpreting escape sequences. Note that any invalid escape + // sequences or other errors were already reported while tokenizing. + // In this case we do not need to produce valid results. + for (const char* ptr = text.c_str() + 1; *ptr != '\0'; ptr++) { + if (*ptr == '\\' && ptr[1] != '\0') { + // An escape sequence. + ++ptr; + + if (OctalDigit::InClass(*ptr)) { + // An octal escape. May one, two, or three digits. + int code = DigitValue(*ptr); + if (OctalDigit::InClass(ptr[1])) { + ++ptr; + code = code * 8 + DigitValue(*ptr); + } + if (OctalDigit::InClass(ptr[1])) { + ++ptr; + code = code * 8 + DigitValue(*ptr); + } + output->push_back(static_cast<char>(code)); + + } else if (*ptr == 'x') { + // A hex escape. May zero, one, or two digits. (The zero case + // will have been caught as an error earlier.) + int code = 0; + if (HexDigit::InClass(ptr[1])) { + ++ptr; + code = DigitValue(*ptr); + } + if (HexDigit::InClass(ptr[1])) { + ++ptr; + code = code * 16 + DigitValue(*ptr); + } + output->push_back(static_cast<char>(code)); + + } else if (*ptr == 'u' || *ptr == 'U') { + uint32_t unicode; + const char* end = FetchUnicodePoint(ptr, &unicode); + if (end == ptr) { + // Failure: Just dump out what we saw, don't try to parse it. + output->push_back(*ptr); + } else { + AppendUTF8(unicode, output); + ptr = end - 1; // Because we're about to ++ptr. + } + } else { + // Some other escape code. + output->push_back(TranslateEscape(*ptr)); + } + + } else if (*ptr == text[0] && ptr[1] == '\0') { + // Ignore final quote matching the starting quote. + } else { + output->push_back(*ptr); + } + } +} + +template <typename CharacterClass> +static bool AllInClass(const std::string& s) { + for (const char character : s) { + if (!CharacterClass::InClass(character)) return false; + } + return true; +} + +bool Tokenizer::IsIdentifier(const std::string& text) { + // Mirrors IDENTIFIER definition in Tokenizer::Next() above. + if (text.size() == 0) return false; + if (!Letter::InClass(text.at(0))) return false; + if (!AllInClass<Alphanumeric>(text.substr(1))) return false; + return true; +} + +} // namespace io +} // namespace protobuf +} // namespace google + +#include <google/protobuf/port_undef.inc> diff --git a/toolkit/components/protobuf/src/google/protobuf/io/tokenizer.h b/toolkit/components/protobuf/src/google/protobuf/io/tokenizer.h new file mode 100644 index 0000000000..4abab7e30c --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/io/tokenizer.h @@ -0,0 +1,442 @@ +// 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. + +// Author: kenton@google.com (Kenton Varda) +// Based on original Protocol Buffers design by +// Sanjay Ghemawat, Jeff Dean, and others. +// +// Class for parsing tokenized text from a ZeroCopyInputStream. + +#ifndef GOOGLE_PROTOBUF_IO_TOKENIZER_H__ +#define GOOGLE_PROTOBUF_IO_TOKENIZER_H__ + + +#include <string> +#include <vector> + +#include <google/protobuf/stubs/common.h> +#include <google/protobuf/stubs/logging.h> + +// Must be included last. +#include <google/protobuf/port_def.inc> + +namespace google { +namespace protobuf { +namespace io { + +class ZeroCopyInputStream; // zero_copy_stream.h + +// Defined in this file. +class ErrorCollector; +class Tokenizer; + +// By "column number", the proto compiler refers to a count of the number +// of bytes before a given byte, except that a tab character advances to +// the next multiple of 8 bytes. Note in particular that column numbers +// are zero-based, while many user interfaces use one-based column numbers. +typedef int ColumnNumber; + +// Abstract interface for an object which collects the errors that occur +// during parsing. A typical implementation might simply print the errors +// to stdout. +class PROTOBUF_EXPORT ErrorCollector { + public: + inline ErrorCollector() {} + virtual ~ErrorCollector(); + + // Indicates that there was an error in the input at the given line and + // column numbers. The numbers are zero-based, so you may want to add + // 1 to each before printing them. + virtual void AddError(int line, ColumnNumber column, + const std::string& message) = 0; + + // Indicates that there was a warning in the input at the given line and + // column numbers. The numbers are zero-based, so you may want to add + // 1 to each before printing them. + virtual void AddWarning(int /* line */, ColumnNumber /* column */, + const std::string& /* message */) {} + + private: + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ErrorCollector); +}; + +// This class converts a stream of raw text into a stream of tokens for +// the protocol definition parser to parse. The tokens recognized are +// similar to those that make up the C language; see the TokenType enum for +// precise descriptions. Whitespace and comments are skipped. By default, +// C- and C++-style comments are recognized, but other styles can be used by +// calling set_comment_style(). +class PROTOBUF_EXPORT Tokenizer { + public: + // Construct a Tokenizer that reads and tokenizes text from the given + // input stream and writes errors to the given error_collector. + // The caller keeps ownership of input and error_collector. + Tokenizer(ZeroCopyInputStream* input, ErrorCollector* error_collector); + ~Tokenizer(); + + enum TokenType { + TYPE_START, // Next() has not yet been called. + TYPE_END, // End of input reached. "text" is empty. + + TYPE_IDENTIFIER, // A sequence of letters, digits, and underscores, not + // starting with a digit. It is an error for a number + // to be followed by an identifier with no space in + // between. + TYPE_INTEGER, // A sequence of digits representing an integer. Normally + // the digits are decimal, but a prefix of "0x" indicates + // a hex number and a leading zero indicates octal, just + // like with C numeric literals. A leading negative sign + // is NOT included in the token; it's up to the parser to + // interpret the unary minus operator on its own. + TYPE_FLOAT, // A floating point literal, with a fractional part and/or + // an exponent. Always in decimal. Again, never + // negative. + TYPE_STRING, // A quoted sequence of escaped characters. Either single + // or double quotes can be used, but they must match. + // A string literal cannot cross a line break. + TYPE_SYMBOL, // Any other printable character, like '!' or '+'. + // Symbols are always a single character, so "!+$%" is + // four tokens. + TYPE_WHITESPACE, // A sequence of whitespace. This token type is only + // produced if report_whitespace() is true. It is not + // reported for whitespace within comments or strings. + TYPE_NEWLINE, // A newline (\n). This token type is only + // produced if report_whitespace() is true and + // report_newlines() is true. It is not reported for + // newlines in comments or strings. + }; + + // Structure representing a token read from the token stream. + struct Token { + TokenType type; + std::string text; // The exact text of the token as it appeared in + // the input. e.g. tokens of TYPE_STRING will still + // be escaped and in quotes. + + // "line" and "column" specify the position of the first character of + // the token within the input stream. They are zero-based. + int line; + ColumnNumber column; + ColumnNumber end_column; + }; + + // Get the current token. This is updated when Next() is called. Before + // the first call to Next(), current() has type TYPE_START and no contents. + const Token& current(); + + // Return the previous token -- i.e. what current() returned before the + // previous call to Next(). + const Token& previous(); + + // Advance to the next token. Returns false if the end of the input is + // reached. + bool Next(); + + // Like Next(), but also collects comments which appear between the previous + // and next tokens. + // + // Comments which appear to be attached to the previous token are stored + // in *prev_tailing_comments. Comments which appear to be attached to the + // next token are stored in *next_leading_comments. Comments appearing in + // between which do not appear to be attached to either will be added to + // detached_comments. Any of these parameters can be NULL to simply discard + // the comments. + // + // A series of line comments appearing on consecutive lines, with no other + // tokens appearing on those lines, will be treated as a single comment. + // + // Only the comment content is returned; comment markers (e.g. //) are + // stripped out. For block comments, leading whitespace and an asterisk will + // be stripped from the beginning of each line other than the first. Newlines + // are included in the output. + // + // Examples: + // + // optional int32 foo = 1; // Comment attached to foo. + // // Comment attached to bar. + // optional int32 bar = 2; + // + // optional string baz = 3; + // // Comment attached to baz. + // // Another line attached to baz. + // + // // Comment attached to qux. + // // + // // Another line attached to qux. + // optional double qux = 4; + // + // // Detached comment. This is not attached to qux or corge + // // because there are blank lines separating it from both. + // + // optional string corge = 5; + // /* Block comment attached + // * to corge. Leading asterisks + // * will be removed. */ + // /* Block comment attached to + // * grault. */ + // optional int32 grault = 6; + bool NextWithComments(std::string* prev_trailing_comments, + std::vector<std::string>* detached_comments, + std::string* next_leading_comments); + + // Parse helpers --------------------------------------------------- + + // Parses a TYPE_FLOAT token. This never fails, so long as the text actually + // comes from a TYPE_FLOAT token parsed by Tokenizer. If it doesn't, the + // result is undefined (possibly an assert failure). + static double ParseFloat(const std::string& text); + + // Parses a TYPE_STRING token. This never fails, so long as the text actually + // comes from a TYPE_STRING token parsed by Tokenizer. If it doesn't, the + // result is undefined (possibly an assert failure). + static void ParseString(const std::string& text, std::string* output); + + // Identical to ParseString, but appends to output. + static void ParseStringAppend(const std::string& text, std::string* output); + + // Parses a TYPE_INTEGER token. Returns false if the result would be + // greater than max_value. Otherwise, returns true and sets *output to the + // result. If the text is not from a Token of type TYPE_INTEGER originally + // parsed by a Tokenizer, the result is undefined (possibly an assert + // failure). + static bool ParseInteger(const std::string& text, uint64_t max_value, + uint64_t* output); + + // Options --------------------------------------------------------- + + // Set true to allow floats to be suffixed with the letter 'f'. Tokens + // which would otherwise be integers but which have the 'f' suffix will be + // forced to be interpreted as floats. For all other purposes, the 'f' is + // ignored. + void set_allow_f_after_float(bool value) { allow_f_after_float_ = value; } + + // Valid values for set_comment_style(). + enum CommentStyle { + // Line comments begin with "//", block comments are delimited by "/*" and + // "*/". + CPP_COMMENT_STYLE, + // Line comments begin with "#". No way to write block comments. + SH_COMMENT_STYLE + }; + + // Sets the comment style. + void set_comment_style(CommentStyle style) { comment_style_ = style; } + + // Whether to require whitespace between a number and a field name. + // Default is true. Do not use this; for Google-internal cleanup only. + void set_require_space_after_number(bool require) { + require_space_after_number_ = require; + } + + // Whether to allow string literals to span multiple lines. Default is false. + // Do not use this; for Google-internal cleanup only. + void set_allow_multiline_strings(bool allow) { + allow_multiline_strings_ = allow; + } + + // If true, whitespace tokens are reported by Next(). + // Note: `set_report_whitespace(false)` implies `set_report_newlines(false)`. + bool report_whitespace() const; + void set_report_whitespace(bool report); + + // If true, newline tokens are reported by Next(). + // Note: `set_report_newlines(true)` implies `set_report_whitespace(true)`. + bool report_newlines() const; + void set_report_newlines(bool report); + + // External helper: validate an identifier. + static bool IsIdentifier(const std::string& text); + + // ----------------------------------------------------------------- + private: + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Tokenizer); + + Token current_; // Returned by current(). + Token previous_; // Returned by previous(). + + ZeroCopyInputStream* input_; + ErrorCollector* error_collector_; + + char current_char_; // == buffer_[buffer_pos_], updated by NextChar(). + const char* buffer_; // Current buffer returned from input_. + int buffer_size_; // Size of buffer_. + int buffer_pos_; // Current position within the buffer. + bool read_error_; // Did we previously encounter a read error? + + // Line and column number of current_char_ within the whole input stream. + int line_; + ColumnNumber column_; + + // String to which text should be appended as we advance through it. + // Call RecordTo(&str) to start recording and StopRecording() to stop. + // E.g. StartToken() calls RecordTo(¤t_.text). record_start_ is the + // position within the current buffer where recording started. + std::string* record_target_; + int record_start_; + + // Options. + bool allow_f_after_float_; + CommentStyle comment_style_; + bool require_space_after_number_; + bool allow_multiline_strings_; + bool report_whitespace_ = false; + bool report_newlines_ = false; + + // Since we count columns we need to interpret tabs somehow. We'll take + // the standard 8-character definition for lack of any way to do better. + // This must match the documentation of ColumnNumber. + static const int kTabWidth = 8; + + // ----------------------------------------------------------------- + // Helper methods. + + // Consume this character and advance to the next one. + void NextChar(); + + // Read a new buffer from the input. + void Refresh(); + + inline void RecordTo(std::string* target); + inline void StopRecording(); + + // Called when the current character is the first character of a new + // token (not including whitespace or comments). + inline void StartToken(); + // Called when the current character is the first character after the + // end of the last token. After this returns, current_.text will + // contain all text consumed since StartToken() was called. + inline void EndToken(); + + // Convenience method to add an error at the current line and column. + void AddError(const std::string& message) { + error_collector_->AddError(line_, column_, message); + } + + // ----------------------------------------------------------------- + // The following four methods are used to consume tokens of specific + // types. They are actually used to consume all characters *after* + // the first, since the calling function consumes the first character + // in order to decide what kind of token is being read. + + // Read and consume a string, ending when the given delimiter is + // consumed. + void ConsumeString(char delimiter); + + // Read and consume a number, returning TYPE_FLOAT or TYPE_INTEGER + // depending on what was read. This needs to know if the first + // character was a zero in order to correctly recognize hex and octal + // numbers. + // It also needs to know if the first character was a . to parse floating + // point correctly. + TokenType ConsumeNumber(bool started_with_zero, bool started_with_dot); + + // Consume the rest of a line. + void ConsumeLineComment(std::string* content); + // Consume until "*/". + void ConsumeBlockComment(std::string* content); + + enum NextCommentStatus { + // Started a line comment. + LINE_COMMENT, + + // Started a block comment. + BLOCK_COMMENT, + + // Consumed a slash, then realized it wasn't a comment. current_ has + // been filled in with a slash token. The caller should return it. + SLASH_NOT_COMMENT, + + // We do not appear to be starting a comment here. + NO_COMMENT + }; + + // If we're at the start of a new comment, consume it and return what kind + // of comment it is. + NextCommentStatus TryConsumeCommentStart(); + + // If we're looking at a TYPE_WHITESPACE token and `report_whitespace_` is + // true, consume it and return true. + bool TryConsumeWhitespace(); + + // If we're looking at a TYPE_NEWLINE token and `report_newlines_` is true, + // consume it and return true. + bool TryConsumeNewline(); + + // ----------------------------------------------------------------- + // These helper methods make the parsing code more readable. The + // "character classes" referred to are defined at the top of the .cc file. + // Basically it is a C++ class with one method: + // static bool InClass(char c); + // The method returns true if c is a member of this "class", like "Letter" + // or "Digit". + + // Returns true if the current character is of the given character + // class, but does not consume anything. + template <typename CharacterClass> + inline bool LookingAt(); + + // If the current character is in the given class, consume it and return + // true. Otherwise return false. + // e.g. TryConsumeOne<Letter>() + template <typename CharacterClass> + inline bool TryConsumeOne(); + + // Like above, but try to consume the specific character indicated. + inline bool TryConsume(char c); + + // Consume zero or more of the given character class. + template <typename CharacterClass> + inline void ConsumeZeroOrMore(); + + // Consume one or more of the given character class or log the given + // error message. + // e.g. ConsumeOneOrMore<Digit>("Expected digits."); + template <typename CharacterClass> + inline void ConsumeOneOrMore(const char* error); +}; + +// inline methods ==================================================== +inline const Tokenizer::Token& Tokenizer::current() { return current_; } + +inline const Tokenizer::Token& Tokenizer::previous() { return previous_; } + +inline void Tokenizer::ParseString(const std::string& text, + std::string* output) { + output->clear(); + ParseStringAppend(text, output); +} + +} // namespace io +} // namespace protobuf +} // namespace google + +#include <google/protobuf/port_undef.inc> + +#endif // GOOGLE_PROTOBUF_IO_TOKENIZER_H__ diff --git a/toolkit/components/protobuf/src/google/protobuf/io/zero_copy_stream.cc b/toolkit/components/protobuf/src/google/protobuf/io/zero_copy_stream.cc new file mode 100644 index 0000000000..f81555e554 --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/io/zero_copy_stream.cc @@ -0,0 +1,55 @@ +// 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. + +// Author: kenton@google.com (Kenton Varda) +// Based on original Protocol Buffers design by +// Sanjay Ghemawat, Jeff Dean, and others. + +#include <google/protobuf/io/zero_copy_stream.h> + +#include <google/protobuf/stubs/logging.h> +#include <google/protobuf/stubs/common.h> + +namespace google { +namespace protobuf { +namespace io { + + +bool ZeroCopyOutputStream::WriteAliasedRaw(const void* /* data */, + int /* size */) { + GOOGLE_LOG(FATAL) << "This ZeroCopyOutputStream doesn't support aliasing. " + "Reaching here usually means a ZeroCopyOutputStream " + "implementation bug."; + return false; +} + +} // namespace io +} // namespace protobuf +} // namespace google diff --git a/toolkit/components/protobuf/src/google/protobuf/io/zero_copy_stream.h b/toolkit/components/protobuf/src/google/protobuf/io/zero_copy_stream.h new file mode 100644 index 0000000000..2041cbf648 --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/io/zero_copy_stream.h @@ -0,0 +1,260 @@ +// 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. + +// Author: kenton@google.com (Kenton Varda) +// Based on original Protocol Buffers design by +// Sanjay Ghemawat, Jeff Dean, and others. +// +// This file contains the ZeroCopyInputStream and ZeroCopyOutputStream +// interfaces, which represent abstract I/O streams to and from which +// protocol buffers can be read and written. For a few simple +// implementations of these interfaces, see zero_copy_stream_impl.h. +// +// These interfaces are different from classic I/O streams in that they +// try to minimize the amount of data copying that needs to be done. +// To accomplish this, responsibility for allocating buffers is moved to +// the stream object, rather than being the responsibility of the caller. +// So, the stream can return a buffer which actually points directly into +// the final data structure where the bytes are to be stored, and the caller +// can interact directly with that buffer, eliminating an intermediate copy +// operation. +// +// As an example, consider the common case in which you are reading bytes +// from an array that is already in memory (or perhaps an mmap()ed file). +// With classic I/O streams, you would do something like: +// char buffer[BUFFER_SIZE]; +// input->Read(buffer, BUFFER_SIZE); +// DoSomething(buffer, BUFFER_SIZE); +// Then, the stream basically just calls memcpy() to copy the data from +// the array into your buffer. With a ZeroCopyInputStream, you would do +// this instead: +// const void* buffer; +// int size; +// input->Next(&buffer, &size); +// DoSomething(buffer, size); +// Here, no copy is performed. The input stream returns a pointer directly +// into the backing array, and the caller ends up reading directly from it. +// +// If you want to be able to read the old-fashion way, you can create +// a CodedInputStream or CodedOutputStream wrapping these objects and use +// their ReadRaw()/WriteRaw() methods. These will, of course, add a copy +// step, but Coded*Stream will handle buffering so at least it will be +// reasonably efficient. +// +// ZeroCopyInputStream example: +// // Read in a file and print its contents to stdout. +// int fd = open("myfile", O_RDONLY); +// ZeroCopyInputStream* input = new FileInputStream(fd); +// +// const void* buffer; +// int size; +// while (input->Next(&buffer, &size)) { +// cout.write(buffer, size); +// } +// +// delete input; +// close(fd); +// +// ZeroCopyOutputStream example: +// // Copy the contents of "infile" to "outfile", using plain read() for +// // "infile" but a ZeroCopyOutputStream for "outfile". +// int infd = open("infile", O_RDONLY); +// int outfd = open("outfile", O_WRONLY); +// ZeroCopyOutputStream* output = new FileOutputStream(outfd); +// +// void* buffer; +// int size; +// while (output->Next(&buffer, &size)) { +// int bytes = read(infd, buffer, size); +// if (bytes < size) { +// // Reached EOF. +// output->BackUp(size - bytes); +// break; +// } +// } +// +// delete output; +// close(infd); +// close(outfd); + +#ifndef GOOGLE_PROTOBUF_IO_ZERO_COPY_STREAM_H__ +#define GOOGLE_PROTOBUF_IO_ZERO_COPY_STREAM_H__ + + +#include <google/protobuf/stubs/common.h> + + +// Must be included last. +#include <google/protobuf/port_def.inc> + +namespace google { +namespace protobuf { +namespace io { + +// Defined in this file. +class ZeroCopyInputStream; +class ZeroCopyOutputStream; + +// Abstract interface similar to an input stream but designed to minimize +// copying. +class PROTOBUF_EXPORT ZeroCopyInputStream { + public: + ZeroCopyInputStream() {} + virtual ~ZeroCopyInputStream() {} + + // Obtains a chunk of data from the stream. + // + // Preconditions: + // * "size" and "data" are not NULL. + // + // Postconditions: + // * If the returned value is false, there is no more data to return or + // an error occurred. All errors are permanent. + // * Otherwise, "size" points to the actual number of bytes read and "data" + // points to a pointer to a buffer containing these bytes. + // * Ownership of this buffer remains with the stream, and the buffer + // remains valid only until some other method of the stream is called + // or the stream is destroyed. + // * It is legal for the returned buffer to have zero size, as long + // as repeatedly calling Next() eventually yields a buffer with non-zero + // size. + virtual bool Next(const void** data, int* size) = 0; + + // Backs up a number of bytes, so that the next call to Next() returns + // data again that was already returned by the last call to Next(). This + // is useful when writing procedures that are only supposed to read up + // to a certain point in the input, then return. If Next() returns a + // buffer that goes beyond what you wanted to read, you can use BackUp() + // to return to the point where you intended to finish. + // + // This method can be called with `count = 0` to finalize (flush) any + // previously returned buffer. For example, a file output stream can + // flush buffers returned from a previous call to Next() upon such + // BackUp(0) invocations. ZeroCopyOutputStream callers should always + // invoke BackUp() after a final Next() call, even if there is no + // excess buffer data to be backed up to indicate a flush point. + // + // Preconditions: + // * The last method called must have been Next(). + // * count must be less than or equal to the size of the last buffer + // returned by Next(). + // + // Postconditions: + // * The last "count" bytes of the last buffer returned by Next() will be + // pushed back into the stream. Subsequent calls to Next() will return + // the same data again before producing new data. + virtual void BackUp(int count) = 0; + + // Skips a number of bytes. Returns false if the end of the stream is + // reached or some input error occurred. In the end-of-stream case, the + // stream is advanced to the end of the stream (so ByteCount() will return + // the total size of the stream). + virtual bool Skip(int count) = 0; + + // Returns the total number of bytes read since this object was created. + virtual int64_t ByteCount() const = 0; + + + private: + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ZeroCopyInputStream); +}; + +// Abstract interface similar to an output stream but designed to minimize +// copying. +class PROTOBUF_EXPORT ZeroCopyOutputStream { + public: + ZeroCopyOutputStream() {} + virtual ~ZeroCopyOutputStream() {} + + // Obtains a buffer into which data can be written. Any data written + // into this buffer will eventually (maybe instantly, maybe later on) + // be written to the output. + // + // Preconditions: + // * "size" and "data" are not NULL. + // + // Postconditions: + // * If the returned value is false, an error occurred. All errors are + // permanent. + // * Otherwise, "size" points to the actual number of bytes in the buffer + // and "data" points to the buffer. + // * Ownership of this buffer remains with the stream, and the buffer + // remains valid only until some other method of the stream is called + // or the stream is destroyed. + // * Any data which the caller stores in this buffer will eventually be + // written to the output (unless BackUp() is called). + // * It is legal for the returned buffer to have zero size, as long + // as repeatedly calling Next() eventually yields a buffer with non-zero + // size. + virtual bool Next(void** data, int* size) = 0; + + // Backs up a number of bytes, so that the end of the last buffer returned + // by Next() is not actually written. This is needed when you finish + // writing all the data you want to write, but the last buffer was bigger + // than you needed. You don't want to write a bunch of garbage after the + // end of your data, so you use BackUp() to back up. + // + // Preconditions: + // * The last method called must have been Next(). + // * count must be less than or equal to the size of the last buffer + // returned by Next(). + // * The caller must not have written anything to the last "count" bytes + // of that buffer. + // + // Postconditions: + // * The last "count" bytes of the last buffer returned by Next() will be + // ignored. + virtual void BackUp(int count) = 0; + + // Returns the total number of bytes written since this object was created. + virtual int64_t ByteCount() const = 0; + + // Write a given chunk of data to the output. Some output streams may + // implement this in a way that avoids copying. Check AllowsAliasing() before + // calling WriteAliasedRaw(). It will GOOGLE_CHECK fail if WriteAliasedRaw() is + // called on a stream that does not allow aliasing. + // + // NOTE: It is caller's responsibility to ensure that the chunk of memory + // remains live until all of the data has been consumed from the stream. + virtual bool WriteAliasedRaw(const void* data, int size); + virtual bool AllowsAliasing() const { return false; } + + + private: + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ZeroCopyOutputStream); +}; + +} // namespace io +} // namespace protobuf +} // namespace google + +#include <google/protobuf/port_undef.inc> + +#endif // GOOGLE_PROTOBUF_IO_ZERO_COPY_STREAM_H__ diff --git a/toolkit/components/protobuf/src/google/protobuf/io/zero_copy_stream_impl.cc b/toolkit/components/protobuf/src/google/protobuf/io/zero_copy_stream_impl.cc new file mode 100644 index 0000000000..c66bc862a7 --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/io/zero_copy_stream_impl.cc @@ -0,0 +1,372 @@ +// 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. + +// Author: kenton@google.com (Kenton Varda) +// Based on original Protocol Buffers design by +// Sanjay Ghemawat, Jeff Dean, and others. + +#ifndef _MSC_VER +#include <fcntl.h> +#include <sys/stat.h> +#include <sys/types.h> +#include <unistd.h> +#endif +#include <errno.h> + +#include <algorithm> +#include <iostream> + +#include <google/protobuf/stubs/common.h> +#include <google/protobuf/stubs/logging.h> +#include <google/protobuf/io/io_win32.h> +#include <google/protobuf/io/zero_copy_stream_impl.h> +#include <google/protobuf/stubs/stl_util.h> + + +namespace google { +namespace protobuf { +namespace io { + +#ifdef _WIN32 +// Win32 lseek is broken: If invoked on a non-seekable file descriptor, its +// return value is undefined. We re-define it to always produce an error. +#define lseek(fd, offset, origin) ((off_t)-1) +// DO NOT include <io.h>, instead create functions in io_win32.{h,cc} and import +// them like we do below. +using google::protobuf::io::win32::access; +using google::protobuf::io::win32::close; +using google::protobuf::io::win32::open; +using google::protobuf::io::win32::read; +using google::protobuf::io::win32::write; +#endif + +namespace { + +// EINTR sucks. +int close_no_eintr(int fd) { + int result; + do { + result = close(fd); + } while (result < 0 && errno == EINTR); + return result; +} + +} // namespace + +// =================================================================== + +FileInputStream::FileInputStream(int file_descriptor, int block_size) + : copying_input_(file_descriptor), impl_(©ing_input_, block_size) {} + +bool FileInputStream::Close() { return copying_input_.Close(); } + +bool FileInputStream::Next(const void** data, int* size) { + return impl_.Next(data, size); +} + +void FileInputStream::BackUp(int count) { impl_.BackUp(count); } + +bool FileInputStream::Skip(int count) { return impl_.Skip(count); } + +int64_t FileInputStream::ByteCount() const { return impl_.ByteCount(); } + +FileInputStream::CopyingFileInputStream::CopyingFileInputStream( + int file_descriptor) + : file_(file_descriptor), + close_on_delete_(false), + is_closed_(false), + errno_(0), + previous_seek_failed_(false) { +#ifndef _WIN32 + int flags = fcntl(file_, F_GETFL); + flags &= ~O_NONBLOCK; + fcntl(file_, F_SETFL, flags); +#endif +} + +FileInputStream::CopyingFileInputStream::~CopyingFileInputStream() { + if (close_on_delete_) { + if (!Close()) { + GOOGLE_LOG(ERROR) << "close() failed: " << strerror(errno_); + } + } +} + +bool FileInputStream::CopyingFileInputStream::Close() { + GOOGLE_CHECK(!is_closed_); + + is_closed_ = true; + if (close_no_eintr(file_) != 0) { + // The docs on close() do not specify whether a file descriptor is still + // open after close() fails with EIO. However, the glibc source code + // seems to indicate that it is not. + errno_ = errno; + return false; + } + + return true; +} + +int FileInputStream::CopyingFileInputStream::Read(void* buffer, int size) { + GOOGLE_CHECK(!is_closed_); + + int result; + do { + result = read(file_, buffer, size); + } while (result < 0 && errno == EINTR); + + if (result < 0) { + // Read error (not EOF). + errno_ = errno; + } + + return result; +} + +int FileInputStream::CopyingFileInputStream::Skip(int count) { + GOOGLE_CHECK(!is_closed_); + + if (!previous_seek_failed_ && lseek(file_, count, SEEK_CUR) != (off_t)-1) { + // Seek succeeded. + return count; + } else { + // Failed to seek. + + // Note to self: Don't seek again. This file descriptor doesn't + // support it. + previous_seek_failed_ = true; + + // Use the default implementation. + return CopyingInputStream::Skip(count); + } +} + +// =================================================================== + +FileOutputStream::FileOutputStream(int file_descriptor, int /*block_size*/) + : CopyingOutputStreamAdaptor(©ing_output_), + copying_output_(file_descriptor) {} + +bool FileOutputStream::Close() { + bool flush_succeeded = Flush(); + return copying_output_.Close() && flush_succeeded; +} + +FileOutputStream::CopyingFileOutputStream::CopyingFileOutputStream( + int file_descriptor) + : file_(file_descriptor), + close_on_delete_(false), + is_closed_(false), + errno_(0) {} + +FileOutputStream::~FileOutputStream() { Flush(); } + +FileOutputStream::CopyingFileOutputStream::~CopyingFileOutputStream() { + if (close_on_delete_) { + if (!Close()) { + GOOGLE_LOG(ERROR) << "close() failed: " << strerror(errno_); + } + } +} + +bool FileOutputStream::CopyingFileOutputStream::Close() { + GOOGLE_CHECK(!is_closed_); + + is_closed_ = true; + if (close_no_eintr(file_) != 0) { + // The docs on close() do not specify whether a file descriptor is still + // open after close() fails with EIO. However, the glibc source code + // seems to indicate that it is not. + errno_ = errno; + return false; + } + + return true; +} + +bool FileOutputStream::CopyingFileOutputStream::Write(const void* buffer, + int size) { + GOOGLE_CHECK(!is_closed_); + int total_written = 0; + + const uint8_t* buffer_base = reinterpret_cast<const uint8_t*>(buffer); + + while (total_written < size) { + int bytes; + do { + bytes = write(file_, buffer_base + total_written, size - total_written); + } while (bytes < 0 && errno == EINTR); + + if (bytes <= 0) { + // Write error. + + // FIXME(kenton): According to the man page, if write() returns zero, + // there was no error; write() simply did not write anything. It's + // unclear under what circumstances this might happen, but presumably + // errno won't be set in this case. I am confused as to how such an + // event should be handled. For now I'm treating it as an error, since + // retrying seems like it could lead to an infinite loop. I suspect + // this never actually happens anyway. + + if (bytes < 0) { + errno_ = errno; + } + return false; + } + total_written += bytes; + } + + return true; +} + +// =================================================================== + +IstreamInputStream::IstreamInputStream(std::istream* input, int block_size) + : copying_input_(input), impl_(©ing_input_, block_size) {} + +bool IstreamInputStream::Next(const void** data, int* size) { + return impl_.Next(data, size); +} + +void IstreamInputStream::BackUp(int count) { impl_.BackUp(count); } + +bool IstreamInputStream::Skip(int count) { return impl_.Skip(count); } + +int64_t IstreamInputStream::ByteCount() const { return impl_.ByteCount(); } + +IstreamInputStream::CopyingIstreamInputStream::CopyingIstreamInputStream( + std::istream* input) + : input_(input) {} + +IstreamInputStream::CopyingIstreamInputStream::~CopyingIstreamInputStream() {} + +int IstreamInputStream::CopyingIstreamInputStream::Read(void* buffer, + int size) { + input_->read(reinterpret_cast<char*>(buffer), size); + int result = input_->gcount(); + if (result == 0 && input_->fail() && !input_->eof()) { + return -1; + } + return result; +} + +// =================================================================== + +OstreamOutputStream::OstreamOutputStream(std::ostream* output, int block_size) + : copying_output_(output), impl_(©ing_output_, block_size) {} + +OstreamOutputStream::~OstreamOutputStream() { impl_.Flush(); } + +bool OstreamOutputStream::Next(void** data, int* size) { + return impl_.Next(data, size); +} + +void OstreamOutputStream::BackUp(int count) { impl_.BackUp(count); } + +int64_t OstreamOutputStream::ByteCount() const { return impl_.ByteCount(); } + +OstreamOutputStream::CopyingOstreamOutputStream::CopyingOstreamOutputStream( + std::ostream* output) + : output_(output) {} + +OstreamOutputStream::CopyingOstreamOutputStream::~CopyingOstreamOutputStream() { +} + +bool OstreamOutputStream::CopyingOstreamOutputStream::Write(const void* buffer, + int size) { + output_->write(reinterpret_cast<const char*>(buffer), size); + return output_->good(); +} + +// =================================================================== + +ConcatenatingInputStream::ConcatenatingInputStream( + ZeroCopyInputStream* const streams[], int count) + : streams_(streams), stream_count_(count), bytes_retired_(0) { +} + +bool ConcatenatingInputStream::Next(const void** data, int* size) { + while (stream_count_ > 0) { + if (streams_[0]->Next(data, size)) return true; + + // That stream is done. Advance to the next one. + bytes_retired_ += streams_[0]->ByteCount(); + ++streams_; + --stream_count_; + } + + // No more streams. + return false; +} + +void ConcatenatingInputStream::BackUp(int count) { + if (stream_count_ > 0) { + streams_[0]->BackUp(count); + } else { + GOOGLE_LOG(DFATAL) << "Can't BackUp() after failed Next()."; + } +} + +bool ConcatenatingInputStream::Skip(int count) { + while (stream_count_ > 0) { + // Assume that ByteCount() can be used to find out how much we actually + // skipped when Skip() fails. + int64_t target_byte_count = streams_[0]->ByteCount() + count; + if (streams_[0]->Skip(count)) return true; + + // Hit the end of the stream. Figure out how many more bytes we still have + // to skip. + int64_t final_byte_count = streams_[0]->ByteCount(); + GOOGLE_DCHECK_LT(final_byte_count, target_byte_count); + count = target_byte_count - final_byte_count; + + // That stream is done. Advance to the next one. + bytes_retired_ += final_byte_count; + ++streams_; + --stream_count_; + } + + return false; +} + +int64_t ConcatenatingInputStream::ByteCount() const { + if (stream_count_ == 0) { + return bytes_retired_; + } else { + return bytes_retired_ + streams_[0]->ByteCount(); + } +} + + +// =================================================================== + +} // namespace io +} // namespace protobuf +} // namespace google diff --git a/toolkit/components/protobuf/src/google/protobuf/io/zero_copy_stream_impl.h b/toolkit/components/protobuf/src/google/protobuf/io/zero_copy_stream_impl.h new file mode 100644 index 0000000000..a385992f20 --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/io/zero_copy_stream_impl.h @@ -0,0 +1,336 @@ +// 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. + +// Author: kenton@google.com (Kenton Varda) +// Based on original Protocol Buffers design by +// Sanjay Ghemawat, Jeff Dean, and others. +// +// This file contains common implementations of the interfaces defined in +// zero_copy_stream.h which are only included in the full (non-lite) +// protobuf library. These implementations include Unix file descriptors +// and C++ iostreams. See also: zero_copy_stream_impl_lite.h + +#ifndef GOOGLE_PROTOBUF_IO_ZERO_COPY_STREAM_IMPL_H__ +#define GOOGLE_PROTOBUF_IO_ZERO_COPY_STREAM_IMPL_H__ + + +#include <iosfwd> +#include <string> + +#include <google/protobuf/stubs/common.h> +#include <google/protobuf/io/zero_copy_stream.h> +#include <google/protobuf/io/zero_copy_stream_impl_lite.h> + +// Must be included last. +#include <google/protobuf/port_def.inc> + +namespace google { +namespace protobuf { +namespace io { + +// =================================================================== + +// A ZeroCopyInputStream which reads from a file descriptor. +// +// FileInputStream is preferred over using an ifstream with IstreamInputStream. +// The latter will introduce an extra layer of buffering, harming performance. +// Also, it's conceivable that FileInputStream could someday be enhanced +// to use zero-copy file descriptors on OSs which support them. +class PROTOBUF_EXPORT FileInputStream PROTOBUF_FUTURE_FINAL + : public ZeroCopyInputStream { + public: + // Creates a stream that reads from the given Unix file descriptor. + // If a block_size is given, it specifies the number of bytes that + // should be read and returned with each call to Next(). Otherwise, + // a reasonable default is used. + explicit FileInputStream(int file_descriptor, int block_size = -1); + + // Flushes any buffers and closes the underlying file. Returns false if + // an error occurs during the process; use GetErrno() to examine the error. + // Even if an error occurs, the file descriptor is closed when this returns. + bool Close(); + + // By default, the file descriptor is not closed when the stream is + // destroyed. Call SetCloseOnDelete(true) to change that. WARNING: + // This leaves no way for the caller to detect if close() fails. If + // detecting close() errors is important to you, you should arrange + // to close the descriptor yourself. + void SetCloseOnDelete(bool value) { copying_input_.SetCloseOnDelete(value); } + + // If an I/O error has occurred on this file descriptor, this is the + // errno from that error. Otherwise, this is zero. Once an error + // occurs, the stream is broken and all subsequent operations will + // fail. + int GetErrno() const { return copying_input_.GetErrno(); } + + // implements ZeroCopyInputStream ---------------------------------- + bool Next(const void** data, int* size) override; + void BackUp(int count) override; + bool Skip(int count) override; + int64_t ByteCount() const override; + + private: + class PROTOBUF_EXPORT CopyingFileInputStream PROTOBUF_FUTURE_FINAL + : public CopyingInputStream { + public: + CopyingFileInputStream(int file_descriptor); + ~CopyingFileInputStream() override; + + bool Close(); + void SetCloseOnDelete(bool value) { close_on_delete_ = value; } + int GetErrno() const { return errno_; } + + // implements CopyingInputStream --------------------------------- + int Read(void* buffer, int size) override; + int Skip(int count) override; + + private: + // The file descriptor. + const int file_; + bool close_on_delete_; + bool is_closed_; + + // The errno of the I/O error, if one has occurred. Otherwise, zero. + int errno_; + + // Did we try to seek once and fail? If so, we assume this file descriptor + // doesn't support seeking and won't try again. + bool previous_seek_failed_; + + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(CopyingFileInputStream); + }; + + CopyingFileInputStream copying_input_; + CopyingInputStreamAdaptor impl_; + + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FileInputStream); +}; + +// =================================================================== + +// A ZeroCopyOutputStream which writes to a file descriptor. +// +// FileOutputStream is preferred over using an ofstream with +// OstreamOutputStream. The latter will introduce an extra layer of buffering, +// harming performance. Also, it's conceivable that FileOutputStream could +// someday be enhanced to use zero-copy file descriptors on OSs which +// support them. +class PROTOBUF_EXPORT FileOutputStream PROTOBUF_FUTURE_FINAL + : public CopyingOutputStreamAdaptor { + public: + // Creates a stream that writes to the given Unix file descriptor. + // If a block_size is given, it specifies the size of the buffers + // that should be returned by Next(). Otherwise, a reasonable default + // is used. + explicit FileOutputStream(int file_descriptor, int block_size = -1); + + ~FileOutputStream() override; + + // Flushes any buffers and closes the underlying file. Returns false if + // an error occurs during the process; use GetErrno() to examine the error. + // Even if an error occurs, the file descriptor is closed when this returns. + bool Close(); + + // By default, the file descriptor is not closed when the stream is + // destroyed. Call SetCloseOnDelete(true) to change that. WARNING: + // This leaves no way for the caller to detect if close() fails. If + // detecting close() errors is important to you, you should arrange + // to close the descriptor yourself. + void SetCloseOnDelete(bool value) { copying_output_.SetCloseOnDelete(value); } + + // If an I/O error has occurred on this file descriptor, this is the + // errno from that error. Otherwise, this is zero. Once an error + // occurs, the stream is broken and all subsequent operations will + // fail. + int GetErrno() const { return copying_output_.GetErrno(); } + + private: + class PROTOBUF_EXPORT CopyingFileOutputStream PROTOBUF_FUTURE_FINAL + : public CopyingOutputStream { + public: + CopyingFileOutputStream(int file_descriptor); + ~CopyingFileOutputStream() override; + + bool Close(); + void SetCloseOnDelete(bool value) { close_on_delete_ = value; } + int GetErrno() const { return errno_; } + + // implements CopyingOutputStream -------------------------------- + bool Write(const void* buffer, int size) override; + + private: + // The file descriptor. + const int file_; + bool close_on_delete_; + bool is_closed_; + + // The errno of the I/O error, if one has occurred. Otherwise, zero. + int errno_; + + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(CopyingFileOutputStream); + }; + + CopyingFileOutputStream copying_output_; + + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FileOutputStream); +}; + +// =================================================================== + +// A ZeroCopyInputStream which reads from a C++ istream. +// +// Note that for reading files (or anything represented by a file descriptor), +// FileInputStream is more efficient. +class PROTOBUF_EXPORT IstreamInputStream PROTOBUF_FUTURE_FINAL + : public ZeroCopyInputStream { + public: + // Creates a stream that reads from the given C++ istream. + // If a block_size is given, it specifies the number of bytes that + // should be read and returned with each call to Next(). Otherwise, + // a reasonable default is used. + explicit IstreamInputStream(std::istream* stream, int block_size = -1); + + // implements ZeroCopyInputStream ---------------------------------- + bool Next(const void** data, int* size) override; + void BackUp(int count) override; + bool Skip(int count) override; + int64_t ByteCount() const override; + + private: + class PROTOBUF_EXPORT CopyingIstreamInputStream PROTOBUF_FUTURE_FINAL + : public CopyingInputStream { + public: + CopyingIstreamInputStream(std::istream* input); + ~CopyingIstreamInputStream() override; + + // implements CopyingInputStream --------------------------------- + int Read(void* buffer, int size) override; + // (We use the default implementation of Skip().) + + private: + // The stream. + std::istream* input_; + + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(CopyingIstreamInputStream); + }; + + CopyingIstreamInputStream copying_input_; + CopyingInputStreamAdaptor impl_; + + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(IstreamInputStream); +}; + +// =================================================================== + +// A ZeroCopyOutputStream which writes to a C++ ostream. +// +// Note that for writing files (or anything represented by a file descriptor), +// FileOutputStream is more efficient. +class PROTOBUF_EXPORT OstreamOutputStream PROTOBUF_FUTURE_FINAL + : public ZeroCopyOutputStream { + public: + // Creates a stream that writes to the given C++ ostream. + // If a block_size is given, it specifies the size of the buffers + // that should be returned by Next(). Otherwise, a reasonable default + // is used. + explicit OstreamOutputStream(std::ostream* stream, int block_size = -1); + ~OstreamOutputStream() override; + + // implements ZeroCopyOutputStream --------------------------------- + bool Next(void** data, int* size) override; + void BackUp(int count) override; + int64_t ByteCount() const override; + + private: + class PROTOBUF_EXPORT CopyingOstreamOutputStream PROTOBUF_FUTURE_FINAL + : public CopyingOutputStream { + public: + CopyingOstreamOutputStream(std::ostream* output); + ~CopyingOstreamOutputStream() override; + + // implements CopyingOutputStream -------------------------------- + bool Write(const void* buffer, int size) override; + + private: + // The stream. + std::ostream* output_; + + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(CopyingOstreamOutputStream); + }; + + CopyingOstreamOutputStream copying_output_; + CopyingOutputStreamAdaptor impl_; + + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(OstreamOutputStream); +}; + +// =================================================================== + +// A ZeroCopyInputStream which reads from several other streams in sequence. +// ConcatenatingInputStream is unable to distinguish between end-of-stream +// and read errors in the underlying streams, so it assumes any errors mean +// end-of-stream. So, if the underlying streams fail for any other reason, +// ConcatenatingInputStream may do odd things. It is suggested that you do +// not use ConcatenatingInputStream on streams that might produce read errors +// other than end-of-stream. +class PROTOBUF_EXPORT ConcatenatingInputStream PROTOBUF_FUTURE_FINAL + : public ZeroCopyInputStream { + public: + // All streams passed in as well as the array itself must remain valid + // until the ConcatenatingInputStream is destroyed. + ConcatenatingInputStream(ZeroCopyInputStream* const streams[], int count); + ~ConcatenatingInputStream() override = default; + + // implements ZeroCopyInputStream ---------------------------------- + bool Next(const void** data, int* size) override; + void BackUp(int count) override; + bool Skip(int count) override; + int64_t ByteCount() const override; + + + private: + // As streams are retired, streams_ is incremented and count_ is + // decremented. + ZeroCopyInputStream* const* streams_; + int stream_count_; + int64_t bytes_retired_; // Bytes read from previous streams. + + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ConcatenatingInputStream); +}; + +// =================================================================== + +} // namespace io +} // namespace protobuf +} // namespace google + +#include <google/protobuf/port_undef.inc> + +#endif // GOOGLE_PROTOBUF_IO_ZERO_COPY_STREAM_IMPL_H__ diff --git a/toolkit/components/protobuf/src/google/protobuf/io/zero_copy_stream_impl_lite.cc b/toolkit/components/protobuf/src/google/protobuf/io/zero_copy_stream_impl_lite.cc new file mode 100644 index 0000000000..b3dfd84c7f --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/io/zero_copy_stream_impl_lite.cc @@ -0,0 +1,470 @@ +// 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. + +// Author: kenton@google.com (Kenton Varda) +// Based on original Protocol Buffers design by +// Sanjay Ghemawat, Jeff Dean, and others. + +#include <google/protobuf/io/zero_copy_stream_impl_lite.h> + +#include <algorithm> +#include <limits> + +#include <google/protobuf/stubs/common.h> +#include <google/protobuf/stubs/logging.h> +#include <google/protobuf/stubs/casts.h> +#include <google/protobuf/stubs/stl_util.h> + +namespace google { +namespace protobuf { +namespace io { + +namespace { + +// Default block size for Copying{In,Out}putStreamAdaptor. +static const int kDefaultBlockSize = 8192; + +} // namespace + +// =================================================================== + +ArrayInputStream::ArrayInputStream(const void* data, int size, int block_size) + : data_(reinterpret_cast<const uint8_t*>(data)), + size_(size), + block_size_(block_size > 0 ? block_size : size), + position_(0), + last_returned_size_(0) {} + +bool ArrayInputStream::Next(const void** data, int* size) { + if (position_ < size_) { + last_returned_size_ = std::min(block_size_, size_ - position_); + *data = data_ + position_; + *size = last_returned_size_; + position_ += last_returned_size_; + return true; + } else { + // We're at the end of the array. + last_returned_size_ = 0; // Don't let caller back up. + return false; + } +} + +void ArrayInputStream::BackUp(int count) { + GOOGLE_CHECK_GT(last_returned_size_, 0) + << "BackUp() can only be called after a successful Next()."; + GOOGLE_CHECK_LE(count, last_returned_size_); + GOOGLE_CHECK_GE(count, 0); + position_ -= count; + last_returned_size_ = 0; // Don't let caller back up further. +} + +bool ArrayInputStream::Skip(int count) { + GOOGLE_CHECK_GE(count, 0); + last_returned_size_ = 0; // Don't let caller back up. + if (count > size_ - position_) { + position_ = size_; + return false; + } else { + position_ += count; + return true; + } +} + +int64_t ArrayInputStream::ByteCount() const { return position_; } + + +// =================================================================== + +ArrayOutputStream::ArrayOutputStream(void* data, int size, int block_size) + : data_(reinterpret_cast<uint8_t*>(data)), + size_(size), + block_size_(block_size > 0 ? block_size : size), + position_(0), + last_returned_size_(0) {} + +bool ArrayOutputStream::Next(void** data, int* size) { + if (position_ < size_) { + last_returned_size_ = std::min(block_size_, size_ - position_); + *data = data_ + position_; + *size = last_returned_size_; + position_ += last_returned_size_; + return true; + } else { + // We're at the end of the array. + last_returned_size_ = 0; // Don't let caller back up. + return false; + } +} + +void ArrayOutputStream::BackUp(int count) { + GOOGLE_CHECK_LE(count, last_returned_size_) + << "BackUp() can not exceed the size of the last Next() call."; + GOOGLE_CHECK_GE(count, 0); + position_ -= count; + last_returned_size_ -= count; +} + +int64_t ArrayOutputStream::ByteCount() const { return position_; } + +// =================================================================== + +StringOutputStream::StringOutputStream(std::string* target) : target_(target) {} + +bool StringOutputStream::Next(void** data, int* size) { + GOOGLE_CHECK(target_ != NULL); + size_t old_size = target_->size(); + + // Grow the string. + size_t new_size; + if (old_size < target_->capacity()) { + // Resize the string to match its capacity, since we can get away + // without a memory allocation this way. + new_size = target_->capacity(); + } else { + // Size has reached capacity, try to double it. + new_size = old_size * 2; + } + // Avoid integer overflow in returned '*size'. + new_size = std::min(new_size, old_size + std::numeric_limits<int>::max()); + // Increase the size, also make sure that it is at least kMinimumSize. + STLStringResizeUninitialized( + target_, + std::max(new_size, + kMinimumSize + 0)); // "+ 0" works around GCC4 weirdness. + + *data = mutable_string_data(target_) + old_size; + *size = target_->size() - old_size; + return true; +} + +void StringOutputStream::BackUp(int count) { + GOOGLE_CHECK_GE(count, 0); + GOOGLE_CHECK(target_ != NULL); + GOOGLE_CHECK_LE(static_cast<size_t>(count), target_->size()); + target_->resize(target_->size() - count); +} + +int64_t StringOutputStream::ByteCount() const { + GOOGLE_CHECK(target_ != NULL); + return target_->size(); +} + +// =================================================================== + +int CopyingInputStream::Skip(int count) { + char junk[4096]; + int skipped = 0; + while (skipped < count) { + int bytes = Read(junk, std::min(count - skipped, + implicit_cast<int>(sizeof(junk)))); + if (bytes <= 0) { + // EOF or read error. + return skipped; + } + skipped += bytes; + } + return skipped; +} + +CopyingInputStreamAdaptor::CopyingInputStreamAdaptor( + CopyingInputStream* copying_stream, int block_size) + : copying_stream_(copying_stream), + owns_copying_stream_(false), + failed_(false), + position_(0), + buffer_size_(block_size > 0 ? block_size : kDefaultBlockSize), + buffer_used_(0), + backup_bytes_(0) {} + +CopyingInputStreamAdaptor::~CopyingInputStreamAdaptor() { + if (owns_copying_stream_) { + delete copying_stream_; + } +} + +bool CopyingInputStreamAdaptor::Next(const void** data, int* size) { + if (failed_) { + // Already failed on a previous read. + return false; + } + + AllocateBufferIfNeeded(); + + if (backup_bytes_ > 0) { + // We have data left over from a previous BackUp(), so just return that. + *data = buffer_.get() + buffer_used_ - backup_bytes_; + *size = backup_bytes_; + backup_bytes_ = 0; + return true; + } + + // Read new data into the buffer. + buffer_used_ = copying_stream_->Read(buffer_.get(), buffer_size_); + if (buffer_used_ <= 0) { + // EOF or read error. We don't need the buffer anymore. + if (buffer_used_ < 0) { + // Read error (not EOF). + failed_ = true; + } + FreeBuffer(); + return false; + } + position_ += buffer_used_; + + *size = buffer_used_; + *data = buffer_.get(); + return true; +} + +void CopyingInputStreamAdaptor::BackUp(int count) { + GOOGLE_CHECK(backup_bytes_ == 0 && buffer_.get() != NULL) + << " BackUp() can only be called after Next()."; + GOOGLE_CHECK_LE(count, buffer_used_) + << " Can't back up over more bytes than were returned by the last call" + " to Next()."; + GOOGLE_CHECK_GE(count, 0) << " Parameter to BackUp() can't be negative."; + + backup_bytes_ = count; +} + +bool CopyingInputStreamAdaptor::Skip(int count) { + GOOGLE_CHECK_GE(count, 0); + + if (failed_) { + // Already failed on a previous read. + return false; + } + + // First skip any bytes left over from a previous BackUp(). + if (backup_bytes_ >= count) { + // We have more data left over than we're trying to skip. Just chop it. + backup_bytes_ -= count; + return true; + } + + count -= backup_bytes_; + backup_bytes_ = 0; + + int skipped = copying_stream_->Skip(count); + position_ += skipped; + return skipped == count; +} + +int64_t CopyingInputStreamAdaptor::ByteCount() const { + return position_ - backup_bytes_; +} + +void CopyingInputStreamAdaptor::AllocateBufferIfNeeded() { + if (buffer_.get() == NULL) { + buffer_.reset(new uint8_t[buffer_size_]); + } +} + +void CopyingInputStreamAdaptor::FreeBuffer() { + GOOGLE_CHECK_EQ(backup_bytes_, 0); + buffer_used_ = 0; + buffer_.reset(); +} + +// =================================================================== + +CopyingOutputStreamAdaptor::CopyingOutputStreamAdaptor( + CopyingOutputStream* copying_stream, int block_size) + : copying_stream_(copying_stream), + owns_copying_stream_(false), + failed_(false), + position_(0), + buffer_size_(block_size > 0 ? block_size : kDefaultBlockSize), + buffer_used_(0) {} + +CopyingOutputStreamAdaptor::~CopyingOutputStreamAdaptor() { + WriteBuffer(); + if (owns_copying_stream_) { + delete copying_stream_; + } +} + +bool CopyingOutputStreamAdaptor::Flush() { return WriteBuffer(); } + +bool CopyingOutputStreamAdaptor::Next(void** data, int* size) { + if (buffer_used_ == buffer_size_) { + if (!WriteBuffer()) return false; + } + + AllocateBufferIfNeeded(); + + *data = buffer_.get() + buffer_used_; + *size = buffer_size_ - buffer_used_; + buffer_used_ = buffer_size_; + return true; +} + +void CopyingOutputStreamAdaptor::BackUp(int count) { + if (count == 0) { + Flush(); + return; + } + GOOGLE_CHECK_GE(count, 0); + GOOGLE_CHECK_EQ(buffer_used_, buffer_size_) + << " BackUp() can only be called after Next()."; + GOOGLE_CHECK_LE(count, buffer_used_) + << " Can't back up over more bytes than were returned by the last call" + " to Next()."; + + buffer_used_ -= count; +} + +int64_t CopyingOutputStreamAdaptor::ByteCount() const { + return position_ + buffer_used_; +} + +bool CopyingOutputStreamAdaptor::WriteAliasedRaw(const void* data, int size) { + if (size >= buffer_size_) { + if (!Flush() || !copying_stream_->Write(data, size)) { + return false; + } + GOOGLE_DCHECK_EQ(buffer_used_, 0); + position_ += size; + return true; + } + + void* out; + int out_size; + while (true) { + if (!Next(&out, &out_size)) { + return false; + } + + if (size <= out_size) { + std::memcpy(out, data, size); + BackUp(out_size - size); + return true; + } + + std::memcpy(out, data, out_size); + data = static_cast<const char*>(data) + out_size; + size -= out_size; + } + return true; +} + + +bool CopyingOutputStreamAdaptor::WriteBuffer() { + if (failed_) { + // Already failed on a previous write. + return false; + } + + if (buffer_used_ == 0) return true; + + if (copying_stream_->Write(buffer_.get(), buffer_used_)) { + position_ += buffer_used_; + buffer_used_ = 0; + return true; + } else { + failed_ = true; + FreeBuffer(); + return false; + } +} + +void CopyingOutputStreamAdaptor::AllocateBufferIfNeeded() { + if (buffer_ == NULL) { + buffer_.reset(new uint8_t[buffer_size_]); + } +} + +void CopyingOutputStreamAdaptor::FreeBuffer() { + buffer_used_ = 0; + buffer_.reset(); +} + +// =================================================================== + +LimitingInputStream::LimitingInputStream(ZeroCopyInputStream* input, + int64_t limit) + : input_(input), limit_(limit) { + prior_bytes_read_ = input_->ByteCount(); +} + +LimitingInputStream::~LimitingInputStream() { + // If we overshot the limit, back up. + if (limit_ < 0) input_->BackUp(-limit_); +} + +bool LimitingInputStream::Next(const void** data, int* size) { + if (limit_ <= 0) return false; + if (!input_->Next(data, size)) return false; + + limit_ -= *size; + if (limit_ < 0) { + // We overshot the limit. Reduce *size to hide the rest of the buffer. + *size += limit_; + } + return true; +} + +void LimitingInputStream::BackUp(int count) { + if (limit_ < 0) { + input_->BackUp(count - limit_); + limit_ = count; + } else { + input_->BackUp(count); + limit_ += count; + } +} + +bool LimitingInputStream::Skip(int count) { + if (count > limit_) { + if (limit_ < 0) return false; + input_->Skip(limit_); + limit_ = 0; + return false; + } else { + if (!input_->Skip(count)) return false; + limit_ -= count; + return true; + } +} + +int64_t LimitingInputStream::ByteCount() const { + if (limit_ < 0) { + return input_->ByteCount() + limit_ - prior_bytes_read_; + } else { + return input_->ByteCount() - prior_bytes_read_; + } +} + + +// =================================================================== + +} // namespace io +} // namespace protobuf +} // namespace google diff --git a/toolkit/components/protobuf/src/google/protobuf/io/zero_copy_stream_impl_lite.h b/toolkit/components/protobuf/src/google/protobuf/io/zero_copy_stream_impl_lite.h new file mode 100644 index 0000000000..cbda32871e --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/io/zero_copy_stream_impl_lite.h @@ -0,0 +1,413 @@ +// 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. + +// Author: kenton@google.com (Kenton Varda) +// Based on original Protocol Buffers design by +// Sanjay Ghemawat, Jeff Dean, and others. +// +// This file contains common implementations of the interfaces defined in +// zero_copy_stream.h which are included in the "lite" protobuf library. +// These implementations cover I/O on raw arrays and strings, as well as +// adaptors which make it easy to implement streams based on traditional +// streams. Of course, many users will probably want to write their own +// implementations of these interfaces specific to the particular I/O +// abstractions they prefer to use, but these should cover the most common +// cases. + +#ifndef GOOGLE_PROTOBUF_IO_ZERO_COPY_STREAM_IMPL_LITE_H__ +#define GOOGLE_PROTOBUF_IO_ZERO_COPY_STREAM_IMPL_LITE_H__ + + +#include <iosfwd> +#include <memory> +#include <string> + +#include <google/protobuf/stubs/callback.h> +#include <google/protobuf/stubs/common.h> +#include <google/protobuf/io/zero_copy_stream.h> +#include <google/protobuf/stubs/stl_util.h> + + +// Must be included last. +#include <google/protobuf/port_def.inc> + +namespace google { +namespace protobuf { +namespace io { + +// =================================================================== + +// A ZeroCopyInputStream backed by an in-memory array of bytes. +class PROTOBUF_EXPORT ArrayInputStream PROTOBUF_FUTURE_FINAL + : public ZeroCopyInputStream { + public: + // Create an InputStream that returns the bytes pointed to by "data". + // "data" remains the property of the caller but must remain valid until + // the stream is destroyed. If a block_size is given, calls to Next() + // will return data blocks no larger than the given size. Otherwise, the + // first call to Next() returns the entire array. block_size is mainly + // useful for testing; in production you would probably never want to set + // it. + ArrayInputStream(const void* data, int size, int block_size = -1); + ~ArrayInputStream() override = default; + + // implements ZeroCopyInputStream ---------------------------------- + bool Next(const void** data, int* size) override; + void BackUp(int count) override; + bool Skip(int count) override; + int64_t ByteCount() const override; + + + private: + const uint8_t* const data_; // The byte array. + const int size_; // Total size of the array. + const int block_size_; // How many bytes to return at a time. + + int position_; + int last_returned_size_; // How many bytes we returned last time Next() + // was called (used for error checking only). + + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ArrayInputStream); +}; + +// =================================================================== + +// A ZeroCopyOutputStream backed by an in-memory array of bytes. +class PROTOBUF_EXPORT ArrayOutputStream PROTOBUF_FUTURE_FINAL + : public ZeroCopyOutputStream { + public: + // Create an OutputStream that writes to the bytes pointed to by "data". + // "data" remains the property of the caller but must remain valid until + // the stream is destroyed. If a block_size is given, calls to Next() + // will return data blocks no larger than the given size. Otherwise, the + // first call to Next() returns the entire array. block_size is mainly + // useful for testing; in production you would probably never want to set + // it. + ArrayOutputStream(void* data, int size, int block_size = -1); + ~ArrayOutputStream() override = default; + + // implements ZeroCopyOutputStream --------------------------------- + bool Next(void** data, int* size) override; + void BackUp(int count) override; + int64_t ByteCount() const override; + + private: + uint8_t* const data_; // The byte array. + const int size_; // Total size of the array. + const int block_size_; // How many bytes to return at a time. + + int position_; + int last_returned_size_; // How many bytes we returned last time Next() + // was called (used for error checking only). + + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ArrayOutputStream); +}; + +// =================================================================== + +// A ZeroCopyOutputStream which appends bytes to a string. +class PROTOBUF_EXPORT StringOutputStream PROTOBUF_FUTURE_FINAL + : public ZeroCopyOutputStream { + public: + // Create a StringOutputStream which appends bytes to the given string. + // The string remains property of the caller, but it is mutated in arbitrary + // ways and MUST NOT be accessed in any way until you're done with the + // stream. Either be sure there's no further usage, or (safest) destroy the + // stream before using the contents. + // + // Hint: If you call target->reserve(n) before creating the stream, + // the first call to Next() will return at least n bytes of buffer + // space. + explicit StringOutputStream(std::string* target); + ~StringOutputStream() override = default; + + // implements ZeroCopyOutputStream --------------------------------- + bool Next(void** data, int* size) override; + void BackUp(int count) override; + int64_t ByteCount() const override; + + private: + static constexpr size_t kMinimumSize = 16; + + std::string* target_; + + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(StringOutputStream); +}; + +// Note: There is no StringInputStream. Instead, just create an +// ArrayInputStream as follows: +// ArrayInputStream input(str.data(), str.size()); + +// =================================================================== + +// A generic traditional input stream interface. +// +// Lots of traditional input streams (e.g. file descriptors, C stdio +// streams, and C++ iostreams) expose an interface where every read +// involves copying bytes into a buffer. If you want to take such an +// interface and make a ZeroCopyInputStream based on it, simply implement +// CopyingInputStream and then use CopyingInputStreamAdaptor. +// +// CopyingInputStream implementations should avoid buffering if possible. +// CopyingInputStreamAdaptor does its own buffering and will read data +// in large blocks. +class PROTOBUF_EXPORT CopyingInputStream { + public: + virtual ~CopyingInputStream() {} + + // Reads up to "size" bytes into the given buffer. Returns the number of + // bytes read. Read() waits until at least one byte is available, or + // returns zero if no bytes will ever become available (EOF), or -1 if a + // permanent read error occurred. + virtual int Read(void* buffer, int size) = 0; + + // Skips the next "count" bytes of input. Returns the number of bytes + // actually skipped. This will always be exactly equal to "count" unless + // EOF was reached or a permanent read error occurred. + // + // The default implementation just repeatedly calls Read() into a scratch + // buffer. + virtual int Skip(int count); +}; + +// A ZeroCopyInputStream which reads from a CopyingInputStream. This is +// useful for implementing ZeroCopyInputStreams that read from traditional +// streams. Note that this class is not really zero-copy. +// +// If you want to read from file descriptors or C++ istreams, this is +// already implemented for you: use FileInputStream or IstreamInputStream +// respectively. +class PROTOBUF_EXPORT CopyingInputStreamAdaptor : public ZeroCopyInputStream { + public: + // Creates a stream that reads from the given CopyingInputStream. + // If a block_size is given, it specifies the number of bytes that + // should be read and returned with each call to Next(). Otherwise, + // a reasonable default is used. The caller retains ownership of + // copying_stream unless SetOwnsCopyingStream(true) is called. + explicit CopyingInputStreamAdaptor(CopyingInputStream* copying_stream, + int block_size = -1); + ~CopyingInputStreamAdaptor() override; + + // Call SetOwnsCopyingStream(true) to tell the CopyingInputStreamAdaptor to + // delete the underlying CopyingInputStream when it is destroyed. + void SetOwnsCopyingStream(bool value) { owns_copying_stream_ = value; } + + // implements ZeroCopyInputStream ---------------------------------- + bool Next(const void** data, int* size) override; + void BackUp(int count) override; + bool Skip(int count) override; + int64_t ByteCount() const override; + + private: + // Insures that buffer_ is not NULL. + void AllocateBufferIfNeeded(); + // Frees the buffer and resets buffer_used_. + void FreeBuffer(); + + // The underlying copying stream. + CopyingInputStream* copying_stream_; + bool owns_copying_stream_; + + // True if we have seen a permanent error from the underlying stream. + bool failed_; + + // The current position of copying_stream_, relative to the point where + // we started reading. + int64_t position_; + + // Data is read into this buffer. It may be NULL if no buffer is currently + // in use. Otherwise, it points to an array of size buffer_size_. + std::unique_ptr<uint8_t[]> buffer_; + const int buffer_size_; + + // Number of valid bytes currently in the buffer (i.e. the size last + // returned by Next()). 0 <= buffer_used_ <= buffer_size_. + int buffer_used_; + + // Number of bytes in the buffer which were backed up over by a call to + // BackUp(). These need to be returned again. + // 0 <= backup_bytes_ <= buffer_used_ + int backup_bytes_; + + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(CopyingInputStreamAdaptor); +}; + +// =================================================================== + +// A generic traditional output stream interface. +// +// Lots of traditional output streams (e.g. file descriptors, C stdio +// streams, and C++ iostreams) expose an interface where every write +// involves copying bytes from a buffer. If you want to take such an +// interface and make a ZeroCopyOutputStream based on it, simply implement +// CopyingOutputStream and then use CopyingOutputStreamAdaptor. +// +// CopyingOutputStream implementations should avoid buffering if possible. +// CopyingOutputStreamAdaptor does its own buffering and will write data +// in large blocks. +class PROTOBUF_EXPORT CopyingOutputStream { + public: + virtual ~CopyingOutputStream() {} + + // Writes "size" bytes from the given buffer to the output. Returns true + // if successful, false on a write error. + virtual bool Write(const void* buffer, int size) = 0; +}; + +// A ZeroCopyOutputStream which writes to a CopyingOutputStream. This is +// useful for implementing ZeroCopyOutputStreams that write to traditional +// streams. Note that this class is not really zero-copy. +// +// If you want to write to file descriptors or C++ ostreams, this is +// already implemented for you: use FileOutputStream or OstreamOutputStream +// respectively. +class PROTOBUF_EXPORT CopyingOutputStreamAdaptor : public ZeroCopyOutputStream { + public: + // Creates a stream that writes to the given Unix file descriptor. + // If a block_size is given, it specifies the size of the buffers + // that should be returned by Next(). Otherwise, a reasonable default + // is used. + explicit CopyingOutputStreamAdaptor(CopyingOutputStream* copying_stream, + int block_size = -1); + ~CopyingOutputStreamAdaptor() override; + + // Writes all pending data to the underlying stream. Returns false if a + // write error occurred on the underlying stream. (The underlying + // stream itself is not necessarily flushed.) + bool Flush(); + + // Call SetOwnsCopyingStream(true) to tell the CopyingOutputStreamAdaptor to + // delete the underlying CopyingOutputStream when it is destroyed. + void SetOwnsCopyingStream(bool value) { owns_copying_stream_ = value; } + + // implements ZeroCopyOutputStream --------------------------------- + bool Next(void** data, int* size) override; + void BackUp(int count) override; + int64_t ByteCount() const override; + bool WriteAliasedRaw(const void* data, int size) override; + bool AllowsAliasing() const override { return true; } + + private: + // Write the current buffer, if it is present. + bool WriteBuffer(); + // Insures that buffer_ is not NULL. + void AllocateBufferIfNeeded(); + // Frees the buffer. + void FreeBuffer(); + + // The underlying copying stream. + CopyingOutputStream* copying_stream_; + bool owns_copying_stream_; + + // True if we have seen a permanent error from the underlying stream. + bool failed_; + + // The current position of copying_stream_, relative to the point where + // we started writing. + int64_t position_; + + // Data is written from this buffer. It may be NULL if no buffer is + // currently in use. Otherwise, it points to an array of size buffer_size_. + std::unique_ptr<uint8_t[]> buffer_; + const int buffer_size_; + + // Number of valid bytes currently in the buffer (i.e. the size last + // returned by Next()). When BackUp() is called, we just reduce this. + // 0 <= buffer_used_ <= buffer_size_. + int buffer_used_; + + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(CopyingOutputStreamAdaptor); +}; + +// =================================================================== + +// A ZeroCopyInputStream which wraps some other stream and limits it to +// a particular byte count. +class PROTOBUF_EXPORT LimitingInputStream PROTOBUF_FUTURE_FINAL + : public ZeroCopyInputStream { + public: + LimitingInputStream(ZeroCopyInputStream* input, int64_t limit); + ~LimitingInputStream() override; + + // implements ZeroCopyInputStream ---------------------------------- + bool Next(const void** data, int* size) override; + void BackUp(int count) override; + bool Skip(int count) override; + int64_t ByteCount() const override; + + + private: + ZeroCopyInputStream* input_; + int64_t limit_; // Decreases as we go, becomes negative if we overshoot. + int64_t prior_bytes_read_; // Bytes read on underlying stream at construction + + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(LimitingInputStream); +}; + + +// =================================================================== + +// mutable_string_data() and as_string_data() are workarounds to improve +// the performance of writing new data to an existing string. Unfortunately +// the methods provided by the string class are suboptimal, and using memcpy() +// is mildly annoying because it requires its pointer args to be non-NULL even +// if we ask it to copy 0 bytes. Furthermore, string_as_array() has the +// property that it always returns NULL if its arg is the empty string, exactly +// what we want to avoid if we're using it in conjunction with memcpy()! +// With C++11, the desired memcpy() boils down to memcpy(..., &(*s)[0], size), +// where s is a string*. Without C++11, &(*s)[0] is not guaranteed to be safe, +// so we use string_as_array(), and live with the extra logic that tests whether +// *s is empty. + +// Return a pointer to mutable characters underlying the given string. The +// return value is valid until the next time the string is resized. We +// trust the caller to treat the return value as an array of length s->size(). +inline char* mutable_string_data(std::string* s) { + // This should be simpler & faster than string_as_array() because the latter + // is guaranteed to return NULL when *s is empty, so it has to check for that. + return &(*s)[0]; +} + +// as_string_data(s) is equivalent to +// ({ char* p = mutable_string_data(s); make_pair(p, p != NULL); }) +// Sometimes it's faster: in some scenarios p cannot be NULL, and then the +// code can avoid that check. +inline std::pair<char*, bool> as_string_data(std::string* s) { + char* p = mutable_string_data(s); + return std::make_pair(p, true); +} + +} // namespace io +} // namespace protobuf +} // namespace google + +#include <google/protobuf/port_undef.inc> + +#endif // GOOGLE_PROTOBUF_IO_ZERO_COPY_STREAM_IMPL_LITE_H__ diff --git a/toolkit/components/protobuf/src/google/protobuf/map.cc b/toolkit/components/protobuf/src/google/protobuf/map.cc new file mode 100644 index 0000000000..d60a9a285c --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/map.cc @@ -0,0 +1,41 @@ +// 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. + +#include <google/protobuf/map.h> + +namespace google { +namespace protobuf { +namespace internal { + +void* const kGlobalEmptyTable[kGlobalEmptyTableSize] = {nullptr}; + +} // namespace internal +} // namespace protobuf +} // namespace google diff --git a/toolkit/components/protobuf/src/google/protobuf/map.h b/toolkit/components/protobuf/src/google/protobuf/map.h new file mode 100644 index 0000000000..008c192253 --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/map.h @@ -0,0 +1,1448 @@ +// 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. + +// This file defines the map container and its helpers to support protobuf maps. +// +// The Map and MapIterator types are provided by this header file. +// Please avoid using other types defined here, unless they are public +// types within Map or MapIterator, such as Map::value_type. + +#ifndef GOOGLE_PROTOBUF_MAP_H__ +#define GOOGLE_PROTOBUF_MAP_H__ + + +#include <functional> +#include <initializer_list> +#include <iterator> +#include <limits> // To support Visual Studio 2008 +#include <map> +#include <string> +#include <type_traits> +#include <utility> + +#if defined(__cpp_lib_string_view) +#include <string_view> +#endif // defined(__cpp_lib_string_view) + +#if !defined(GOOGLE_PROTOBUF_NO_RDTSC) && defined(__APPLE__) +#include <mach/mach_time.h> +#endif + +#include <google/protobuf/stubs/common.h> +#include <google/protobuf/arena.h> +#include <google/protobuf/generated_enum_util.h> +#include <google/protobuf/map_type_handler.h> +#include <google/protobuf/port.h> +#include <google/protobuf/stubs/hash.h> + +#ifdef SWIG +#error "You cannot SWIG proto headers" +#endif + +// Must be included last. +#include <google/protobuf/port_def.inc> + +namespace google { +namespace protobuf { + +template <typename Key, typename T> +class Map; + +class MapIterator; + +template <typename Enum> +struct is_proto_enum; + +namespace internal { +template <typename Derived, typename Key, typename T, + WireFormatLite::FieldType key_wire_type, + WireFormatLite::FieldType value_wire_type> +class MapFieldLite; + +template <typename Derived, typename Key, typename T, + WireFormatLite::FieldType key_wire_type, + WireFormatLite::FieldType value_wire_type> +class MapField; + +template <typename Key, typename T> +class TypeDefinedMapFieldBase; + +class DynamicMapField; + +class GeneratedMessageReflection; + +// re-implement std::allocator to use arena allocator for memory allocation. +// Used for Map implementation. Users should not use this class +// directly. +template <typename U> +class MapAllocator { + public: + using value_type = U; + using pointer = value_type*; + using const_pointer = const value_type*; + using reference = value_type&; + using const_reference = const value_type&; + using size_type = size_t; + using difference_type = ptrdiff_t; + + constexpr MapAllocator() : arena_(nullptr) {} + explicit constexpr MapAllocator(Arena* arena) : arena_(arena) {} + template <typename X> + MapAllocator(const MapAllocator<X>& allocator) // NOLINT(runtime/explicit) + : arena_(allocator.arena()) {} + + // MapAllocator does not support alignments beyond 8. Technically we should + // support up to std::max_align_t, but this fails with ubsan and tcmalloc + // debug allocation logic which assume 8 as default alignment. + static_assert(alignof(value_type) <= 8, ""); + + pointer allocate(size_type n, const void* /* hint */ = nullptr) { + // If arena is not given, malloc needs to be called which doesn't + // construct element object. + if (arena_ == nullptr) { + return static_cast<pointer>(::operator new(n * sizeof(value_type))); + } else { + return reinterpret_cast<pointer>( + Arena::CreateArray<uint8_t>(arena_, n * sizeof(value_type))); + } + } + + void deallocate(pointer p, size_type n) { + if (arena_ == nullptr) { + internal::SizedDelete(p, n * sizeof(value_type)); + } + } + +#if !defined(GOOGLE_PROTOBUF_OS_APPLE) && !defined(GOOGLE_PROTOBUF_OS_NACL) && \ + !defined(GOOGLE_PROTOBUF_OS_EMSCRIPTEN) + template <class NodeType, class... Args> + void construct(NodeType* p, Args&&... args) { + // Clang 3.6 doesn't compile static casting to void* directly. (Issue + // #1266) According C++ standard 5.2.9/1: "The static_cast operator shall + // not cast away constness". So first the maybe const pointer is casted to + // const void* and after the const void* is const casted. + new (const_cast<void*>(static_cast<const void*>(p))) + NodeType(std::forward<Args>(args)...); + } + + template <class NodeType> + void destroy(NodeType* p) { + p->~NodeType(); + } +#else + void construct(pointer p, const_reference t) { new (p) value_type(t); } + + void destroy(pointer p) { p->~value_type(); } +#endif + + template <typename X> + struct rebind { + using other = MapAllocator<X>; + }; + + template <typename X> + bool operator==(const MapAllocator<X>& other) const { + return arena_ == other.arena_; + } + + template <typename X> + bool operator!=(const MapAllocator<X>& other) const { + return arena_ != other.arena_; + } + + // To support Visual Studio 2008 + size_type max_size() const { + // parentheses around (std::...:max) prevents macro warning of max() + return (std::numeric_limits<size_type>::max)(); + } + + // To support gcc-4.4, which does not properly + // support templated friend classes + Arena* arena() const { return arena_; } + + private: + using DestructorSkippable_ = void; + Arena* arena_; +}; + +template <typename T> +using KeyForTree = + typename std::conditional<std::is_scalar<T>::value, T, + std::reference_wrapper<const T>>::type; + +// Default case: Not transparent. +// We use std::hash<key_type>/std::less<key_type> and all the lookup functions +// only accept `key_type`. +template <typename key_type> +struct TransparentSupport { + using hash = std::hash<key_type>; + using less = std::less<key_type>; + + static bool Equals(const key_type& a, const key_type& b) { return a == b; } + + template <typename K> + using key_arg = key_type; +}; + +#if defined(__cpp_lib_string_view) +// If std::string_view is available, we add transparent support for std::string +// keys. We use std::hash<std::string_view> as it supports the input types we +// care about. The lookup functions accept arbitrary `K`. This will include any +// key type that is convertible to std::string_view. +template <> +struct TransparentSupport<std::string> { + static std::string_view ImplicitConvert(std::string_view str) { return str; } + // If the element is not convertible to std::string_view, try to convert to + // std::string first. + // The template makes this overload lose resolution when both have the same + // rank otherwise. + template <typename = void> + static std::string_view ImplicitConvert(const std::string& str) { + return str; + } + + struct hash : private std::hash<std::string_view> { + using is_transparent = void; + + template <typename T> + size_t operator()(const T& str) const { + return base()(ImplicitConvert(str)); + } + + private: + const std::hash<std::string_view>& base() const { return *this; } + }; + struct less { + using is_transparent = void; + + template <typename T, typename U> + bool operator()(const T& t, const U& u) const { + return ImplicitConvert(t) < ImplicitConvert(u); + } + }; + + template <typename T, typename U> + static bool Equals(const T& t, const U& u) { + return ImplicitConvert(t) == ImplicitConvert(u); + } + + template <typename K> + using key_arg = K; +}; +#endif // defined(__cpp_lib_string_view) + +template <typename Key> +using TreeForMap = + std::map<KeyForTree<Key>, void*, typename TransparentSupport<Key>::less, + MapAllocator<std::pair<const KeyForTree<Key>, void*>>>; + +inline bool TableEntryIsEmpty(void* const* table, size_t b) { + return table[b] == nullptr; +} +inline bool TableEntryIsNonEmptyList(void* const* table, size_t b) { + return table[b] != nullptr && table[b] != table[b ^ 1]; +} +inline bool TableEntryIsTree(void* const* table, size_t b) { + return !TableEntryIsEmpty(table, b) && !TableEntryIsNonEmptyList(table, b); +} +inline bool TableEntryIsList(void* const* table, size_t b) { + return !TableEntryIsTree(table, b); +} + +// This captures all numeric types. +inline size_t MapValueSpaceUsedExcludingSelfLong(bool) { return 0; } +inline size_t MapValueSpaceUsedExcludingSelfLong(const std::string& str) { + return StringSpaceUsedExcludingSelfLong(str); +} +template <typename T, + typename = decltype(std::declval<const T&>().SpaceUsedLong())> +size_t MapValueSpaceUsedExcludingSelfLong(const T& message) { + return message.SpaceUsedLong() - sizeof(T); +} + +constexpr size_t kGlobalEmptyTableSize = 1; +PROTOBUF_EXPORT extern void* const kGlobalEmptyTable[kGlobalEmptyTableSize]; + +// Space used for the table, trees, and nodes. +// Does not include the indirect space used. Eg the data of a std::string. +template <typename Key> +PROTOBUF_NOINLINE size_t SpaceUsedInTable(void** table, size_t num_buckets, + size_t num_elements, + size_t sizeof_node) { + size_t size = 0; + // The size of the table. + size += sizeof(void*) * num_buckets; + // All the nodes. + size += sizeof_node * num_elements; + // For each tree, count the overhead of the those nodes. + // Two buckets at a time because we only care about trees. + for (size_t b = 0; b < num_buckets; b += 2) { + if (internal::TableEntryIsTree(table, b)) { + using Tree = TreeForMap<Key>; + Tree* tree = static_cast<Tree*>(table[b]); + // Estimated cost of the red-black tree nodes, 3 pointers plus a + // bool (plus alignment, so 4 pointers). + size += tree->size() * + (sizeof(typename Tree::value_type) + sizeof(void*) * 4); + } + } + return size; +} + +template <typename Map, + typename = typename std::enable_if< + !std::is_scalar<typename Map::key_type>::value || + !std::is_scalar<typename Map::mapped_type>::value>::type> +size_t SpaceUsedInValues(const Map* map) { + size_t size = 0; + for (const auto& v : *map) { + size += internal::MapValueSpaceUsedExcludingSelfLong(v.first) + + internal::MapValueSpaceUsedExcludingSelfLong(v.second); + } + return size; +} + +inline size_t SpaceUsedInValues(const void*) { return 0; } + +} // namespace internal + +// This is the class for Map's internal value_type. Instead of using +// std::pair as value_type, we use this class which provides us more control of +// its process of construction and destruction. +template <typename Key, typename T> +struct PROTOBUF_ATTRIBUTE_STANDALONE_DEBUG MapPair { + using first_type = const Key; + using second_type = T; + + MapPair(const Key& other_first, const T& other_second) + : first(other_first), second(other_second) {} + explicit MapPair(const Key& other_first) : first(other_first), second() {} + explicit MapPair(Key&& other_first) + : first(std::move(other_first)), second() {} + MapPair(const MapPair& other) : first(other.first), second(other.second) {} + + ~MapPair() {} + + // Implicitly convertible to std::pair of compatible types. + template <typename T1, typename T2> + operator std::pair<T1, T2>() const { // NOLINT(runtime/explicit) + return std::pair<T1, T2>(first, second); + } + + const Key first; + T second; + + private: + friend class Arena; + friend class Map<Key, T>; +}; + +// Map is an associative container type used to store protobuf map +// fields. Each Map instance may or may not use a different hash function, a +// different iteration order, and so on. E.g., please don't examine +// implementation details to decide if the following would work: +// Map<int, int> m0, m1; +// m0[0] = m1[0] = m0[1] = m1[1] = 0; +// assert(m0.begin()->first == m1.begin()->first); // Bug! +// +// Map's interface is similar to std::unordered_map, except that Map is not +// designed to play well with exceptions. +template <typename Key, typename T> +class Map { + public: + using key_type = Key; + using mapped_type = T; + using value_type = MapPair<Key, T>; + + using pointer = value_type*; + using const_pointer = const value_type*; + using reference = value_type&; + using const_reference = const value_type&; + + using size_type = size_t; + using hasher = typename internal::TransparentSupport<Key>::hash; + + constexpr Map() : elements_(nullptr) {} + explicit Map(Arena* arena) : elements_(arena) {} + + Map(const Map& other) : Map() { insert(other.begin(), other.end()); } + + Map(Map&& other) noexcept : Map() { + if (other.arena() != nullptr) { + *this = other; + } else { + swap(other); + } + } + + Map& operator=(Map&& other) noexcept { + if (this != &other) { + if (arena() != other.arena()) { + *this = other; + } else { + swap(other); + } + } + return *this; + } + + template <class InputIt> + Map(const InputIt& first, const InputIt& last) : Map() { + insert(first, last); + } + + ~Map() {} + + private: + using Allocator = internal::MapAllocator<void*>; + + // InnerMap is a generic hash-based map. It doesn't contain any + // protocol-buffer-specific logic. It is a chaining hash map with the + // additional feature that some buckets can be converted to use an ordered + // container. This ensures O(lg n) bounds on find, insert, and erase, while + // avoiding the overheads of ordered containers most of the time. + // + // The implementation doesn't need the full generality of unordered_map, + // and it doesn't have it. More bells and whistles can be added as needed. + // Some implementation details: + // 1. The hash function has type hasher and the equality function + // equal_to<Key>. We inherit from hasher to save space + // (empty-base-class optimization). + // 2. The number of buckets is a power of two. + // 3. Buckets are converted to trees in pairs: if we convert bucket b then + // buckets b and b^1 will share a tree. Invariant: buckets b and b^1 have + // the same non-null value iff they are sharing a tree. (An alternative + // implementation strategy would be to have a tag bit per bucket.) + // 4. As is typical for hash_map and such, the Keys and Values are always + // stored in linked list nodes. Pointers to elements are never invalidated + // until the element is deleted. + // 5. The trees' payload type is pointer to linked-list node. Tree-converting + // a bucket doesn't copy Key-Value pairs. + // 6. Once we've tree-converted a bucket, it is never converted back. However, + // the items a tree contains may wind up assigned to trees or lists upon a + // rehash. + // 7. The code requires no C++ features from C++14 or later. + // 8. Mutations to a map do not invalidate the map's iterators, pointers to + // elements, or references to elements. + // 9. Except for erase(iterator), any non-const method can reorder iterators. + // 10. InnerMap uses KeyForTree<Key> when using the Tree representation, which + // is either `Key`, if Key is a scalar, or `reference_wrapper<const Key>` + // otherwise. This avoids unnecessary copies of string keys, for example. + class InnerMap : private hasher { + public: + explicit constexpr InnerMap(Arena* arena) + : hasher(), + num_elements_(0), + num_buckets_(internal::kGlobalEmptyTableSize), + seed_(0), + index_of_first_non_null_(internal::kGlobalEmptyTableSize), + table_(const_cast<void**>(internal::kGlobalEmptyTable)), + alloc_(arena) {} + + ~InnerMap() { + if (alloc_.arena() == nullptr && + num_buckets_ != internal::kGlobalEmptyTableSize) { + clear(); + Dealloc<void*>(table_, num_buckets_); + } + } + + private: + enum { kMinTableSize = 8 }; + + // Linked-list nodes, as one would expect for a chaining hash table. + struct Node { + value_type kv; + Node* next; + }; + + // Trees. The payload type is a copy of Key, so that we can query the tree + // with Keys that are not in any particular data structure. + // The value is a void* pointing to Node. We use void* instead of Node* to + // avoid code bloat. That way there is only one instantiation of the tree + // class per key type. + using Tree = internal::TreeForMap<Key>; + using TreeIterator = typename Tree::iterator; + + static Node* NodeFromTreeIterator(TreeIterator it) { + return static_cast<Node*>(it->second); + } + + // iterator and const_iterator are instantiations of iterator_base. + template <typename KeyValueType> + class iterator_base { + public: + using reference = KeyValueType&; + using pointer = KeyValueType*; + + // Invariants: + // node_ is always correct. This is handy because the most common + // operations are operator* and operator-> and they only use node_. + // When node_ is set to a non-null value, all the other non-const fields + // are updated to be correct also, but those fields can become stale + // if the underlying map is modified. When those fields are needed they + // are rechecked, and updated if necessary. + iterator_base() : node_(nullptr), m_(nullptr), bucket_index_(0) {} + + explicit iterator_base(const InnerMap* m) : m_(m) { + SearchFrom(m->index_of_first_non_null_); + } + + // Any iterator_base can convert to any other. This is overkill, and we + // rely on the enclosing class to use it wisely. The standard "iterator + // can convert to const_iterator" is OK but the reverse direction is not. + template <typename U> + explicit iterator_base(const iterator_base<U>& it) + : node_(it.node_), m_(it.m_), bucket_index_(it.bucket_index_) {} + + iterator_base(Node* n, const InnerMap* m, size_type index) + : node_(n), m_(m), bucket_index_(index) {} + + iterator_base(TreeIterator tree_it, const InnerMap* m, size_type index) + : node_(NodeFromTreeIterator(tree_it)), m_(m), bucket_index_(index) { + // Invariant: iterators that use buckets with trees have an even + // bucket_index_. + GOOGLE_DCHECK_EQ(bucket_index_ % 2, 0u); + } + + // Advance through buckets, looking for the first that isn't empty. + // If nothing non-empty is found then leave node_ == nullptr. + void SearchFrom(size_type start_bucket) { + GOOGLE_DCHECK(m_->index_of_first_non_null_ == m_->num_buckets_ || + m_->table_[m_->index_of_first_non_null_] != nullptr); + node_ = nullptr; + for (bucket_index_ = start_bucket; bucket_index_ < m_->num_buckets_; + bucket_index_++) { + if (m_->TableEntryIsNonEmptyList(bucket_index_)) { + node_ = static_cast<Node*>(m_->table_[bucket_index_]); + break; + } else if (m_->TableEntryIsTree(bucket_index_)) { + Tree* tree = static_cast<Tree*>(m_->table_[bucket_index_]); + GOOGLE_DCHECK(!tree->empty()); + node_ = NodeFromTreeIterator(tree->begin()); + break; + } + } + } + + reference operator*() const { return node_->kv; } + pointer operator->() const { return &(operator*()); } + + friend bool operator==(const iterator_base& a, const iterator_base& b) { + return a.node_ == b.node_; + } + friend bool operator!=(const iterator_base& a, const iterator_base& b) { + return a.node_ != b.node_; + } + + iterator_base& operator++() { + if (node_->next == nullptr) { + TreeIterator tree_it; + const bool is_list = revalidate_if_necessary(&tree_it); + if (is_list) { + SearchFrom(bucket_index_ + 1); + } else { + GOOGLE_DCHECK_EQ(bucket_index_ & 1, 0u); + Tree* tree = static_cast<Tree*>(m_->table_[bucket_index_]); + if (++tree_it == tree->end()) { + SearchFrom(bucket_index_ + 2); + } else { + node_ = NodeFromTreeIterator(tree_it); + } + } + } else { + node_ = node_->next; + } + return *this; + } + + iterator_base operator++(int /* unused */) { + iterator_base tmp = *this; + ++*this; + return tmp; + } + + // Assumes node_ and m_ are correct and non-null, but other fields may be + // stale. Fix them as needed. Then return true iff node_ points to a + // Node in a list. If false is returned then *it is modified to be + // a valid iterator for node_. + bool revalidate_if_necessary(TreeIterator* it) { + GOOGLE_DCHECK(node_ != nullptr && m_ != nullptr); + // Force bucket_index_ to be in range. + bucket_index_ &= (m_->num_buckets_ - 1); + // Common case: the bucket we think is relevant points to node_. + if (m_->table_[bucket_index_] == static_cast<void*>(node_)) return true; + // Less common: the bucket is a linked list with node_ somewhere in it, + // but not at the head. + if (m_->TableEntryIsNonEmptyList(bucket_index_)) { + Node* l = static_cast<Node*>(m_->table_[bucket_index_]); + while ((l = l->next) != nullptr) { + if (l == node_) { + return true; + } + } + } + // Well, bucket_index_ still might be correct, but probably + // not. Revalidate just to be sure. This case is rare enough that we + // don't worry about potential optimizations, such as having a custom + // find-like method that compares Node* instead of the key. + iterator_base i(m_->find(node_->kv.first, it)); + bucket_index_ = i.bucket_index_; + return m_->TableEntryIsList(bucket_index_); + } + + Node* node_; + const InnerMap* m_; + size_type bucket_index_; + }; + + public: + using iterator = iterator_base<value_type>; + using const_iterator = iterator_base<const value_type>; + + Arena* arena() const { return alloc_.arena(); } + + void Swap(InnerMap* other) { + std::swap(num_elements_, other->num_elements_); + std::swap(num_buckets_, other->num_buckets_); + std::swap(seed_, other->seed_); + std::swap(index_of_first_non_null_, other->index_of_first_non_null_); + std::swap(table_, other->table_); + std::swap(alloc_, other->alloc_); + } + + iterator begin() { return iterator(this); } + iterator end() { return iterator(); } + const_iterator begin() const { return const_iterator(this); } + const_iterator end() const { return const_iterator(); } + + void clear() { + for (size_type b = 0; b < num_buckets_; b++) { + if (TableEntryIsNonEmptyList(b)) { + Node* node = static_cast<Node*>(table_[b]); + table_[b] = nullptr; + do { + Node* next = node->next; + DestroyNode(node); + node = next; + } while (node != nullptr); + } else if (TableEntryIsTree(b)) { + Tree* tree = static_cast<Tree*>(table_[b]); + GOOGLE_DCHECK(table_[b] == table_[b + 1] && (b & 1) == 0); + table_[b] = table_[b + 1] = nullptr; + typename Tree::iterator tree_it = tree->begin(); + do { + Node* node = NodeFromTreeIterator(tree_it); + typename Tree::iterator next = tree_it; + ++next; + tree->erase(tree_it); + DestroyNode(node); + tree_it = next; + } while (tree_it != tree->end()); + DestroyTree(tree); + b++; + } + } + num_elements_ = 0; + index_of_first_non_null_ = num_buckets_; + } + + const hasher& hash_function() const { return *this; } + + static size_type max_size() { + return static_cast<size_type>(1) << (sizeof(void**) >= 8 ? 60 : 28); + } + size_type size() const { return num_elements_; } + bool empty() const { return size() == 0; } + + template <typename K> + iterator find(const K& k) { + return iterator(FindHelper(k).first); + } + + template <typename K> + const_iterator find(const K& k) const { + return FindHelper(k).first; + } + + // Inserts a new element into the container if there is no element with the + // key in the container. + // The new element is: + // (1) Constructed in-place with the given args, if mapped_type is not + // arena constructible. + // (2) Constructed in-place with the arena and then assigned with a + // mapped_type temporary constructed with the given args, otherwise. + template <typename K, typename... Args> + std::pair<iterator, bool> try_emplace(K&& k, Args&&... args) { + return ArenaAwareTryEmplace(Arena::is_arena_constructable<mapped_type>(), + std::forward<K>(k), + std::forward<Args>(args)...); + } + + // Inserts the key into the map, if not present. In that case, the value + // will be value initialized. + template <typename K> + std::pair<iterator, bool> insert(K&& k) { + return try_emplace(std::forward<K>(k)); + } + + template <typename K> + value_type& operator[](K&& k) { + return *try_emplace(std::forward<K>(k)).first; + } + + void erase(iterator it) { + GOOGLE_DCHECK_EQ(it.m_, this); + typename Tree::iterator tree_it; + const bool is_list = it.revalidate_if_necessary(&tree_it); + size_type b = it.bucket_index_; + Node* const item = it.node_; + if (is_list) { + GOOGLE_DCHECK(TableEntryIsNonEmptyList(b)); + Node* head = static_cast<Node*>(table_[b]); + head = EraseFromLinkedList(item, head); + table_[b] = static_cast<void*>(head); + } else { + GOOGLE_DCHECK(TableEntryIsTree(b)); + Tree* tree = static_cast<Tree*>(table_[b]); + tree->erase(tree_it); + if (tree->empty()) { + // Force b to be the minimum of b and b ^ 1. This is important + // only because we want index_of_first_non_null_ to be correct. + b &= ~static_cast<size_type>(1); + DestroyTree(tree); + table_[b] = table_[b + 1] = nullptr; + } + } + DestroyNode(item); + --num_elements_; + if (PROTOBUF_PREDICT_FALSE(b == index_of_first_non_null_)) { + while (index_of_first_non_null_ < num_buckets_ && + table_[index_of_first_non_null_] == nullptr) { + ++index_of_first_non_null_; + } + } + } + + size_t SpaceUsedInternal() const { + return internal::SpaceUsedInTable<Key>(table_, num_buckets_, + num_elements_, sizeof(Node)); + } + + private: + template <typename K, typename... Args> + std::pair<iterator, bool> TryEmplaceInternal(K&& k, Args&&... args) { + std::pair<const_iterator, size_type> p = FindHelper(k); + // Case 1: key was already present. + if (p.first.node_ != nullptr) + return std::make_pair(iterator(p.first), false); + // Case 2: insert. + if (ResizeIfLoadIsOutOfRange(num_elements_ + 1)) { + p = FindHelper(k); + } + const size_type b = p.second; // bucket number + // If K is not key_type, make the conversion to key_type explicit. + using TypeToInit = typename std::conditional< + std::is_same<typename std::decay<K>::type, key_type>::value, K&&, + key_type>::type; + Node* node = Alloc<Node>(1); + // Even when arena is nullptr, CreateInArenaStorage is still used to + // ensure the arena of submessage will be consistent. Otherwise, + // submessage may have its own arena when message-owned arena is enabled. + // Note: This only works if `Key` is not arena constructible. + Arena::CreateInArenaStorage(const_cast<Key*>(&node->kv.first), + alloc_.arena(), + static_cast<TypeToInit>(std::forward<K>(k))); + // Note: if `T` is arena constructible, `Args` needs to be empty. + Arena::CreateInArenaStorage(&node->kv.second, alloc_.arena(), + std::forward<Args>(args)...); + + iterator result = InsertUnique(b, node); + ++num_elements_; + return std::make_pair(result, true); + } + + // A helper function to perform an assignment of `mapped_type`. + // If the first argument is true, then it is a regular assignment. + // Otherwise, we first create a temporary and then perform an assignment. + template <typename V> + static void AssignMapped(std::true_type, mapped_type& mapped, V&& v) { + mapped = std::forward<V>(v); + } + template <typename... Args> + static void AssignMapped(std::false_type, mapped_type& mapped, + Args&&... args) { + mapped = mapped_type(std::forward<Args>(args)...); + } + + // Case 1: `mapped_type` is arena constructible. A temporary object is + // created and then (if `Args` are not empty) assigned to a mapped value + // that was created with the arena. + template <typename K> + std::pair<iterator, bool> ArenaAwareTryEmplace(std::true_type, K&& k) { + // case 1.1: "default" constructed (e.g. from arena only). + return TryEmplaceInternal(std::forward<K>(k)); + } + template <typename K, typename... Args> + std::pair<iterator, bool> ArenaAwareTryEmplace(std::true_type, K&& k, + Args&&... args) { + // case 1.2: "default" constructed + copy/move assignment + auto p = TryEmplaceInternal(std::forward<K>(k)); + if (p.second) { + AssignMapped(std::is_same<void(typename std::decay<Args>::type...), + void(mapped_type)>(), + p.first->second, std::forward<Args>(args)...); + } + return p; + } + // Case 2: `mapped_type` is not arena constructible. Using in-place + // construction. + template <typename... Args> + std::pair<iterator, bool> ArenaAwareTryEmplace(std::false_type, + Args&&... args) { + return TryEmplaceInternal(std::forward<Args>(args)...); + } + + const_iterator find(const Key& k, TreeIterator* it) const { + return FindHelper(k, it).first; + } + template <typename K> + std::pair<const_iterator, size_type> FindHelper(const K& k) const { + return FindHelper(k, nullptr); + } + template <typename K> + std::pair<const_iterator, size_type> FindHelper(const K& k, + TreeIterator* it) const { + size_type b = BucketNumber(k); + if (TableEntryIsNonEmptyList(b)) { + Node* node = static_cast<Node*>(table_[b]); + do { + if (internal::TransparentSupport<Key>::Equals(node->kv.first, k)) { + return std::make_pair(const_iterator(node, this, b), b); + } else { + node = node->next; + } + } while (node != nullptr); + } else if (TableEntryIsTree(b)) { + GOOGLE_DCHECK_EQ(table_[b], table_[b ^ 1]); + b &= ~static_cast<size_t>(1); + Tree* tree = static_cast<Tree*>(table_[b]); + auto tree_it = tree->find(k); + if (tree_it != tree->end()) { + if (it != nullptr) *it = tree_it; + return std::make_pair(const_iterator(tree_it, this, b), b); + } + } + return std::make_pair(end(), b); + } + + // Insert the given Node in bucket b. If that would make bucket b too big, + // and bucket b is not a tree, create a tree for buckets b and b^1 to share. + // Requires count(*KeyPtrFromNodePtr(node)) == 0 and that b is the correct + // bucket. num_elements_ is not modified. + iterator InsertUnique(size_type b, Node* node) { + GOOGLE_DCHECK(index_of_first_non_null_ == num_buckets_ || + table_[index_of_first_non_null_] != nullptr); + // In practice, the code that led to this point may have already + // determined whether we are inserting into an empty list, a short list, + // or whatever. But it's probably cheap enough to recompute that here; + // it's likely that we're inserting into an empty or short list. + iterator result; + GOOGLE_DCHECK(find(node->kv.first) == end()); + if (TableEntryIsEmpty(b)) { + result = InsertUniqueInList(b, node); + } else if (TableEntryIsNonEmptyList(b)) { + if (PROTOBUF_PREDICT_FALSE(TableEntryIsTooLong(b))) { + TreeConvert(b); + result = InsertUniqueInTree(b, node); + GOOGLE_DCHECK_EQ(result.bucket_index_, b & ~static_cast<size_type>(1)); + } else { + // Insert into a pre-existing list. This case cannot modify + // index_of_first_non_null_, so we skip the code to update it. + return InsertUniqueInList(b, node); + } + } else { + // Insert into a pre-existing tree. This case cannot modify + // index_of_first_non_null_, so we skip the code to update it. + return InsertUniqueInTree(b, node); + } + // parentheses around (std::min) prevents macro expansion of min(...) + index_of_first_non_null_ = + (std::min)(index_of_first_non_null_, result.bucket_index_); + return result; + } + + // Returns whether we should insert after the head of the list. For + // non-optimized builds, we randomly decide whether to insert right at the + // head of the list or just after the head. This helps add a little bit of + // non-determinism to the map ordering. + bool ShouldInsertAfterHead(void* node) { +#ifdef NDEBUG + (void)node; + return false; +#else + // Doing modulo with a prime mixes the bits more. + return (reinterpret_cast<uintptr_t>(node) ^ seed_) % 13 > 6; +#endif + } + + // Helper for InsertUnique. Handles the case where bucket b is a + // not-too-long linked list. + iterator InsertUniqueInList(size_type b, Node* node) { + if (table_[b] != nullptr && ShouldInsertAfterHead(node)) { + Node* first = static_cast<Node*>(table_[b]); + node->next = first->next; + first->next = node; + return iterator(node, this, b); + } + + node->next = static_cast<Node*>(table_[b]); + table_[b] = static_cast<void*>(node); + return iterator(node, this, b); + } + + // Helper for InsertUnique. Handles the case where bucket b points to a + // Tree. + iterator InsertUniqueInTree(size_type b, Node* node) { + GOOGLE_DCHECK_EQ(table_[b], table_[b ^ 1]); + // Maintain the invariant that node->next is null for all Nodes in Trees. + node->next = nullptr; + return iterator( + static_cast<Tree*>(table_[b])->insert({node->kv.first, node}).first, + this, b & ~static_cast<size_t>(1)); + } + + // Returns whether it did resize. Currently this is only used when + // num_elements_ increases, though it could be used in other situations. + // It checks for load too low as well as load too high: because any number + // of erases can occur between inserts, the load could be as low as 0 here. + // Resizing to a lower size is not always helpful, but failing to do so can + // destroy the expected big-O bounds for some operations. By having the + // policy that sometimes we resize down as well as up, clients can easily + // keep O(size()) = O(number of buckets) if they want that. + bool ResizeIfLoadIsOutOfRange(size_type new_size) { + const size_type kMaxMapLoadTimes16 = 12; // controls RAM vs CPU tradeoff + const size_type hi_cutoff = num_buckets_ * kMaxMapLoadTimes16 / 16; + const size_type lo_cutoff = hi_cutoff / 4; + // We don't care how many elements are in trees. If a lot are, + // we may resize even though there are many empty buckets. In + // practice, this seems fine. + if (PROTOBUF_PREDICT_FALSE(new_size >= hi_cutoff)) { + if (num_buckets_ <= max_size() / 2) { + Resize(num_buckets_ * 2); + return true; + } + } else if (PROTOBUF_PREDICT_FALSE(new_size <= lo_cutoff && + num_buckets_ > kMinTableSize)) { + size_type lg2_of_size_reduction_factor = 1; + // It's possible we want to shrink a lot here... size() could even be 0. + // So, estimate how much to shrink by making sure we don't shrink so + // much that we would need to grow the table after a few inserts. + const size_type hypothetical_size = new_size * 5 / 4 + 1; + while ((hypothetical_size << lg2_of_size_reduction_factor) < + hi_cutoff) { + ++lg2_of_size_reduction_factor; + } + size_type new_num_buckets = std::max<size_type>( + kMinTableSize, num_buckets_ >> lg2_of_size_reduction_factor); + if (new_num_buckets != num_buckets_) { + Resize(new_num_buckets); + return true; + } + } + return false; + } + + // Resize to the given number of buckets. + void Resize(size_t new_num_buckets) { + if (num_buckets_ == internal::kGlobalEmptyTableSize) { + // This is the global empty array. + // Just overwrite with a new one. No need to transfer or free anything. + num_buckets_ = index_of_first_non_null_ = kMinTableSize; + table_ = CreateEmptyTable(num_buckets_); + seed_ = Seed(); + return; + } + + GOOGLE_DCHECK_GE(new_num_buckets, kMinTableSize); + void** const old_table = table_; + const size_type old_table_size = num_buckets_; + num_buckets_ = new_num_buckets; + table_ = CreateEmptyTable(num_buckets_); + const size_type start = index_of_first_non_null_; + index_of_first_non_null_ = num_buckets_; + for (size_type i = start; i < old_table_size; i++) { + if (internal::TableEntryIsNonEmptyList(old_table, i)) { + TransferList(old_table, i); + } else if (internal::TableEntryIsTree(old_table, i)) { + TransferTree(old_table, i++); + } + } + Dealloc<void*>(old_table, old_table_size); + } + + void TransferList(void* const* table, size_type index) { + Node* node = static_cast<Node*>(table[index]); + do { + Node* next = node->next; + InsertUnique(BucketNumber(node->kv.first), node); + node = next; + } while (node != nullptr); + } + + void TransferTree(void* const* table, size_type index) { + Tree* tree = static_cast<Tree*>(table[index]); + typename Tree::iterator tree_it = tree->begin(); + do { + InsertUnique(BucketNumber(std::cref(tree_it->first).get()), + NodeFromTreeIterator(tree_it)); + } while (++tree_it != tree->end()); + DestroyTree(tree); + } + + Node* EraseFromLinkedList(Node* item, Node* head) { + if (head == item) { + return head->next; + } else { + head->next = EraseFromLinkedList(item, head->next); + return head; + } + } + + bool TableEntryIsEmpty(size_type b) const { + return internal::TableEntryIsEmpty(table_, b); + } + bool TableEntryIsNonEmptyList(size_type b) const { + return internal::TableEntryIsNonEmptyList(table_, b); + } + bool TableEntryIsTree(size_type b) const { + return internal::TableEntryIsTree(table_, b); + } + bool TableEntryIsList(size_type b) const { + return internal::TableEntryIsList(table_, b); + } + + void TreeConvert(size_type b) { + GOOGLE_DCHECK(!TableEntryIsTree(b) && !TableEntryIsTree(b ^ 1)); + Tree* tree = + Arena::Create<Tree>(alloc_.arena(), typename Tree::key_compare(), + typename Tree::allocator_type(alloc_)); + size_type count = CopyListToTree(b, tree) + CopyListToTree(b ^ 1, tree); + GOOGLE_DCHECK_EQ(count, tree->size()); + table_[b] = table_[b ^ 1] = static_cast<void*>(tree); + } + + // Copy a linked list in the given bucket to a tree. + // Returns the number of things it copied. + size_type CopyListToTree(size_type b, Tree* tree) { + size_type count = 0; + Node* node = static_cast<Node*>(table_[b]); + while (node != nullptr) { + tree->insert({node->kv.first, node}); + ++count; + Node* next = node->next; + node->next = nullptr; + node = next; + } + return count; + } + + // Return whether table_[b] is a linked list that seems awfully long. + // Requires table_[b] to point to a non-empty linked list. + bool TableEntryIsTooLong(size_type b) { + const size_type kMaxLength = 8; + size_type count = 0; + Node* node = static_cast<Node*>(table_[b]); + do { + ++count; + node = node->next; + } while (node != nullptr); + // Invariant: no linked list ever is more than kMaxLength in length. + GOOGLE_DCHECK_LE(count, kMaxLength); + return count >= kMaxLength; + } + + template <typename K> + size_type BucketNumber(const K& k) const { + // We xor the hash value against the random seed so that we effectively + // have a random hash function. + uint64_t h = hash_function()(k) ^ seed_; + + // We use the multiplication method to determine the bucket number from + // the hash value. The constant kPhi (suggested by Knuth) is roughly + // (sqrt(5) - 1) / 2 * 2^64. + constexpr uint64_t kPhi = uint64_t{0x9e3779b97f4a7c15}; + return ((kPhi * h) >> 32) & (num_buckets_ - 1); + } + + // Return a power of two no less than max(kMinTableSize, n). + // Assumes either n < kMinTableSize or n is a power of two. + size_type TableSize(size_type n) { + return n < static_cast<size_type>(kMinTableSize) + ? static_cast<size_type>(kMinTableSize) + : n; + } + + // Use alloc_ to allocate an array of n objects of type U. + template <typename U> + U* Alloc(size_type n) { + using alloc_type = typename Allocator::template rebind<U>::other; + return alloc_type(alloc_).allocate(n); + } + + // Use alloc_ to deallocate an array of n objects of type U. + template <typename U> + void Dealloc(U* t, size_type n) { + using alloc_type = typename Allocator::template rebind<U>::other; + alloc_type(alloc_).deallocate(t, n); + } + + void DestroyNode(Node* node) { + if (alloc_.arena() == nullptr) { + delete node; + } + } + + void DestroyTree(Tree* tree) { + if (alloc_.arena() == nullptr) { + delete tree; + } + } + + void** CreateEmptyTable(size_type n) { + GOOGLE_DCHECK(n >= kMinTableSize); + GOOGLE_DCHECK_EQ(n & (n - 1), 0u); + void** result = Alloc<void*>(n); + memset(result, 0, n * sizeof(result[0])); + return result; + } + + // Return a randomish value. + size_type Seed() const { + // We get a little bit of randomness from the address of the map. The + // lower bits are not very random, due to alignment, so we discard them + // and shift the higher bits into their place. + size_type s = reinterpret_cast<uintptr_t>(this) >> 4; +#if !defined(GOOGLE_PROTOBUF_NO_RDTSC) +#if defined(__APPLE__) + // Use a commpage-based fast time function on Apple environments (MacOS, + // iOS, tvOS, watchOS, etc). + s += mach_absolute_time(); +#elif defined(__x86_64__) && defined(__GNUC__) + uint32_t hi, lo; + asm volatile("rdtsc" : "=a"(lo), "=d"(hi)); + s += ((static_cast<uint64_t>(hi) << 32) | lo); +#elif defined(__aarch64__) && defined(__GNUC__) + // There is no rdtsc on ARMv8. CNTVCT_EL0 is the virtual counter of the + // system timer. It runs at a different frequency than the CPU's, but is + // the best source of time-based entropy we get. + uint64_t virtual_timer_value; + asm volatile("mrs %0, cntvct_el0" : "=r"(virtual_timer_value)); + s += virtual_timer_value; +#endif +#endif // !defined(GOOGLE_PROTOBUF_NO_RDTSC) + return s; + } + + friend class Arena; + using InternalArenaConstructable_ = void; + using DestructorSkippable_ = void; + + size_type num_elements_; + size_type num_buckets_; + size_type seed_; + size_type index_of_first_non_null_; + void** table_; // an array with num_buckets_ entries + Allocator alloc_; + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(InnerMap); + }; // end of class InnerMap + + template <typename LookupKey> + using key_arg = typename internal::TransparentSupport< + key_type>::template key_arg<LookupKey>; + + public: + // Iterators + class const_iterator { + using InnerIt = typename InnerMap::const_iterator; + + public: + using iterator_category = std::forward_iterator_tag; + using value_type = typename Map::value_type; + using difference_type = ptrdiff_t; + using pointer = const value_type*; + using reference = const value_type&; + + const_iterator() {} + explicit const_iterator(const InnerIt& it) : it_(it) {} + + const_reference operator*() const { return *it_; } + const_pointer operator->() const { return &(operator*()); } + + const_iterator& operator++() { + ++it_; + return *this; + } + const_iterator operator++(int) { return const_iterator(it_++); } + + friend bool operator==(const const_iterator& a, const const_iterator& b) { + return a.it_ == b.it_; + } + friend bool operator!=(const const_iterator& a, const const_iterator& b) { + return !(a == b); + } + + private: + InnerIt it_; + }; + + class iterator { + using InnerIt = typename InnerMap::iterator; + + public: + using iterator_category = std::forward_iterator_tag; + using value_type = typename Map::value_type; + using difference_type = ptrdiff_t; + using pointer = value_type*; + using reference = value_type&; + + iterator() {} + explicit iterator(const InnerIt& it) : it_(it) {} + + reference operator*() const { return *it_; } + pointer operator->() const { return &(operator*()); } + + iterator& operator++() { + ++it_; + return *this; + } + iterator operator++(int) { return iterator(it_++); } + + // Allow implicit conversion to const_iterator. + operator const_iterator() const { // NOLINT(runtime/explicit) + return const_iterator(typename InnerMap::const_iterator(it_)); + } + + friend bool operator==(const iterator& a, const iterator& b) { + return a.it_ == b.it_; + } + friend bool operator!=(const iterator& a, const iterator& b) { + return !(a == b); + } + + private: + friend class Map; + + InnerIt it_; + }; + + iterator begin() { return iterator(elements_.begin()); } + iterator end() { return iterator(elements_.end()); } + const_iterator begin() const { return const_iterator(elements_.begin()); } + const_iterator end() const { return const_iterator(elements_.end()); } + const_iterator cbegin() const { return begin(); } + const_iterator cend() const { return end(); } + + // Capacity + size_type size() const { return elements_.size(); } + bool empty() const { return size() == 0; } + + // Element access + template <typename K = key_type> + T& operator[](const key_arg<K>& key) { + return elements_[key].second; + } + template < + typename K = key_type, + // Disable for integral types to reduce code bloat. + typename = typename std::enable_if<!std::is_integral<K>::value>::type> + T& operator[](key_arg<K>&& key) { + return elements_[std::forward<K>(key)].second; + } + + template <typename K = key_type> + const T& at(const key_arg<K>& key) const { + const_iterator it = find(key); + GOOGLE_CHECK(it != end()) << "key not found: " << static_cast<Key>(key); + return it->second; + } + + template <typename K = key_type> + T& at(const key_arg<K>& key) { + iterator it = find(key); + GOOGLE_CHECK(it != end()) << "key not found: " << static_cast<Key>(key); + return it->second; + } + + // Lookup + template <typename K = key_type> + size_type count(const key_arg<K>& key) const { + return find(key) == end() ? 0 : 1; + } + + template <typename K = key_type> + const_iterator find(const key_arg<K>& key) const { + return const_iterator(elements_.find(key)); + } + template <typename K = key_type> + iterator find(const key_arg<K>& key) { + return iterator(elements_.find(key)); + } + + template <typename K = key_type> + bool contains(const key_arg<K>& key) const { + return find(key) != end(); + } + + template <typename K = key_type> + std::pair<const_iterator, const_iterator> equal_range( + const key_arg<K>& key) const { + const_iterator it = find(key); + if (it == end()) { + return std::pair<const_iterator, const_iterator>(it, it); + } else { + const_iterator begin = it++; + return std::pair<const_iterator, const_iterator>(begin, it); + } + } + + template <typename K = key_type> + std::pair<iterator, iterator> equal_range(const key_arg<K>& key) { + iterator it = find(key); + if (it == end()) { + return std::pair<iterator, iterator>(it, it); + } else { + iterator begin = it++; + return std::pair<iterator, iterator>(begin, it); + } + } + + // insert + template <typename K, typename... Args> + std::pair<iterator, bool> try_emplace(K&& k, Args&&... args) { + auto p = + elements_.try_emplace(std::forward<K>(k), std::forward<Args>(args)...); + return std::pair<iterator, bool>(iterator(p.first), p.second); + } + std::pair<iterator, bool> insert(const value_type& value) { + return try_emplace(value.first, value.second); + } + std::pair<iterator, bool> insert(value_type&& value) { + return try_emplace(value.first, std::move(value.second)); + } + template <typename... Args> + std::pair<iterator, bool> emplace(Args&&... args) { + return insert(value_type(std::forward<Args>(args)...)); + } + template <class InputIt> + void insert(InputIt first, InputIt last) { + for (; first != last; ++first) { + try_emplace(first->first, first->second); + } + } + void insert(std::initializer_list<value_type> values) { + insert(values.begin(), values.end()); + } + + // Erase and clear + template <typename K = key_type> + size_type erase(const key_arg<K>& key) { + iterator it = find(key); + if (it == end()) { + return 0; + } else { + erase(it); + return 1; + } + } + iterator erase(iterator pos) { + iterator i = pos++; + elements_.erase(i.it_); + return pos; + } + void erase(iterator first, iterator last) { + while (first != last) { + first = erase(first); + } + } + void clear() { elements_.clear(); } + + // Assign + Map& operator=(const Map& other) { + if (this != &other) { + clear(); + insert(other.begin(), other.end()); + } + return *this; + } + + void swap(Map& other) { + if (arena() == other.arena()) { + InternalSwap(other); + } else { + // TODO(zuguang): optimize this. The temporary copy can be allocated + // in the same arena as the other message, and the "other = copy" can + // be replaced with the fast-path swap above. + Map copy = *this; + *this = other; + other = copy; + } + } + + void InternalSwap(Map& other) { elements_.Swap(&other.elements_); } + + // Access to hasher. Currently this returns a copy, but it may + // be modified to return a const reference in the future. + hasher hash_function() const { return elements_.hash_function(); } + + size_t SpaceUsedExcludingSelfLong() const { + if (empty()) return 0; + return elements_.SpaceUsedInternal() + internal::SpaceUsedInValues(this); + } + + private: + Arena* arena() const { return elements_.arena(); } + InnerMap elements_; + + friend class Arena; + using InternalArenaConstructable_ = void; + using DestructorSkippable_ = void; + template <typename Derived, typename K, typename V, + internal::WireFormatLite::FieldType key_wire_type, + internal::WireFormatLite::FieldType value_wire_type> + friend class internal::MapFieldLite; +}; + +} // namespace protobuf +} // namespace google + +#include <google/protobuf/port_undef.inc> + +#endif // GOOGLE_PROTOBUF_MAP_H__ diff --git a/toolkit/components/protobuf/src/google/protobuf/map_entry.h b/toolkit/components/protobuf/src/google/protobuf/map_entry.h new file mode 100644 index 0000000000..536dec9d0d --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/map_entry.h @@ -0,0 +1,134 @@ +// 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. + +#ifndef GOOGLE_PROTOBUF_MAP_ENTRY_H__ +#define GOOGLE_PROTOBUF_MAP_ENTRY_H__ + +#include <google/protobuf/port.h> +#include <google/protobuf/generated_message_reflection.h> +#include <google/protobuf/map_entry_lite.h> +#include <google/protobuf/map_type_handler.h> +#include <google/protobuf/reflection_ops.h> +#include <google/protobuf/unknown_field_set.h> +#include <google/protobuf/wire_format_lite.h> + +// Must be included last. +#include <google/protobuf/port_def.inc> + +#ifdef SWIG +#error "You cannot SWIG proto headers" +#endif + +namespace google { +namespace protobuf { +class Arena; +namespace internal { +template <typename Derived, typename Key, typename Value, + WireFormatLite::FieldType kKeyFieldType, + WireFormatLite::FieldType kValueFieldType> +class MapField; +} +} // namespace protobuf +} // namespace google + +namespace google { +namespace protobuf { +namespace internal { + +// MapEntry is the returned google::protobuf::Message when calling AddMessage of +// google::protobuf::Reflection. In order to let it work with generated message +// reflection, its in-memory type is the same as generated message with the same +// fields. However, in order to decide the in-memory type of key/value, we need +// to know both their cpp type in generated api and proto type. In +// implementation, all in-memory types have related wire format functions to +// support except ArenaStringPtr. Therefore, we need to define another type with +// supporting wire format functions. Since this type is only used as return type +// of MapEntry accessors, it's named MapEntry accessor type. +// +// cpp type: the type visible to users in public API. +// proto type: WireFormatLite::FieldType of the field. +// in-memory type: type of the data member used to stored this field. +// MapEntry accessor type: type used in MapEntry getters/mutators to access the +// field. +// +// cpp type | proto type | in-memory type | MapEntry accessor type +// int32_t TYPE_INT32 int32_t int32_t +// int32_t TYPE_FIXED32 int32_t int32_t +// string TYPE_STRING ArenaStringPtr string +// FooEnum TYPE_ENUM int int +// FooMessage TYPE_MESSAGE FooMessage* FooMessage +// +// The in-memory types of primitive types can be inferred from its proto type, +// while we need to explicitly specify the cpp type if proto type is +// TYPE_MESSAGE to infer the in-memory type. +template <typename Derived, typename Key, typename Value, + WireFormatLite::FieldType kKeyFieldType, + WireFormatLite::FieldType kValueFieldType> +class MapEntry : public MapEntryImpl<Derived, Message, Key, Value, + kKeyFieldType, kValueFieldType> { + public: + constexpr MapEntry() {} + explicit MapEntry(Arena* arena) + : MapEntryImpl<Derived, Message, Key, Value, kKeyFieldType, + kValueFieldType>(arena) {} + ~MapEntry() override { + Message::_internal_metadata_.template Delete<UnknownFieldSet>(); + } + typedef void InternalArenaConstructable_; + typedef void DestructorSkippable_; + + typedef typename MapEntryImpl<Derived, Message, Key, Value, kKeyFieldType, + kValueFieldType>::KeyTypeHandler KeyTypeHandler; + typedef + typename MapEntryImpl<Derived, Message, Key, Value, kKeyFieldType, + kValueFieldType>::ValueTypeHandler ValueTypeHandler; + size_t SpaceUsedLong() const override { + size_t size = sizeof(Derived); + size += KeyTypeHandler::SpaceUsedInMapEntryLong(this->key_); + size += ValueTypeHandler::SpaceUsedInMapEntryLong(this->value_); + return size; + } + + private: + friend class ::PROTOBUF_NAMESPACE_ID::Arena; + template <typename C, typename K, typename V, + WireFormatLite::FieldType k_wire_type, WireFormatLite::FieldType> + friend class internal::MapField; + + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MapEntry); +}; + +} // namespace internal +} // namespace protobuf +} // namespace google + +#include <google/protobuf/port_undef.inc> + +#endif // GOOGLE_PROTOBUF_MAP_ENTRY_H__ diff --git a/toolkit/components/protobuf/src/google/protobuf/map_entry_lite.h b/toolkit/components/protobuf/src/google/protobuf/map_entry_lite.h new file mode 100644 index 0000000000..6b08cd92ba --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/map_entry_lite.h @@ -0,0 +1,563 @@ +// 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. + +#ifndef GOOGLE_PROTOBUF_MAP_ENTRY_LITE_H__ +#define GOOGLE_PROTOBUF_MAP_ENTRY_LITE_H__ + +#include <assert.h> + +#include <algorithm> +#include <string> +#include <utility> + +#include <google/protobuf/stubs/casts.h> +#include <google/protobuf/io/coded_stream.h> +#include <google/protobuf/arena.h> +#include <google/protobuf/port.h> +#include <google/protobuf/arenastring.h> +#include <google/protobuf/generated_message_util.h> +#include <google/protobuf/map.h> +#include <google/protobuf/map_type_handler.h> +#include <google/protobuf/parse_context.h> +#include <google/protobuf/wire_format_lite.h> + +// Must be included last. +#include <google/protobuf/port_def.inc> +#ifdef SWIG +#error "You cannot SWIG proto headers" +#endif + +namespace google { +namespace protobuf { +namespace internal { +template <typename Derived, typename Key, typename Value, + WireFormatLite::FieldType kKeyFieldType, + WireFormatLite::FieldType kValueFieldType> +class MapEntry; +template <typename Derived, typename Key, typename Value, + WireFormatLite::FieldType kKeyFieldType, + WireFormatLite::FieldType kValueFieldType> +class MapFieldLite; +} // namespace internal +} // namespace protobuf +} // namespace google + +namespace google { +namespace protobuf { +namespace internal { + +// MoveHelper::Move is used to set *dest. It copies *src, or moves it (in +// the C++11 sense), or swaps it. *src is left in a sane state for +// subsequent destruction, but shouldn't be used for anything. +template <bool is_enum, bool is_message, bool is_stringlike, typename T> +struct MoveHelper { // primitives + static void Move(T* src, T* dest) { *dest = *src; } +}; + +template <bool is_message, bool is_stringlike, typename T> +struct MoveHelper<true, is_message, is_stringlike, T> { // enums + static void Move(T* src, T* dest) { *dest = *src; } + // T is an enum here, so allow conversions to and from int. + static void Move(T* src, int* dest) { *dest = static_cast<int>(*src); } + static void Move(int* src, T* dest) { *dest = static_cast<T>(*src); } +}; + +template <bool is_stringlike, typename T> +struct MoveHelper<false, true, is_stringlike, T> { // messages + static void Move(T* src, T* dest) { dest->Swap(src); } +}; + +template <typename T> +struct MoveHelper<false, false, true, T> { // strings and similar + static void Move(T* src, T* dest) { + *dest = std::move(*src); + } +}; + +// MapEntryImpl is used to implement parsing and serialization of map entries. +// It uses Curious Recursive Template Pattern (CRTP) to provide the type of +// the eventual code to the template code. +template <typename Derived, typename Base, typename Key, typename Value, + WireFormatLite::FieldType kKeyFieldType, + WireFormatLite::FieldType kValueFieldType> +class MapEntryImpl : public Base { + public: + typedef MapEntryFuncs<Key, Value, kKeyFieldType, kValueFieldType> Funcs; + + protected: + // Provide utilities to parse/serialize key/value. Provide utilities to + // manipulate internal stored type. + typedef MapTypeHandler<kKeyFieldType, Key> KeyTypeHandler; + typedef MapTypeHandler<kValueFieldType, Value> ValueTypeHandler; + + // Define internal memory layout. Strings and messages are stored as + // pointers, while other types are stored as values. + typedef typename KeyTypeHandler::TypeOnMemory KeyOnMemory; + typedef typename ValueTypeHandler::TypeOnMemory ValueOnMemory; + + // Enum type cannot be used for MapTypeHandler::Read. Define a type + // which will replace Enum with int. + typedef typename KeyTypeHandler::MapEntryAccessorType KeyMapEntryAccessorType; + typedef + typename ValueTypeHandler::MapEntryAccessorType ValueMapEntryAccessorType; + + // Constants for field number. + static const int kKeyFieldNumber = 1; + static const int kValueFieldNumber = 2; + + // Constants for field tag. + static const uint8_t kKeyTag = + GOOGLE_PROTOBUF_WIRE_FORMAT_MAKE_TAG(kKeyFieldNumber, KeyTypeHandler::kWireType); + static const uint8_t kValueTag = GOOGLE_PROTOBUF_WIRE_FORMAT_MAKE_TAG( + kValueFieldNumber, ValueTypeHandler::kWireType); + static const size_t kTagSize = 1; + + public: + // Work-around for a compiler bug (see repeated_field.h). + typedef void MapEntryHasMergeTypeTrait; + typedef Derived EntryType; + typedef Key EntryKeyType; + typedef Value EntryValueType; + static const WireFormatLite::FieldType kEntryKeyFieldType = kKeyFieldType; + static const WireFormatLite::FieldType kEntryValueFieldType = kValueFieldType; + + constexpr MapEntryImpl() + : key_(KeyTypeHandler::Constinit()), + value_(ValueTypeHandler::Constinit()), + _has_bits_{} {} + + explicit MapEntryImpl(Arena* arena) + : Base(arena), + key_(KeyTypeHandler::Constinit()), + value_(ValueTypeHandler::Constinit()), + _has_bits_{} {} + + ~MapEntryImpl() override { + if (Base::GetArenaForAllocation() != nullptr) return; + KeyTypeHandler::DeleteNoArena(key_); + ValueTypeHandler::DeleteNoArena(value_); + } + + // accessors ====================================================== + + virtual inline const KeyMapEntryAccessorType& key() const { + return KeyTypeHandler::GetExternalReference(key_); + } + virtual inline const ValueMapEntryAccessorType& value() const { + return ValueTypeHandler::DefaultIfNotInitialized(value_); + } + inline KeyMapEntryAccessorType* mutable_key() { + set_has_key(); + return KeyTypeHandler::EnsureMutable(&key_, Base::GetArenaForAllocation()); + } + inline ValueMapEntryAccessorType* mutable_value() { + set_has_value(); + return ValueTypeHandler::EnsureMutable(&value_, + Base::GetArenaForAllocation()); + } + + // implements MessageLite ========================================= + + // MapEntryImpl is for implementation only and this function isn't called + // anywhere. Just provide a fake implementation here for MessageLite. + std::string GetTypeName() const override { return ""; } + + void CheckTypeAndMergeFrom(const MessageLite& other) override { + MergeFromInternal(*::google::protobuf::internal::DownCast<const Derived*>(&other)); + } + + const char* _InternalParse(const char* ptr, ParseContext* ctx) final { + while (!ctx->Done(&ptr)) { + uint32_t tag; + ptr = ReadTag(ptr, &tag); + GOOGLE_PROTOBUF_PARSER_ASSERT(ptr); + if (tag == kKeyTag) { + set_has_key(); + KeyMapEntryAccessorType* key = mutable_key(); + ptr = KeyTypeHandler::Read(ptr, ctx, key); + if (!Derived::ValidateKey(key)) return nullptr; + } else if (tag == kValueTag) { + set_has_value(); + ValueMapEntryAccessorType* value = mutable_value(); + ptr = ValueTypeHandler::Read(ptr, ctx, value); + if (!Derived::ValidateValue(value)) return nullptr; + } else { + if (tag == 0 || WireFormatLite::GetTagWireType(tag) == + WireFormatLite::WIRETYPE_END_GROUP) { + ctx->SetLastTag(tag); + return ptr; + } + ptr = UnknownFieldParse(tag, static_cast<std::string*>(nullptr), ptr, + ctx); + } + GOOGLE_PROTOBUF_PARSER_ASSERT(ptr); + } + return ptr; + } + + size_t ByteSizeLong() const override { + size_t size = 0; + size += kTagSize + static_cast<size_t>(KeyTypeHandler::ByteSize(key())); + size += kTagSize + static_cast<size_t>(ValueTypeHandler::ByteSize(value())); + return size; + } + + ::uint8_t* _InternalSerialize( + ::uint8_t* ptr, io::EpsCopyOutputStream* stream) const override { + ptr = KeyTypeHandler::Write(kKeyFieldNumber, key(), ptr, stream); + return ValueTypeHandler::Write(kValueFieldNumber, value(), ptr, stream); + } + + // Don't override SerializeWithCachedSizesToArray. Use MessageLite's. + + int GetCachedSize() const override { + int size = 0; + size += has_key() ? static_cast<int>(kTagSize) + + KeyTypeHandler::GetCachedSize(key()) + : 0; + size += has_value() ? static_cast<int>(kTagSize) + + ValueTypeHandler::GetCachedSize(value()) + : 0; + return size; + } + + bool IsInitialized() const override { + return ValueTypeHandler::IsInitialized(value_); + } + + Base* New(Arena* arena) const override { + Derived* entry = Arena::CreateMessage<Derived>(arena); + return entry; + } + + protected: + // We can't declare this function directly here as it would hide the other + // overload (const Message&). + void MergeFromInternal(const MapEntryImpl& from) { + if (from._has_bits_[0]) { + if (from.has_key()) { + KeyTypeHandler::EnsureMutable(&key_, Base::GetArenaForAllocation()); + KeyTypeHandler::Merge(from.key(), &key_, Base::GetArenaForAllocation()); + set_has_key(); + } + if (from.has_value()) { + ValueTypeHandler::EnsureMutable(&value_, Base::GetArenaForAllocation()); + ValueTypeHandler::Merge(from.value(), &value_, + Base::GetArenaForAllocation()); + set_has_value(); + } + } + } + + public: + void Clear() override { + KeyTypeHandler::Clear(&key_, Base::GetArenaForAllocation()); + ValueTypeHandler::Clear(&value_, Base::GetArenaForAllocation()); + clear_has_key(); + clear_has_value(); + } + + // Parsing using MergePartialFromCodedStream, above, is not as + // efficient as it could be. This helper class provides a speedier way. + template <typename MapField, typename Map> + class Parser { + public: + explicit Parser(MapField* mf) : mf_(mf), map_(mf->MutableMap()) {} + ~Parser() { + if (entry_ != nullptr && entry_->GetArenaForAllocation() == nullptr) + delete entry_; + } + + const char* _InternalParse(const char* ptr, ParseContext* ctx) { + if (PROTOBUF_PREDICT_TRUE(!ctx->Done(&ptr) && *ptr == kKeyTag)) { + ptr = KeyTypeHandler::Read(ptr + 1, ctx, &key_); + if (PROTOBUF_PREDICT_FALSE(!ptr || !Derived::ValidateKey(&key_))) { + return nullptr; + } + if (PROTOBUF_PREDICT_TRUE(!ctx->Done(&ptr) && *ptr == kValueTag)) { + typename Map::size_type map_size = map_->size(); + value_ptr_ = &(*map_)[key_]; + if (PROTOBUF_PREDICT_TRUE(map_size != map_->size())) { + using T = + typename MapIf<ValueTypeHandler::kIsEnum, int*, Value*>::type; + ptr = ValueTypeHandler::Read(ptr + 1, ctx, + reinterpret_cast<T>(value_ptr_)); + if (PROTOBUF_PREDICT_FALSE(!ptr || + !Derived::ValidateValue(value_ptr_))) { + map_->erase(key_); // Failure! Undo insertion. + return nullptr; + } + if (PROTOBUF_PREDICT_TRUE(ctx->Done(&ptr))) return ptr; + if (!ptr) return nullptr; + NewEntry(); + ValueMover::Move(value_ptr_, entry_->mutable_value()); + map_->erase(key_); + goto move_key; + } + } else { + if (!ptr) return nullptr; + } + NewEntry(); + move_key: + KeyMover::Move(&key_, entry_->mutable_key()); + } else { + if (!ptr) return nullptr; + NewEntry(); + } + ptr = entry_->_InternalParse(ptr, ctx); + if (ptr) UseKeyAndValueFromEntry(); + return ptr; + } + + template <typename UnknownType> + const char* ParseWithEnumValidation(const char* ptr, ParseContext* ctx, + bool (*is_valid)(int), + uint32_t field_num, + InternalMetadata* metadata) { + auto entry = NewEntry(); + ptr = entry->_InternalParse(ptr, ctx); + if (!ptr) return nullptr; + if (is_valid(entry->value())) { + UseKeyAndValueFromEntry(); + } else { + WriteLengthDelimited(field_num, entry->SerializeAsString(), + metadata->mutable_unknown_fields<UnknownType>()); + } + return ptr; + } + + MapEntryImpl* NewEntry() { return entry_ = mf_->NewEntry(); } + + const Key& key() const { return key_; } + const Value& value() const { return *value_ptr_; } + + const Key& entry_key() const { return entry_->key(); } + const Value& entry_value() const { return entry_->value(); } + + private: + void UseKeyAndValueFromEntry() { + // Update key_ in case we need it later (because key() is called). + // This is potentially inefficient, especially if the key is + // expensive to copy (e.g., a long string), but this is a cold + // path, so it's not a big deal. + key_ = entry_->key(); + value_ptr_ = &(*map_)[key_]; + ValueMover::Move(entry_->mutable_value(), value_ptr_); + } + + // After reading a key and value successfully, and inserting that data + // into map_, we are not at the end of the input. This is unusual, but + // allowed by the spec. + bool ReadBeyondKeyValuePair(io::CodedInputStream* input) PROTOBUF_COLD { + NewEntry(); + ValueMover::Move(value_ptr_, entry_->mutable_value()); + map_->erase(key_); + KeyMover::Move(&key_, entry_->mutable_key()); + const bool result = entry_->MergePartialFromCodedStream(input); + if (result) UseKeyAndValueFromEntry(); + return result; + } + + typedef MoveHelper<KeyTypeHandler::kIsEnum, KeyTypeHandler::kIsMessage, + KeyTypeHandler::kWireType == + WireFormatLite::WIRETYPE_LENGTH_DELIMITED, + Key> + KeyMover; + typedef MoveHelper<ValueTypeHandler::kIsEnum, ValueTypeHandler::kIsMessage, + ValueTypeHandler::kWireType == + WireFormatLite::WIRETYPE_LENGTH_DELIMITED, + Value> + ValueMover; + + MapField* const mf_; + Map* const map_; + Key key_; + Value* value_ptr_; + MapEntryImpl* entry_ = nullptr; + }; + + protected: + void set_has_key() { _has_bits_[0] |= 0x00000001u; } + bool has_key() const { return (_has_bits_[0] & 0x00000001u) != 0; } + void clear_has_key() { _has_bits_[0] &= ~0x00000001u; } + void set_has_value() { _has_bits_[0] |= 0x00000002u; } + bool has_value() const { return (_has_bits_[0] & 0x00000002u) != 0; } + void clear_has_value() { _has_bits_[0] &= ~0x00000002u; } + + public: + inline Arena* GetArena() const { return Base::GetArena(); } + + protected: // Needed for constructing tables + KeyOnMemory key_; + ValueOnMemory value_; + uint32_t _has_bits_[1]; + + private: + friend class ::PROTOBUF_NAMESPACE_ID::Arena; + typedef void InternalArenaConstructable_; + typedef void DestructorSkippable_; + template <typename C, typename K, typename V, WireFormatLite::FieldType, + WireFormatLite::FieldType> + friend class internal::MapEntry; + template <typename C, typename K, typename V, WireFormatLite::FieldType, + WireFormatLite::FieldType> + friend class internal::MapFieldLite; + + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MapEntryImpl); +}; + +template <typename T, typename Key, typename Value, + WireFormatLite::FieldType kKeyFieldType, + WireFormatLite::FieldType kValueFieldType> +class MapEntryLite : public MapEntryImpl<T, MessageLite, Key, Value, + kKeyFieldType, kValueFieldType> { + public: + typedef MapEntryImpl<T, MessageLite, Key, Value, kKeyFieldType, + kValueFieldType> + SuperType; + constexpr MapEntryLite() {} + explicit MapEntryLite(Arena* arena) : SuperType(arena) {} + ~MapEntryLite() override { + MessageLite::_internal_metadata_.template Delete<std::string>(); + } + void MergeFrom(const MapEntryLite& other) { MergeFromInternal(other); } + + private: + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MapEntryLite); +}; + +// Helpers for deterministic serialization ============================= + +// Iterator base for MapSorterFlat and MapSorterPtr. +template <typename storage_type> +struct MapSorterIt { + storage_type* ptr; + MapSorterIt(storage_type* ptr) : ptr(ptr) {} + bool operator==(const MapSorterIt& other) const { return ptr == other.ptr; } + bool operator!=(const MapSorterIt& other) const { return !(*this == other); } + MapSorterIt& operator++() { ++ptr; return *this; } + MapSorterIt operator++(int) { auto other = *this; ++ptr; return other; } + MapSorterIt operator+(int v) { return MapSorterIt{ptr + v}; } +}; + +// MapSorterFlat stores keys inline with pointers to map entries, so that +// keys can be compared without indirection. This type is used for maps with +// keys that are not strings. +template <typename MapT> +class MapSorterFlat { + public: + using value_type = typename MapT::value_type; + using storage_type = std::pair<typename MapT::key_type, const value_type*>; + + // This const_iterator dereferenes to the map entry stored in the sorting + // array pairs. This is the same interface as the Map::const_iterator type, + // and allows generated code to use the same loop body with either form: + // for (const auto& entry : map) { ... } + // for (const auto& entry : MapSorterFlat(map)) { ... } + struct const_iterator : public MapSorterIt<storage_type> { + using pointer = const typename MapT::value_type*; + using reference = const typename MapT::value_type&; + using MapSorterIt<storage_type>::MapSorterIt; + + pointer operator->() const { return this->ptr->second; } + reference operator*() const { return *this->operator->(); } + }; + + explicit MapSorterFlat(const MapT& m) + : size_(m.size()), items_(size_ ? new storage_type[size_] : nullptr) { + if (!size_) return; + storage_type* it = &items_[0]; + for (const auto& entry : m) { + *it++ = {entry.first, &entry}; + } + std::sort(&items_[0], &items_[size_], + [](const storage_type& a, const storage_type& b) { + return a.first < b.first; + }); + } + size_t size() const { return size_; } + const_iterator begin() const { return {items_.get()}; } + const_iterator end() const { return {items_.get() + size_}; } + + private: + size_t size_; + std::unique_ptr<storage_type[]> items_; +}; + +// MapSorterPtr stores and sorts pointers to map entries. This type is used for +// maps with keys that are strings. +template <typename MapT> +class MapSorterPtr { + public: + using value_type = typename MapT::value_type; + using storage_type = const typename MapT::value_type*; + + // This const_iterator dereferenes the map entry pointer stored in the sorting + // array. This is the same interface as the Map::const_iterator type, and + // allows generated code to use the same loop body with either form: + // for (const auto& entry : map) { ... } + // for (const auto& entry : MapSorterPtr(map)) { ... } + struct const_iterator : public MapSorterIt<storage_type> { + using pointer = const typename MapT::value_type*; + using reference = const typename MapT::value_type&; + using MapSorterIt<storage_type>::MapSorterIt; + + pointer operator->() const { return *this->ptr; } + reference operator*() const { return *this->operator->(); } + }; + + explicit MapSorterPtr(const MapT& m) + : size_(m.size()), items_(size_ ? new storage_type[size_] : nullptr) { + if (!size_) return; + storage_type* it = &items_[0]; + for (const auto& entry : m) { + *it++ = &entry; + } + std::sort(&items_[0], &items_[size_], + [](const storage_type& a, const storage_type& b) { + return a->first < b->first; + }); + } + size_t size() const { return size_; } + const_iterator begin() const { return {items_.get()}; } + const_iterator end() const { return {items_.get() + size_}; } + + private: + size_t size_; + std::unique_ptr<storage_type[]> items_; +}; + +} // namespace internal +} // namespace protobuf +} // namespace google + +#include <google/protobuf/port_undef.inc> + +#endif // GOOGLE_PROTOBUF_MAP_ENTRY_LITE_H__ diff --git a/toolkit/components/protobuf/src/google/protobuf/map_field.cc b/toolkit/components/protobuf/src/google/protobuf/map_field.cc new file mode 100644 index 0000000000..ed662dfc43 --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/map_field.cc @@ -0,0 +1,654 @@ +// 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. + +#include <google/protobuf/map_field.h> + +#include <vector> + +#include <google/protobuf/map_field_inl.h> + +// Must be included last. +#include <google/protobuf/port_def.inc> + +namespace google { +namespace protobuf { +namespace internal { + +void MapFieldBase::Destruct() { + if (arena_ == nullptr) { + delete repeated_field_; + } + repeated_field_ = nullptr; +} + +const RepeatedPtrFieldBase& MapFieldBase::GetRepeatedField() const { + ConstAccess(); + SyncRepeatedFieldWithMap(); + return *reinterpret_cast<RepeatedPtrFieldBase*>(repeated_field_); +} + +RepeatedPtrFieldBase* MapFieldBase::MutableRepeatedField() { + MutableAccess(); + SyncRepeatedFieldWithMap(); + SetRepeatedDirty(); + return reinterpret_cast<RepeatedPtrFieldBase*>(repeated_field_); +} + +void MapFieldBase::SwapState(MapFieldBase* other) { + // a relaxed swap of the atomic + auto other_state = other->state_.load(std::memory_order_relaxed); + auto this_state = state_.load(std::memory_order_relaxed); + other->state_.store(this_state, std::memory_order_relaxed); + state_.store(other_state, std::memory_order_relaxed); +} + +void SwapRepeatedPtrToNull(RepeatedPtrField<Message>** from, + RepeatedPtrField<Message>** to, Arena* from_arena, + Arena* to_arena) { + GOOGLE_DCHECK(*from != nullptr); + GOOGLE_DCHECK(*to == nullptr); + *to = Arena::CreateMessage<RepeatedPtrField<Message> >(to_arena); + **to = std::move(**from); + if (from_arena == nullptr) { + delete *from; + } + *from = nullptr; +} + +void MapFieldBase::Swap(MapFieldBase* other) { + if (arena_ == other->arena_) { + InternalSwap(other); + return; + } + if (repeated_field_ != nullptr || other->repeated_field_ != nullptr) { + if (repeated_field_ == nullptr) { + SwapRepeatedPtrToNull(&other->repeated_field_, &repeated_field_, + other->arena_, arena_); + } else if (other->repeated_field_ == nullptr) { + SwapRepeatedPtrToNull(&repeated_field_, &other->repeated_field_, arena_, + other->arena_); + } else { + repeated_field_->Swap(other->repeated_field_); + } + } + SwapState(other); +} + +void MapFieldBase::UnsafeShallowSwap(MapFieldBase* other) { + GOOGLE_DCHECK_EQ(arena_, other->arena_); + InternalSwap(other); +} + +void MapFieldBase::InternalSwap(MapFieldBase* other) { + std::swap(arena_, other->arena_); + std::swap(repeated_field_, other->repeated_field_); + SwapState(other); +} + +size_t MapFieldBase::SpaceUsedExcludingSelfLong() const { + ConstAccess(); + mutex_.Lock(); + size_t size = SpaceUsedExcludingSelfNoLock(); + mutex_.Unlock(); + ConstAccess(); + return size; +} + +size_t MapFieldBase::SpaceUsedExcludingSelfNoLock() const { + if (repeated_field_ != nullptr) { + return repeated_field_->SpaceUsedExcludingSelfLong(); + } else { + return 0; + } +} + +bool MapFieldBase::IsMapValid() const { + ConstAccess(); + // "Acquire" insures the operation after SyncRepeatedFieldWithMap won't get + // executed before state_ is checked. + int state = state_.load(std::memory_order_acquire); + return state != STATE_MODIFIED_REPEATED; +} + +bool MapFieldBase::IsRepeatedFieldValid() const { + ConstAccess(); + int state = state_.load(std::memory_order_acquire); + return state != STATE_MODIFIED_MAP; +} + +void MapFieldBase::SetMapDirty() { + MutableAccess(); + // These are called by (non-const) mutator functions. So by our API it's the + // callers responsibility to have these calls properly ordered. + state_.store(STATE_MODIFIED_MAP, std::memory_order_relaxed); +} + +void MapFieldBase::SetRepeatedDirty() { + MutableAccess(); + // These are called by (non-const) mutator functions. So by our API it's the + // callers responsibility to have these calls properly ordered. + state_.store(STATE_MODIFIED_REPEATED, std::memory_order_relaxed); +} + +void MapFieldBase::SyncRepeatedFieldWithMap() const { + ConstAccess(); + // acquire here matches with release below to ensure that we can only see a + // value of CLEAN after all previous changes have been synced. + switch (state_.load(std::memory_order_acquire)) { + case STATE_MODIFIED_MAP: + mutex_.Lock(); + // Double check state, because another thread may have seen the same + // state and done the synchronization before the current thread. + if (state_.load(std::memory_order_relaxed) == STATE_MODIFIED_MAP) { + SyncRepeatedFieldWithMapNoLock(); + state_.store(CLEAN, std::memory_order_release); + } + mutex_.Unlock(); + ConstAccess(); + break; + case CLEAN: + mutex_.Lock(); + // Double check state + if (state_.load(std::memory_order_relaxed) == CLEAN) { + if (repeated_field_ == nullptr) { + repeated_field_ = + Arena::CreateMessage<RepeatedPtrField<Message> >(arena_); + } + state_.store(CLEAN, std::memory_order_release); + } + mutex_.Unlock(); + ConstAccess(); + break; + default: + break; + } +} + +void MapFieldBase::SyncRepeatedFieldWithMapNoLock() const { + if (repeated_field_ == nullptr) { + repeated_field_ = Arena::CreateMessage<RepeatedPtrField<Message> >(arena_); + } +} + +void MapFieldBase::SyncMapWithRepeatedField() const { + ConstAccess(); + // acquire here matches with release below to ensure that we can only see a + // value of CLEAN after all previous changes have been synced. + if (state_.load(std::memory_order_acquire) == STATE_MODIFIED_REPEATED) { + mutex_.Lock(); + // Double check state, because another thread may have seen the same state + // and done the synchronization before the current thread. + if (state_.load(std::memory_order_relaxed) == STATE_MODIFIED_REPEATED) { + SyncMapWithRepeatedFieldNoLock(); + state_.store(CLEAN, std::memory_order_release); + } + mutex_.Unlock(); + ConstAccess(); + } +} + +// ------------------DynamicMapField------------------ +DynamicMapField::DynamicMapField(const Message* default_entry) + : default_entry_(default_entry) {} + +DynamicMapField::DynamicMapField(const Message* default_entry, Arena* arena) + : TypeDefinedMapFieldBase<MapKey, MapValueRef>(arena), + map_(arena), + default_entry_(default_entry) {} + +DynamicMapField::~DynamicMapField() { + if (arena_ == nullptr) { + // DynamicMapField owns map values. Need to delete them before clearing the + // map. + for (auto& kv : map_) { + kv.second.DeleteData(); + } + map_.clear(); + } + Destruct(); +} + +int DynamicMapField::size() const { return GetMap().size(); } + +void DynamicMapField::Clear() { + Map<MapKey, MapValueRef>* map = &const_cast<DynamicMapField*>(this)->map_; + if (MapFieldBase::arena_ == nullptr) { + for (Map<MapKey, MapValueRef>::iterator iter = map->begin(); + iter != map->end(); ++iter) { + iter->second.DeleteData(); + } + } + + map->clear(); + + if (MapFieldBase::repeated_field_ != nullptr) { + MapFieldBase::repeated_field_->Clear(); + } + // Data in map and repeated field are both empty, but we can't set status + // CLEAN which will invalidate previous reference to map. + MapFieldBase::SetMapDirty(); +} + +bool DynamicMapField::ContainsMapKey(const MapKey& map_key) const { + const Map<MapKey, MapValueRef>& map = GetMap(); + Map<MapKey, MapValueRef>::const_iterator iter = map.find(map_key); + return iter != map.end(); +} + +void DynamicMapField::AllocateMapValue(MapValueRef* map_val) { + const FieldDescriptor* val_des = default_entry_->GetDescriptor()->map_value(); + map_val->SetType(val_des->cpp_type()); + // Allocate memory for the MapValueRef, and initialize to + // default value. + switch (val_des->cpp_type()) { +#define HANDLE_TYPE(CPPTYPE, TYPE) \ + case FieldDescriptor::CPPTYPE_##CPPTYPE: { \ + TYPE* value = Arena::Create<TYPE>(MapFieldBase::arena_); \ + map_val->SetValue(value); \ + break; \ + } + HANDLE_TYPE(INT32, int32_t); + HANDLE_TYPE(INT64, int64_t); + HANDLE_TYPE(UINT32, uint32_t); + HANDLE_TYPE(UINT64, uint64_t); + HANDLE_TYPE(DOUBLE, double); + HANDLE_TYPE(FLOAT, float); + HANDLE_TYPE(BOOL, bool); + HANDLE_TYPE(STRING, std::string); + HANDLE_TYPE(ENUM, int32_t); +#undef HANDLE_TYPE + case FieldDescriptor::CPPTYPE_MESSAGE: { + const Message& message = + default_entry_->GetReflection()->GetMessage(*default_entry_, val_des); + Message* value = message.New(MapFieldBase::arena_); + map_val->SetValue(value); + break; + } + } +} + +bool DynamicMapField::InsertOrLookupMapValue(const MapKey& map_key, + MapValueRef* val) { + // Always use mutable map because users may change the map value by + // MapValueRef. + Map<MapKey, MapValueRef>* map = MutableMap(); + Map<MapKey, MapValueRef>::iterator iter = map->find(map_key); + if (iter == map->end()) { + MapValueRef& map_val = map_[map_key]; + AllocateMapValue(&map_val); + val->CopyFrom(map_val); + return true; + } + // map_key is already in the map. Make sure (*map)[map_key] is not called. + // [] may reorder the map and iterators. + val->CopyFrom(iter->second); + return false; +} + +bool DynamicMapField::LookupMapValue(const MapKey& map_key, + MapValueConstRef* val) const { + const Map<MapKey, MapValueRef>& map = GetMap(); + Map<MapKey, MapValueRef>::const_iterator iter = map.find(map_key); + if (iter == map.end()) { + return false; + } + // map_key is already in the map. Make sure (*map)[map_key] is not called. + // [] may reorder the map and iterators. + val->CopyFrom(iter->second); + return true; +} + +bool DynamicMapField::DeleteMapValue(const MapKey& map_key) { + MapFieldBase::SyncMapWithRepeatedField(); + Map<MapKey, MapValueRef>::iterator iter = map_.find(map_key); + if (iter == map_.end()) { + return false; + } + // Set map dirty only if the delete is successful. + MapFieldBase::SetMapDirty(); + if (MapFieldBase::arena_ == nullptr) { + iter->second.DeleteData(); + } + map_.erase(iter); + return true; +} + +const Map<MapKey, MapValueRef>& DynamicMapField::GetMap() const { + MapFieldBase::SyncMapWithRepeatedField(); + return map_; +} + +Map<MapKey, MapValueRef>* DynamicMapField::MutableMap() { + MapFieldBase::SyncMapWithRepeatedField(); + MapFieldBase::SetMapDirty(); + return &map_; +} + +void DynamicMapField::SetMapIteratorValue(MapIterator* map_iter) const { + Map<MapKey, MapValueRef>::const_iterator iter = + TypeDefinedMapFieldBase<MapKey, MapValueRef>::InternalGetIterator( + map_iter); + if (iter == map_.end()) return; + map_iter->key_.CopyFrom(iter->first); + map_iter->value_.CopyFrom(iter->second); +} + +void DynamicMapField::MergeFrom(const MapFieldBase& other) { + GOOGLE_DCHECK(IsMapValid() && other.IsMapValid()); + Map<MapKey, MapValueRef>* map = MutableMap(); + const DynamicMapField& other_field = + reinterpret_cast<const DynamicMapField&>(other); + for (Map<MapKey, MapValueRef>::const_iterator other_it = + other_field.map_.begin(); + other_it != other_field.map_.end(); ++other_it) { + Map<MapKey, MapValueRef>::iterator iter = map->find(other_it->first); + MapValueRef* map_val; + if (iter == map->end()) { + map_val = &map_[other_it->first]; + AllocateMapValue(map_val); + } else { + map_val = &iter->second; + } + + // Copy map value + const FieldDescriptor* field_descriptor = + default_entry_->GetDescriptor()->map_value(); + switch (field_descriptor->cpp_type()) { + case FieldDescriptor::CPPTYPE_INT32: { + map_val->SetInt32Value(other_it->second.GetInt32Value()); + break; + } + case FieldDescriptor::CPPTYPE_INT64: { + map_val->SetInt64Value(other_it->second.GetInt64Value()); + break; + } + case FieldDescriptor::CPPTYPE_UINT32: { + map_val->SetUInt32Value(other_it->second.GetUInt32Value()); + break; + } + case FieldDescriptor::CPPTYPE_UINT64: { + map_val->SetUInt64Value(other_it->second.GetUInt64Value()); + break; + } + case FieldDescriptor::CPPTYPE_FLOAT: { + map_val->SetFloatValue(other_it->second.GetFloatValue()); + break; + } + case FieldDescriptor::CPPTYPE_DOUBLE: { + map_val->SetDoubleValue(other_it->second.GetDoubleValue()); + break; + } + case FieldDescriptor::CPPTYPE_BOOL: { + map_val->SetBoolValue(other_it->second.GetBoolValue()); + break; + } + case FieldDescriptor::CPPTYPE_STRING: { + map_val->SetStringValue(other_it->second.GetStringValue()); + break; + } + case FieldDescriptor::CPPTYPE_ENUM: { + map_val->SetEnumValue(other_it->second.GetEnumValue()); + break; + } + case FieldDescriptor::CPPTYPE_MESSAGE: { + map_val->MutableMessageValue()->CopyFrom( + other_it->second.GetMessageValue()); + break; + } + } + } +} + +void DynamicMapField::Swap(MapFieldBase* other) { + DynamicMapField* other_field = down_cast<DynamicMapField*>(other); + std::swap(this->MapFieldBase::repeated_field_, other_field->repeated_field_); + map_.swap(other_field->map_); + // a relaxed swap of the atomic + auto other_state = other_field->state_.load(std::memory_order_relaxed); + auto this_state = this->MapFieldBase::state_.load(std::memory_order_relaxed); + other_field->state_.store(this_state, std::memory_order_relaxed); + this->MapFieldBase::state_.store(other_state, std::memory_order_relaxed); +} + +void DynamicMapField::SyncRepeatedFieldWithMapNoLock() const { + const Reflection* reflection = default_entry_->GetReflection(); + const FieldDescriptor* key_des = default_entry_->GetDescriptor()->map_key(); + const FieldDescriptor* val_des = default_entry_->GetDescriptor()->map_value(); + if (MapFieldBase::repeated_field_ == nullptr) { + MapFieldBase::repeated_field_ = + Arena::CreateMessage<RepeatedPtrField<Message> >(MapFieldBase::arena_); + } + + MapFieldBase::repeated_field_->Clear(); + + for (Map<MapKey, MapValueRef>::const_iterator it = map_.begin(); + it != map_.end(); ++it) { + Message* new_entry = default_entry_->New(MapFieldBase::arena_); + MapFieldBase::repeated_field_->AddAllocated(new_entry); + const MapKey& map_key = it->first; + switch (key_des->cpp_type()) { + case FieldDescriptor::CPPTYPE_STRING: + reflection->SetString(new_entry, key_des, map_key.GetStringValue()); + break; + case FieldDescriptor::CPPTYPE_INT64: + reflection->SetInt64(new_entry, key_des, map_key.GetInt64Value()); + break; + case FieldDescriptor::CPPTYPE_INT32: + reflection->SetInt32(new_entry, key_des, map_key.GetInt32Value()); + break; + case FieldDescriptor::CPPTYPE_UINT64: + reflection->SetUInt64(new_entry, key_des, map_key.GetUInt64Value()); + break; + case FieldDescriptor::CPPTYPE_UINT32: + reflection->SetUInt32(new_entry, key_des, map_key.GetUInt32Value()); + break; + case FieldDescriptor::CPPTYPE_BOOL: + reflection->SetBool(new_entry, key_des, map_key.GetBoolValue()); + break; + case FieldDescriptor::CPPTYPE_DOUBLE: + case FieldDescriptor::CPPTYPE_FLOAT: + case FieldDescriptor::CPPTYPE_ENUM: + case FieldDescriptor::CPPTYPE_MESSAGE: + GOOGLE_LOG(FATAL) << "Can't get here."; + break; + } + const MapValueRef& map_val = it->second; + switch (val_des->cpp_type()) { + case FieldDescriptor::CPPTYPE_STRING: + reflection->SetString(new_entry, val_des, map_val.GetStringValue()); + break; + case FieldDescriptor::CPPTYPE_INT64: + reflection->SetInt64(new_entry, val_des, map_val.GetInt64Value()); + break; + case FieldDescriptor::CPPTYPE_INT32: + reflection->SetInt32(new_entry, val_des, map_val.GetInt32Value()); + break; + case FieldDescriptor::CPPTYPE_UINT64: + reflection->SetUInt64(new_entry, val_des, map_val.GetUInt64Value()); + break; + case FieldDescriptor::CPPTYPE_UINT32: + reflection->SetUInt32(new_entry, val_des, map_val.GetUInt32Value()); + break; + case FieldDescriptor::CPPTYPE_BOOL: + reflection->SetBool(new_entry, val_des, map_val.GetBoolValue()); + break; + case FieldDescriptor::CPPTYPE_DOUBLE: + reflection->SetDouble(new_entry, val_des, map_val.GetDoubleValue()); + break; + case FieldDescriptor::CPPTYPE_FLOAT: + reflection->SetFloat(new_entry, val_des, map_val.GetFloatValue()); + break; + case FieldDescriptor::CPPTYPE_ENUM: + reflection->SetEnumValue(new_entry, val_des, map_val.GetEnumValue()); + break; + case FieldDescriptor::CPPTYPE_MESSAGE: { + const Message& message = map_val.GetMessageValue(); + reflection->MutableMessage(new_entry, val_des)->CopyFrom(message); + break; + } + } + } +} + +void DynamicMapField::SyncMapWithRepeatedFieldNoLock() const { + Map<MapKey, MapValueRef>* map = &const_cast<DynamicMapField*>(this)->map_; + const Reflection* reflection = default_entry_->GetReflection(); + const FieldDescriptor* key_des = default_entry_->GetDescriptor()->map_key(); + const FieldDescriptor* val_des = default_entry_->GetDescriptor()->map_value(); + // DynamicMapField owns map values. Need to delete them before clearing + // the map. + if (MapFieldBase::arena_ == nullptr) { + for (Map<MapKey, MapValueRef>::iterator iter = map->begin(); + iter != map->end(); ++iter) { + iter->second.DeleteData(); + } + } + map->clear(); + for (RepeatedPtrField<Message>::iterator it = + MapFieldBase::repeated_field_->begin(); + it != MapFieldBase::repeated_field_->end(); ++it) { + // MapKey type will be set later. + MapKey map_key; + switch (key_des->cpp_type()) { + case FieldDescriptor::CPPTYPE_STRING: + map_key.SetStringValue(reflection->GetString(*it, key_des)); + break; + case FieldDescriptor::CPPTYPE_INT64: + map_key.SetInt64Value(reflection->GetInt64(*it, key_des)); + break; + case FieldDescriptor::CPPTYPE_INT32: + map_key.SetInt32Value(reflection->GetInt32(*it, key_des)); + break; + case FieldDescriptor::CPPTYPE_UINT64: + map_key.SetUInt64Value(reflection->GetUInt64(*it, key_des)); + break; + case FieldDescriptor::CPPTYPE_UINT32: + map_key.SetUInt32Value(reflection->GetUInt32(*it, key_des)); + break; + case FieldDescriptor::CPPTYPE_BOOL: + map_key.SetBoolValue(reflection->GetBool(*it, key_des)); + break; + case FieldDescriptor::CPPTYPE_DOUBLE: + case FieldDescriptor::CPPTYPE_FLOAT: + case FieldDescriptor::CPPTYPE_ENUM: + case FieldDescriptor::CPPTYPE_MESSAGE: + GOOGLE_LOG(FATAL) << "Can't get here."; + break; + } + + if (MapFieldBase::arena_ == nullptr) { + // Remove existing map value with same key. + Map<MapKey, MapValueRef>::iterator iter = map->find(map_key); + if (iter != map->end()) { + iter->second.DeleteData(); + } + } + + MapValueRef& map_val = (*map)[map_key]; + map_val.SetType(val_des->cpp_type()); + switch (val_des->cpp_type()) { +#define HANDLE_TYPE(CPPTYPE, TYPE, METHOD) \ + case FieldDescriptor::CPPTYPE_##CPPTYPE: { \ + TYPE* value = Arena::Create<TYPE>(MapFieldBase::arena_); \ + *value = reflection->Get##METHOD(*it, val_des); \ + map_val.SetValue(value); \ + break; \ + } + HANDLE_TYPE(INT32, int32_t, Int32); + HANDLE_TYPE(INT64, int64_t, Int64); + HANDLE_TYPE(UINT32, uint32_t, UInt32); + HANDLE_TYPE(UINT64, uint64_t, UInt64); + HANDLE_TYPE(DOUBLE, double, Double); + HANDLE_TYPE(FLOAT, float, Float); + HANDLE_TYPE(BOOL, bool, Bool); + HANDLE_TYPE(STRING, std::string, String); + HANDLE_TYPE(ENUM, int32_t, EnumValue); +#undef HANDLE_TYPE + case FieldDescriptor::CPPTYPE_MESSAGE: { + const Message& message = reflection->GetMessage(*it, val_des); + Message* value = message.New(MapFieldBase::arena_); + value->CopyFrom(message); + map_val.SetValue(value); + break; + } + } + } +} + +size_t DynamicMapField::SpaceUsedExcludingSelfNoLock() const { + size_t size = 0; + if (MapFieldBase::repeated_field_ != nullptr) { + size += MapFieldBase::repeated_field_->SpaceUsedExcludingSelfLong(); + } + size += sizeof(map_); + size_t map_size = map_.size(); + if (map_size) { + Map<MapKey, MapValueRef>::const_iterator it = map_.begin(); + size += sizeof(it->first) * map_size; + size += sizeof(it->second) * map_size; + // If key is string, add the allocated space. + if (it->first.type() == FieldDescriptor::CPPTYPE_STRING) { + size += sizeof(std::string) * map_size; + } + // Add the allocated space in MapValueRef. + switch (it->second.type()) { +#define HANDLE_TYPE(CPPTYPE, TYPE) \ + case FieldDescriptor::CPPTYPE_##CPPTYPE: { \ + size += sizeof(TYPE) * map_size; \ + break; \ + } + HANDLE_TYPE(INT32, int32_t); + HANDLE_TYPE(INT64, int64_t); + HANDLE_TYPE(UINT32, uint32_t); + HANDLE_TYPE(UINT64, uint64_t); + HANDLE_TYPE(DOUBLE, double); + HANDLE_TYPE(FLOAT, float); + HANDLE_TYPE(BOOL, bool); + HANDLE_TYPE(STRING, std::string); + HANDLE_TYPE(ENUM, int32_t); +#undef HANDLE_TYPE + case FieldDescriptor::CPPTYPE_MESSAGE: { + while (it != map_.end()) { + const Message& message = it->second.GetMessageValue(); + size += message.GetReflection()->SpaceUsedLong(message); + ++it; + } + break; + } + } + } + return size; +} + +} // namespace internal +} // namespace protobuf +} // namespace google + +#include <google/protobuf/port_undef.inc> diff --git a/toolkit/components/protobuf/src/google/protobuf/map_field.h b/toolkit/components/protobuf/src/google/protobuf/map_field.h new file mode 100644 index 0000000000..287d58f312 --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/map_field.h @@ -0,0 +1,946 @@ +// 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. + +#ifndef GOOGLE_PROTOBUF_MAP_FIELD_H__ +#define GOOGLE_PROTOBUF_MAP_FIELD_H__ + +#include <atomic> +#include <functional> + +#include <google/protobuf/arena.h> +#include <google/protobuf/stubs/mutex.h> +#include <google/protobuf/port.h> +#include <google/protobuf/descriptor.h> +#include <google/protobuf/generated_message_reflection.h> +#include <google/protobuf/generated_message_util.h> +#include <google/protobuf/map_entry.h> +#include <google/protobuf/map_field_lite.h> +#include <google/protobuf/map_type_handler.h> +#include <google/protobuf/message.h> +#include <google/protobuf/repeated_field.h> +#include <google/protobuf/unknown_field_set.h> + + +// Must be included last. +#include <google/protobuf/port_def.inc> + +#ifdef SWIG +#error "You cannot SWIG proto headers" +#endif + +namespace google { +namespace protobuf { +class DynamicMessage; +class MapIterator; + +// Microsoft compiler complains about non-virtual destructor, +// even when the destructor is private. +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable : 4265) +#endif // _MSC_VER + +#define TYPE_CHECK(EXPECTEDTYPE, METHOD) \ + if (type() != EXPECTEDTYPE) { \ + GOOGLE_LOG(FATAL) << "Protocol Buffer map usage error:\n" \ + << METHOD << " type does not match\n" \ + << " Expected : " \ + << FieldDescriptor::CppTypeName(EXPECTEDTYPE) << "\n" \ + << " Actual : " << FieldDescriptor::CppTypeName(type()); \ + } + +// MapKey is an union type for representing any possible +// map key. +class PROTOBUF_EXPORT MapKey { + public: + MapKey() : type_() {} + MapKey(const MapKey& other) : type_() { CopyFrom(other); } + + MapKey& operator=(const MapKey& other) { + CopyFrom(other); + return *this; + } + + ~MapKey() { + if (type_ == FieldDescriptor::CPPTYPE_STRING) { + val_.string_value_.Destruct(); + } + } + + FieldDescriptor::CppType type() const { + if (type_ == FieldDescriptor::CppType()) { + GOOGLE_LOG(FATAL) << "Protocol Buffer map usage error:\n" + << "MapKey::type MapKey is not initialized. " + << "Call set methods to initialize MapKey."; + } + return type_; + } + + void SetInt64Value(int64_t value) { + SetType(FieldDescriptor::CPPTYPE_INT64); + val_.int64_value_ = value; + } + void SetUInt64Value(uint64_t value) { + SetType(FieldDescriptor::CPPTYPE_UINT64); + val_.uint64_value_ = value; + } + void SetInt32Value(int32_t value) { + SetType(FieldDescriptor::CPPTYPE_INT32); + val_.int32_value_ = value; + } + void SetUInt32Value(uint32_t value) { + SetType(FieldDescriptor::CPPTYPE_UINT32); + val_.uint32_value_ = value; + } + void SetBoolValue(bool value) { + SetType(FieldDescriptor::CPPTYPE_BOOL); + val_.bool_value_ = value; + } + void SetStringValue(std::string val) { + SetType(FieldDescriptor::CPPTYPE_STRING); + *val_.string_value_.get_mutable() = std::move(val); + } + + int64_t GetInt64Value() const { + TYPE_CHECK(FieldDescriptor::CPPTYPE_INT64, "MapKey::GetInt64Value"); + return val_.int64_value_; + } + uint64_t GetUInt64Value() const { + TYPE_CHECK(FieldDescriptor::CPPTYPE_UINT64, "MapKey::GetUInt64Value"); + return val_.uint64_value_; + } + int32_t GetInt32Value() const { + TYPE_CHECK(FieldDescriptor::CPPTYPE_INT32, "MapKey::GetInt32Value"); + return val_.int32_value_; + } + uint32_t GetUInt32Value() const { + TYPE_CHECK(FieldDescriptor::CPPTYPE_UINT32, "MapKey::GetUInt32Value"); + return val_.uint32_value_; + } + bool GetBoolValue() const { + TYPE_CHECK(FieldDescriptor::CPPTYPE_BOOL, "MapKey::GetBoolValue"); + return val_.bool_value_; + } + const std::string& GetStringValue() const { + TYPE_CHECK(FieldDescriptor::CPPTYPE_STRING, "MapKey::GetStringValue"); + return val_.string_value_.get(); + } + + bool operator<(const MapKey& other) const { + if (type_ != other.type_) { + // We could define a total order that handles this case, but + // there currently no need. So, for now, fail. + GOOGLE_LOG(FATAL) << "Unsupported: type mismatch"; + } + switch (type()) { + case FieldDescriptor::CPPTYPE_DOUBLE: + case FieldDescriptor::CPPTYPE_FLOAT: + case FieldDescriptor::CPPTYPE_ENUM: + case FieldDescriptor::CPPTYPE_MESSAGE: + GOOGLE_LOG(FATAL) << "Unsupported"; + return false; + case FieldDescriptor::CPPTYPE_STRING: + return val_.string_value_.get() < other.val_.string_value_.get(); + case FieldDescriptor::CPPTYPE_INT64: + return val_.int64_value_ < other.val_.int64_value_; + case FieldDescriptor::CPPTYPE_INT32: + return val_.int32_value_ < other.val_.int32_value_; + case FieldDescriptor::CPPTYPE_UINT64: + return val_.uint64_value_ < other.val_.uint64_value_; + case FieldDescriptor::CPPTYPE_UINT32: + return val_.uint32_value_ < other.val_.uint32_value_; + case FieldDescriptor::CPPTYPE_BOOL: + return val_.bool_value_ < other.val_.bool_value_; + } + return false; + } + + bool operator==(const MapKey& other) const { + if (type_ != other.type_) { + // To be consistent with operator<, we don't allow this either. + GOOGLE_LOG(FATAL) << "Unsupported: type mismatch"; + } + switch (type()) { + case FieldDescriptor::CPPTYPE_DOUBLE: + case FieldDescriptor::CPPTYPE_FLOAT: + case FieldDescriptor::CPPTYPE_ENUM: + case FieldDescriptor::CPPTYPE_MESSAGE: + GOOGLE_LOG(FATAL) << "Unsupported"; + break; + case FieldDescriptor::CPPTYPE_STRING: + return val_.string_value_.get() == other.val_.string_value_.get(); + case FieldDescriptor::CPPTYPE_INT64: + return val_.int64_value_ == other.val_.int64_value_; + case FieldDescriptor::CPPTYPE_INT32: + return val_.int32_value_ == other.val_.int32_value_; + case FieldDescriptor::CPPTYPE_UINT64: + return val_.uint64_value_ == other.val_.uint64_value_; + case FieldDescriptor::CPPTYPE_UINT32: + return val_.uint32_value_ == other.val_.uint32_value_; + case FieldDescriptor::CPPTYPE_BOOL: + return val_.bool_value_ == other.val_.bool_value_; + } + GOOGLE_LOG(FATAL) << "Can't get here."; + return false; + } + + void CopyFrom(const MapKey& other) { + SetType(other.type()); + switch (type_) { + case FieldDescriptor::CPPTYPE_DOUBLE: + case FieldDescriptor::CPPTYPE_FLOAT: + case FieldDescriptor::CPPTYPE_ENUM: + case FieldDescriptor::CPPTYPE_MESSAGE: + GOOGLE_LOG(FATAL) << "Unsupported"; + break; + case FieldDescriptor::CPPTYPE_STRING: + *val_.string_value_.get_mutable() = other.val_.string_value_.get(); + break; + case FieldDescriptor::CPPTYPE_INT64: + val_.int64_value_ = other.val_.int64_value_; + break; + case FieldDescriptor::CPPTYPE_INT32: + val_.int32_value_ = other.val_.int32_value_; + break; + case FieldDescriptor::CPPTYPE_UINT64: + val_.uint64_value_ = other.val_.uint64_value_; + break; + case FieldDescriptor::CPPTYPE_UINT32: + val_.uint32_value_ = other.val_.uint32_value_; + break; + case FieldDescriptor::CPPTYPE_BOOL: + val_.bool_value_ = other.val_.bool_value_; + break; + } + } + + private: + template <typename K, typename V> + friend class internal::TypeDefinedMapFieldBase; + friend class ::PROTOBUF_NAMESPACE_ID::MapIterator; + friend class internal::DynamicMapField; + + union KeyValue { + KeyValue() {} + internal::ExplicitlyConstructed<std::string> string_value_; + int64_t int64_value_; + int32_t int32_value_; + uint64_t uint64_value_; + uint32_t uint32_value_; + bool bool_value_; + } val_; + + void SetType(FieldDescriptor::CppType type) { + if (type_ == type) return; + if (type_ == FieldDescriptor::CPPTYPE_STRING) { + val_.string_value_.Destruct(); + } + type_ = type; + if (type_ == FieldDescriptor::CPPTYPE_STRING) { + val_.string_value_.DefaultConstruct(); + } + } + + // type_ is 0 or a valid FieldDescriptor::CppType. + // Use "CppType()" to indicate zero. + FieldDescriptor::CppType type_; +}; + +} // namespace protobuf +} // namespace google +namespace std { +template <> +struct hash<::PROTOBUF_NAMESPACE_ID::MapKey> { + size_t operator()(const ::PROTOBUF_NAMESPACE_ID::MapKey& map_key) const { + switch (map_key.type()) { + case ::PROTOBUF_NAMESPACE_ID::FieldDescriptor::CPPTYPE_DOUBLE: + case ::PROTOBUF_NAMESPACE_ID::FieldDescriptor::CPPTYPE_FLOAT: + case ::PROTOBUF_NAMESPACE_ID::FieldDescriptor::CPPTYPE_ENUM: + case ::PROTOBUF_NAMESPACE_ID::FieldDescriptor::CPPTYPE_MESSAGE: + GOOGLE_LOG(FATAL) << "Unsupported"; + break; + case ::PROTOBUF_NAMESPACE_ID::FieldDescriptor::CPPTYPE_STRING: + return hash<std::string>()(map_key.GetStringValue()); + case ::PROTOBUF_NAMESPACE_ID::FieldDescriptor::CPPTYPE_INT64: { + auto value = map_key.GetInt64Value(); + return hash<decltype(value)>()(value); + } + case ::PROTOBUF_NAMESPACE_ID::FieldDescriptor::CPPTYPE_INT32: { + auto value = map_key.GetInt32Value(); + return hash<decltype(value)>()(map_key.GetInt32Value()); + } + case ::PROTOBUF_NAMESPACE_ID::FieldDescriptor::CPPTYPE_UINT64: { + auto value = map_key.GetUInt64Value(); + return hash<decltype(value)>()(map_key.GetUInt64Value()); + } + case ::PROTOBUF_NAMESPACE_ID::FieldDescriptor::CPPTYPE_UINT32: { + auto value = map_key.GetUInt32Value(); + return hash<decltype(value)>()(map_key.GetUInt32Value()); + } + case ::PROTOBUF_NAMESPACE_ID::FieldDescriptor::CPPTYPE_BOOL: { + return hash<bool>()(map_key.GetBoolValue()); + } + } + GOOGLE_LOG(FATAL) << "Can't get here."; + return 0; + } + bool operator()(const ::PROTOBUF_NAMESPACE_ID::MapKey& map_key1, + const ::PROTOBUF_NAMESPACE_ID::MapKey& map_key2) const { + return map_key1 < map_key2; + } +}; +} // namespace std + +namespace google { +namespace protobuf { +namespace internal { + +class ContendedMapCleanTest; +class GeneratedMessageReflection; +class MapFieldAccessor; + +// This class provides access to map field using reflection, which is the same +// as those provided for RepeatedPtrField<Message>. It is used for internal +// reflection implementation only. Users should never use this directly. +class PROTOBUF_EXPORT MapFieldBase { + public: + MapFieldBase() + : arena_(nullptr), repeated_field_(nullptr), state_(STATE_MODIFIED_MAP) {} + + // This constructor is for constant initialized global instances. + // It uses a linker initialized mutex, so it is not compatible with regular + // runtime instances. + // Except in MSVC, where we can't have a constinit mutex. + // NOLINTNEXTLINE(google-explicit-constructor) + constexpr MapFieldBase(ConstantInitialized) + : arena_(nullptr), + repeated_field_(nullptr), + mutex_(GOOGLE_PROTOBUF_LINKER_INITIALIZED), + state_(STATE_MODIFIED_MAP) {} + explicit MapFieldBase(Arena* arena) + : arena_(arena), repeated_field_(nullptr), state_(STATE_MODIFIED_MAP) {} + + protected: + ~MapFieldBase() { // "protected" stops users from deleting a `MapFieldBase *` + GOOGLE_DCHECK(repeated_field_ == nullptr); + } + void Destruct(); + + public: + // Returns reference to internal repeated field. Data written using + // Map's api prior to calling this function is guarantted to be + // included in repeated field. + const RepeatedPtrFieldBase& GetRepeatedField() const; + + // Like above. Returns mutable pointer to the internal repeated field. + RepeatedPtrFieldBase* MutableRepeatedField(); + + // Pure virtual map APIs for Map Reflection. + virtual bool ContainsMapKey(const MapKey& map_key) const = 0; + virtual bool InsertOrLookupMapValue(const MapKey& map_key, + MapValueRef* val) = 0; + virtual bool LookupMapValue(const MapKey& map_key, + MapValueConstRef* val) const = 0; + bool LookupMapValue(const MapKey&, MapValueRef*) const = delete; + + // Returns whether changes to the map are reflected in the repeated field. + bool IsRepeatedFieldValid() const; + // Insures operations after won't get executed before calling this. + bool IsMapValid() const; + virtual bool DeleteMapValue(const MapKey& map_key) = 0; + virtual bool EqualIterator(const MapIterator& a, + const MapIterator& b) const = 0; + virtual void MapBegin(MapIterator* map_iter) const = 0; + virtual void MapEnd(MapIterator* map_iter) const = 0; + virtual void MergeFrom(const MapFieldBase& other) = 0; + virtual void Swap(MapFieldBase* other); + virtual void UnsafeShallowSwap(MapFieldBase* other); + // Sync Map with repeated field and returns the size of map. + virtual int size() const = 0; + virtual void Clear() = 0; + + // Returns the number of bytes used by the repeated field, excluding + // sizeof(*this) + size_t SpaceUsedExcludingSelfLong() const; + + int SpaceUsedExcludingSelf() const { + return internal::ToIntSize(SpaceUsedExcludingSelfLong()); + } + + protected: + // Gets the size of space used by map field. + virtual size_t SpaceUsedExcludingSelfNoLock() const; + + // Synchronizes the content in Map to RepeatedPtrField if there is any change + // to Map after last synchronization. + void SyncRepeatedFieldWithMap() const; + virtual void SyncRepeatedFieldWithMapNoLock() const; + + // Synchronizes the content in RepeatedPtrField to Map if there is any change + // to RepeatedPtrField after last synchronization. + void SyncMapWithRepeatedField() const; + virtual void SyncMapWithRepeatedFieldNoLock() const {} + + // Tells MapFieldBase that there is new change to Map. + void SetMapDirty(); + + // Tells MapFieldBase that there is new change to RepeatedPtrField. + void SetRepeatedDirty(); + + // Provides derived class the access to repeated field. + void* MutableRepeatedPtrField() const; + + void InternalSwap(MapFieldBase* other); + + // Support thread sanitizer (tsan) by making const / mutable races + // more apparent. If one thread calls MutableAccess() while another + // thread calls either ConstAccess() or MutableAccess(), on the same + // MapFieldBase-derived object, and there is no synchronization going + // on between them, tsan will alert. +#if defined(__SANITIZE_THREAD__) || defined(THREAD_SANITIZER) + void ConstAccess() const { GOOGLE_CHECK_EQ(seq1_, seq2_); } + void MutableAccess() { + if (seq1_ & 1) { + seq2_ = ++seq1_; + } else { + seq1_ = ++seq2_; + } + } + unsigned int seq1_ = 0, seq2_ = 0; +#else + void ConstAccess() const {} + void MutableAccess() {} +#endif + enum State { + STATE_MODIFIED_MAP = 0, // map has newly added data that has not been + // synchronized to repeated field + STATE_MODIFIED_REPEATED = 1, // repeated field has newly added data that + // has not been synchronized to map + CLEAN = 2, // data in map and repeated field are same + }; + + Arena* arena_; + mutable RepeatedPtrField<Message>* repeated_field_; + + mutable internal::WrappedMutex + mutex_; // The thread to synchronize map and repeated field + // needs to get lock first; + mutable std::atomic<State> state_; + + private: + friend class ContendedMapCleanTest; + friend class GeneratedMessageReflection; + friend class MapFieldAccessor; + friend class ::PROTOBUF_NAMESPACE_ID::Reflection; + friend class ::PROTOBUF_NAMESPACE_ID::DynamicMessage; + + // Virtual helper methods for MapIterator. MapIterator doesn't have the + // type helper for key and value. Call these help methods to deal with + // different types. Real helper methods are implemented in + // TypeDefinedMapFieldBase. + friend class ::PROTOBUF_NAMESPACE_ID::MapIterator; + // Allocate map<...>::iterator for MapIterator. + virtual void InitializeIterator(MapIterator* map_iter) const = 0; + + // DeleteIterator() is called by the destructor of MapIterator only. + // It deletes map<...>::iterator for MapIterator. + virtual void DeleteIterator(MapIterator* map_iter) const = 0; + + // Copy the map<...>::iterator from other_iterator to + // this_iterator. + virtual void CopyIterator(MapIterator* this_iterator, + const MapIterator& other_iterator) const = 0; + + // IncreaseIterator() is called by operator++() of MapIterator only. + // It implements the ++ operator of MapIterator. + virtual void IncreaseIterator(MapIterator* map_iter) const = 0; + + // Swaps state_ with another MapFieldBase + void SwapState(MapFieldBase* other); + + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MapFieldBase); +}; + +// This class provides common Map Reflection implementations for generated +// message and dynamic message. +template <typename Key, typename T> +class TypeDefinedMapFieldBase : public MapFieldBase { + public: + TypeDefinedMapFieldBase() {} + + // This constructor is for constant initialized global instances. + // It uses a linker initialized mutex, so it is not compatible with regular + // runtime instances. + // NOLINTNEXTLINE(google-explicit-constructor) + constexpr TypeDefinedMapFieldBase(ConstantInitialized tag) + : MapFieldBase(tag) {} + explicit TypeDefinedMapFieldBase(Arena* arena) : MapFieldBase(arena) {} + TypeDefinedMapFieldBase(ArenaInitialized, Arena* arena) + : TypeDefinedMapFieldBase(arena) {} + + protected: + ~TypeDefinedMapFieldBase() {} + using MapFieldBase::Destruct; + + public: + void MapBegin(MapIterator* map_iter) const override; + void MapEnd(MapIterator* map_iter) const override; + bool EqualIterator(const MapIterator& a, const MapIterator& b) const override; + + virtual const Map<Key, T>& GetMap() const = 0; + virtual Map<Key, T>* MutableMap() = 0; + + protected: + typename Map<Key, T>::const_iterator& InternalGetIterator( + const MapIterator* map_iter) const; + + private: + void InitializeIterator(MapIterator* map_iter) const override; + void DeleteIterator(MapIterator* map_iter) const override; + void CopyIterator(MapIterator* this_iteratorm, + const MapIterator& that_iterator) const override; + void IncreaseIterator(MapIterator* map_iter) const override; + + virtual void SetMapIteratorValue(MapIterator* map_iter) const = 0; + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(TypeDefinedMapFieldBase); +}; + +// This class provides access to map field using generated api. It is used for +// internal generated message implementation only. Users should never use this +// directly. +template <typename Derived, typename Key, typename T, + WireFormatLite::FieldType kKeyFieldType, + WireFormatLite::FieldType kValueFieldType> +class MapField : public TypeDefinedMapFieldBase<Key, T> { + // Provide utilities to parse/serialize key/value. Provide utilities to + // manipulate internal stored type. + typedef MapTypeHandler<kKeyFieldType, Key> KeyTypeHandler; + typedef MapTypeHandler<kValueFieldType, T> ValueTypeHandler; + + // Define message type for internal repeated field. + typedef Derived EntryType; + + // Define abbreviation for parent MapFieldLite + typedef MapFieldLite<Derived, Key, T, kKeyFieldType, kValueFieldType> + MapFieldLiteType; + + // Enum needs to be handled differently from other types because it has + // different exposed type in Map's api and repeated field's api. For + // details see the comment in the implementation of + // SyncMapWithRepeatedFieldNoLock. + static constexpr bool kIsValueEnum = ValueTypeHandler::kIsEnum; + typedef typename MapIf<kIsValueEnum, T, const T&>::type CastValueType; + + public: + typedef Map<Key, T> MapType; + + MapField() : impl_() {} + virtual ~MapField() {} // Destruct() must already have been called! + void Destruct() { + impl_.Destruct(); + TypeDefinedMapFieldBase<Key, T>::Destruct(); + } + + // This constructor is for constant initialized global instances. + // It uses a linker initialized mutex, so it is not compatible with regular + // runtime instances. + // NOLINTNEXTLINE(google-explicit-constructor) + constexpr MapField(ConstantInitialized tag) + : TypeDefinedMapFieldBase<Key, T>(tag), impl_() {} + explicit MapField(Arena* arena) + : TypeDefinedMapFieldBase<Key, T>(arena), impl_(arena) {} + MapField(ArenaInitialized, Arena* arena) : MapField(arena) {} + + // Implement MapFieldBase + bool ContainsMapKey(const MapKey& map_key) const override; + bool InsertOrLookupMapValue(const MapKey& map_key, MapValueRef* val) override; + bool LookupMapValue(const MapKey& map_key, + MapValueConstRef* val) const override; + bool LookupMapValue(const MapKey&, MapValueRef*) const = delete; + bool DeleteMapValue(const MapKey& map_key) override; + + const Map<Key, T>& GetMap() const override { + MapFieldBase::SyncMapWithRepeatedField(); + return impl_.GetMap(); + } + + Map<Key, T>* MutableMap() override { + MapFieldBase::SyncMapWithRepeatedField(); + Map<Key, T>* result = impl_.MutableMap(); + MapFieldBase::SetMapDirty(); + return result; + } + + int size() const override; + void Clear() override; + void MergeFrom(const MapFieldBase& other) override; + void Swap(MapFieldBase* other) override; + void UnsafeShallowSwap(MapFieldBase* other) override; + void InternalSwap(MapField* other); + + // Used in the implementation of parsing. Caller should take the ownership iff + // arena_ is nullptr. + EntryType* NewEntry() const { return impl_.NewEntry(); } + + const char* _InternalParse(const char* ptr, ParseContext* ctx) { + return impl_._InternalParse(ptr, ctx); + } + template <typename UnknownType> + const char* ParseWithEnumValidation(const char* ptr, ParseContext* ctx, + bool (*is_valid)(int), uint32_t field_num, + InternalMetadata* metadata) { + return impl_.template ParseWithEnumValidation<UnknownType>( + ptr, ctx, is_valid, field_num, metadata); + } + + private: + MapFieldLiteType impl_; + + typedef void InternalArenaConstructable_; + typedef void DestructorSkippable_; + + // Implements MapFieldBase + void SyncRepeatedFieldWithMapNoLock() const override; + void SyncMapWithRepeatedFieldNoLock() const override; + size_t SpaceUsedExcludingSelfNoLock() const override; + + void SetMapIteratorValue(MapIterator* map_iter) const override; + + friend class ::PROTOBUF_NAMESPACE_ID::Arena; + friend class MapFieldStateTest; // For testing, it needs raw access to impl_ + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MapField); +}; + +template <typename Derived, typename Key, typename T, + WireFormatLite::FieldType key_wire_type, + WireFormatLite::FieldType value_wire_type> +bool AllAreInitialized( + const MapField<Derived, Key, T, key_wire_type, value_wire_type>& field) { + const auto& t = field.GetMap(); + for (typename Map<Key, T>::const_iterator it = t.begin(); it != t.end(); + ++it) { + if (!it->second.IsInitialized()) return false; + } + return true; +} + +template <typename T, typename Key, typename Value, + WireFormatLite::FieldType kKeyFieldType, + WireFormatLite::FieldType kValueFieldType> +struct MapEntryToMapField< + MapEntry<T, Key, Value, kKeyFieldType, kValueFieldType>> { + typedef MapField<T, Key, Value, kKeyFieldType, kValueFieldType> MapFieldType; +}; + +class PROTOBUF_EXPORT DynamicMapField + : public TypeDefinedMapFieldBase<MapKey, MapValueRef> { + public: + explicit DynamicMapField(const Message* default_entry); + DynamicMapField(const Message* default_entry, Arena* arena); + virtual ~DynamicMapField(); + + // Implement MapFieldBase + bool ContainsMapKey(const MapKey& map_key) const override; + bool InsertOrLookupMapValue(const MapKey& map_key, MapValueRef* val) override; + bool LookupMapValue(const MapKey& map_key, + MapValueConstRef* val) const override; + bool LookupMapValue(const MapKey&, MapValueRef*) const = delete; + bool DeleteMapValue(const MapKey& map_key) override; + void MergeFrom(const MapFieldBase& other) override; + void Swap(MapFieldBase* other) override; + void UnsafeShallowSwap(MapFieldBase* other) override { Swap(other); } + + const Map<MapKey, MapValueRef>& GetMap() const override; + Map<MapKey, MapValueRef>* MutableMap() override; + + int size() const override; + void Clear() override; + + private: + Map<MapKey, MapValueRef> map_; + const Message* default_entry_; + + void AllocateMapValue(MapValueRef* map_val); + + // Implements MapFieldBase + void SyncRepeatedFieldWithMapNoLock() const override; + void SyncMapWithRepeatedFieldNoLock() const override; + size_t SpaceUsedExcludingSelfNoLock() const override; + void SetMapIteratorValue(MapIterator* map_iter) const override; + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(DynamicMapField); +}; + +} // namespace internal + +// MapValueConstRef points to a map value. Users can NOT modify +// the map value. +class PROTOBUF_EXPORT MapValueConstRef { + public: + MapValueConstRef() : data_(nullptr), type_() {} + + int64_t GetInt64Value() const { + TYPE_CHECK(FieldDescriptor::CPPTYPE_INT64, + "MapValueConstRef::GetInt64Value"); + return *reinterpret_cast<int64_t*>(data_); + } + uint64_t GetUInt64Value() const { + TYPE_CHECK(FieldDescriptor::CPPTYPE_UINT64, + "MapValueConstRef::GetUInt64Value"); + return *reinterpret_cast<uint64_t*>(data_); + } + int32_t GetInt32Value() const { + TYPE_CHECK(FieldDescriptor::CPPTYPE_INT32, + "MapValueConstRef::GetInt32Value"); + return *reinterpret_cast<int32_t*>(data_); + } + uint32_t GetUInt32Value() const { + TYPE_CHECK(FieldDescriptor::CPPTYPE_UINT32, + "MapValueConstRef::GetUInt32Value"); + return *reinterpret_cast<uint32_t*>(data_); + } + bool GetBoolValue() const { + TYPE_CHECK(FieldDescriptor::CPPTYPE_BOOL, "MapValueConstRef::GetBoolValue"); + return *reinterpret_cast<bool*>(data_); + } + int GetEnumValue() const { + TYPE_CHECK(FieldDescriptor::CPPTYPE_ENUM, "MapValueConstRef::GetEnumValue"); + return *reinterpret_cast<int*>(data_); + } + const std::string& GetStringValue() const { + TYPE_CHECK(FieldDescriptor::CPPTYPE_STRING, + "MapValueConstRef::GetStringValue"); + return *reinterpret_cast<std::string*>(data_); + } + float GetFloatValue() const { + TYPE_CHECK(FieldDescriptor::CPPTYPE_FLOAT, + "MapValueConstRef::GetFloatValue"); + return *reinterpret_cast<float*>(data_); + } + double GetDoubleValue() const { + TYPE_CHECK(FieldDescriptor::CPPTYPE_DOUBLE, + "MapValueConstRef::GetDoubleValue"); + return *reinterpret_cast<double*>(data_); + } + + const Message& GetMessageValue() const { + TYPE_CHECK(FieldDescriptor::CPPTYPE_MESSAGE, + "MapValueConstRef::GetMessageValue"); + return *reinterpret_cast<Message*>(data_); + } + + protected: + // data_ point to a map value. MapValueConstRef does not + // own this value. + void* data_; + // type_ is 0 or a valid FieldDescriptor::CppType. + // Use "CppType()" to indicate zero. + FieldDescriptor::CppType type_; + + FieldDescriptor::CppType type() const { + if (type_ == FieldDescriptor::CppType() || data_ == nullptr) { + GOOGLE_LOG(FATAL) + << "Protocol Buffer map usage error:\n" + << "MapValueConstRef::type MapValueConstRef is not initialized."; + } + return type_; + } + + private: + template <typename Derived, typename K, typename V, + internal::WireFormatLite::FieldType key_wire_type, + internal::WireFormatLite::FieldType value_wire_type> + friend class internal::MapField; + template <typename K, typename V> + friend class internal::TypeDefinedMapFieldBase; + friend class ::PROTOBUF_NAMESPACE_ID::MapIterator; + friend class Reflection; + friend class internal::DynamicMapField; + + void SetType(FieldDescriptor::CppType type) { type_ = type; } + void SetValue(const void* val) { data_ = const_cast<void*>(val); } + void CopyFrom(const MapValueConstRef& other) { + type_ = other.type_; + data_ = other.data_; + } +}; + +// MapValueRef points to a map value. Users are able to modify +// the map value. +class PROTOBUF_EXPORT MapValueRef final : public MapValueConstRef { + public: + MapValueRef() {} + + void SetInt64Value(int64_t value) { + TYPE_CHECK(FieldDescriptor::CPPTYPE_INT64, "MapValueRef::SetInt64Value"); + *reinterpret_cast<int64_t*>(data_) = value; + } + void SetUInt64Value(uint64_t value) { + TYPE_CHECK(FieldDescriptor::CPPTYPE_UINT64, "MapValueRef::SetUInt64Value"); + *reinterpret_cast<uint64_t*>(data_) = value; + } + void SetInt32Value(int32_t value) { + TYPE_CHECK(FieldDescriptor::CPPTYPE_INT32, "MapValueRef::SetInt32Value"); + *reinterpret_cast<int32_t*>(data_) = value; + } + void SetUInt32Value(uint32_t value) { + TYPE_CHECK(FieldDescriptor::CPPTYPE_UINT32, "MapValueRef::SetUInt32Value"); + *reinterpret_cast<uint32_t*>(data_) = value; + } + void SetBoolValue(bool value) { + TYPE_CHECK(FieldDescriptor::CPPTYPE_BOOL, "MapValueRef::SetBoolValue"); + *reinterpret_cast<bool*>(data_) = value; + } + // TODO(jieluo) - Checks that enum is member. + void SetEnumValue(int value) { + TYPE_CHECK(FieldDescriptor::CPPTYPE_ENUM, "MapValueRef::SetEnumValue"); + *reinterpret_cast<int*>(data_) = value; + } + void SetStringValue(const std::string& value) { + TYPE_CHECK(FieldDescriptor::CPPTYPE_STRING, "MapValueRef::SetStringValue"); + *reinterpret_cast<std::string*>(data_) = value; + } + void SetFloatValue(float value) { + TYPE_CHECK(FieldDescriptor::CPPTYPE_FLOAT, "MapValueRef::SetFloatValue"); + *reinterpret_cast<float*>(data_) = value; + } + void SetDoubleValue(double value) { + TYPE_CHECK(FieldDescriptor::CPPTYPE_DOUBLE, "MapValueRef::SetDoubleValue"); + *reinterpret_cast<double*>(data_) = value; + } + + Message* MutableMessageValue() { + TYPE_CHECK(FieldDescriptor::CPPTYPE_MESSAGE, + "MapValueRef::MutableMessageValue"); + return reinterpret_cast<Message*>(data_); + } + + private: + friend class internal::DynamicMapField; + + // Only used in DynamicMapField + void DeleteData() { + switch (type_) { +#define HANDLE_TYPE(CPPTYPE, TYPE) \ + case FieldDescriptor::CPPTYPE_##CPPTYPE: { \ + delete reinterpret_cast<TYPE*>(data_); \ + break; \ + } + HANDLE_TYPE(INT32, int32_t); + HANDLE_TYPE(INT64, int64_t); + HANDLE_TYPE(UINT32, uint32_t); + HANDLE_TYPE(UINT64, uint64_t); + HANDLE_TYPE(DOUBLE, double); + HANDLE_TYPE(FLOAT, float); + HANDLE_TYPE(BOOL, bool); + HANDLE_TYPE(STRING, std::string); + HANDLE_TYPE(ENUM, int32_t); + HANDLE_TYPE(MESSAGE, Message); +#undef HANDLE_TYPE + } + } +}; + +#undef TYPE_CHECK + +class PROTOBUF_EXPORT MapIterator { + public: + MapIterator(Message* message, const FieldDescriptor* field) { + const Reflection* reflection = message->GetReflection(); + map_ = reflection->MutableMapData(message, field); + key_.SetType(field->message_type()->map_key()->cpp_type()); + value_.SetType(field->message_type()->map_value()->cpp_type()); + map_->InitializeIterator(this); + } + MapIterator(const MapIterator& other) { + map_ = other.map_; + map_->InitializeIterator(this); + map_->CopyIterator(this, other); + } + ~MapIterator() { map_->DeleteIterator(this); } + MapIterator& operator=(const MapIterator& other) { + map_ = other.map_; + map_->CopyIterator(this, other); + return *this; + } + friend bool operator==(const MapIterator& a, const MapIterator& b) { + return a.map_->EqualIterator(a, b); + } + friend bool operator!=(const MapIterator& a, const MapIterator& b) { + return !a.map_->EqualIterator(a, b); + } + MapIterator& operator++() { + map_->IncreaseIterator(this); + return *this; + } + MapIterator operator++(int) { + // iter_ is copied from Map<...>::iterator, no need to + // copy from its self again. Use the same implementation + // with operator++() + map_->IncreaseIterator(this); + return *this; + } + const MapKey& GetKey() { return key_; } + const MapValueRef& GetValueRef() { return value_; } + MapValueRef* MutableValueRef() { + map_->SetMapDirty(); + return &value_; + } + + private: + template <typename Key, typename T> + friend class internal::TypeDefinedMapFieldBase; + friend class internal::DynamicMapField; + template <typename Derived, typename Key, typename T, + internal::WireFormatLite::FieldType kKeyFieldType, + internal::WireFormatLite::FieldType kValueFieldType> + friend class internal::MapField; + + // reinterpret_cast from heap-allocated Map<...>::iterator*. MapIterator owns + // the iterator. It is allocated by MapField<...>::InitializeIterator() called + // in constructor and deleted by MapField<...>::DeleteIterator() called in + // destructor. + void* iter_; + // Point to a MapField to call helper methods implemented in MapField. + // MapIterator does not own this object. + internal::MapFieldBase* map_; + MapKey key_; + MapValueRef value_; +}; + +} // namespace protobuf +} // namespace google + +#ifdef _MSC_VER +#pragma warning(pop) // restore warning C4265 +#endif // _MSC_VER + +#include <google/protobuf/port_undef.inc> + +#endif // GOOGLE_PROTOBUF_MAP_FIELD_H__ diff --git a/toolkit/components/protobuf/src/google/protobuf/map_field_inl.h b/toolkit/components/protobuf/src/google/protobuf/map_field_inl.h new file mode 100644 index 0000000000..7c4c2323c4 --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/map_field_inl.h @@ -0,0 +1,375 @@ +// 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. + +#ifndef GOOGLE_PROTOBUF_MAP_FIELD_INL_H__ +#define GOOGLE_PROTOBUF_MAP_FIELD_INL_H__ + +#include <memory> + +#include <google/protobuf/stubs/casts.h> +#include <google/protobuf/map.h> +#include <google/protobuf/map_field.h> +#include <google/protobuf/map_type_handler.h> + +#ifdef SWIG +#error "You cannot SWIG proto headers" +#endif + +namespace google { +namespace protobuf { +namespace internal { +// UnwrapMapKey template +template <typename T> +T UnwrapMapKey(const MapKey& map_key); +template <> +inline int32_t UnwrapMapKey<int32_t>(const MapKey& map_key) { + return map_key.GetInt32Value(); +} +template <> +inline uint32_t UnwrapMapKey<uint32_t>(const MapKey& map_key) { + return map_key.GetUInt32Value(); +} +template <> +inline int64_t UnwrapMapKey<int64_t>(const MapKey& map_key) { + return map_key.GetInt64Value(); +} +template <> +inline uint64_t UnwrapMapKey<uint64_t>(const MapKey& map_key) { + return map_key.GetUInt64Value(); +} +template <> +inline bool UnwrapMapKey<bool>(const MapKey& map_key) { + return map_key.GetBoolValue(); +} +template <> +inline std::string UnwrapMapKey<std::string>(const MapKey& map_key) { + return map_key.GetStringValue(); +} + +// SetMapKey template +template <typename T> +inline void SetMapKey(MapKey* map_key, const T& value); +template <> +inline void SetMapKey<int32_t>(MapKey* map_key, const int32_t& value) { + map_key->SetInt32Value(value); +} +template <> +inline void SetMapKey<uint32_t>(MapKey* map_key, const uint32_t& value) { + map_key->SetUInt32Value(value); +} +template <> +inline void SetMapKey<int64_t>(MapKey* map_key, const int64_t& value) { + map_key->SetInt64Value(value); +} +template <> +inline void SetMapKey<uint64_t>(MapKey* map_key, const uint64_t& value) { + map_key->SetUInt64Value(value); +} +template <> +inline void SetMapKey<bool>(MapKey* map_key, const bool& value) { + map_key->SetBoolValue(value); +} +template <> +inline void SetMapKey<std::string>(MapKey* map_key, const std::string& value) { + map_key->SetStringValue(value); +} + +// ------------------------TypeDefinedMapFieldBase--------------- +template <typename Key, typename T> +typename Map<Key, T>::const_iterator& +TypeDefinedMapFieldBase<Key, T>::InternalGetIterator( + const MapIterator* map_iter) const { + return *reinterpret_cast<typename Map<Key, T>::const_iterator*>( + map_iter->iter_); +} + +template <typename Key, typename T> +void TypeDefinedMapFieldBase<Key, T>::MapBegin(MapIterator* map_iter) const { + InternalGetIterator(map_iter) = GetMap().begin(); + SetMapIteratorValue(map_iter); +} + +template <typename Key, typename T> +void TypeDefinedMapFieldBase<Key, T>::MapEnd(MapIterator* map_iter) const { + InternalGetIterator(map_iter) = GetMap().end(); +} + +template <typename Key, typename T> +bool TypeDefinedMapFieldBase<Key, T>::EqualIterator( + const MapIterator& a, const MapIterator& b) const { + return InternalGetIterator(&a) == InternalGetIterator(&b); +} + +template <typename Key, typename T> +void TypeDefinedMapFieldBase<Key, T>::IncreaseIterator( + MapIterator* map_iter) const { + ++InternalGetIterator(map_iter); + SetMapIteratorValue(map_iter); +} + +template <typename Key, typename T> +void TypeDefinedMapFieldBase<Key, T>::InitializeIterator( + MapIterator* map_iter) const { + map_iter->iter_ = new typename Map<Key, T>::const_iterator; + GOOGLE_CHECK(map_iter->iter_ != nullptr); +} + +template <typename Key, typename T> +void TypeDefinedMapFieldBase<Key, T>::DeleteIterator( + MapIterator* map_iter) const { + delete reinterpret_cast<typename Map<Key, T>::const_iterator*>( + map_iter->iter_); +} + +template <typename Key, typename T> +void TypeDefinedMapFieldBase<Key, T>::CopyIterator( + MapIterator* this_iter, const MapIterator& that_iter) const { + InternalGetIterator(this_iter) = InternalGetIterator(&that_iter); + this_iter->key_.SetType(that_iter.key_.type()); + // MapValueRef::type() fails when containing data is null. However, if + // this_iter points to MapEnd, data can be null. + this_iter->value_.SetType( + static_cast<FieldDescriptor::CppType>(that_iter.value_.type_)); + SetMapIteratorValue(this_iter); +} + +// ---------------------------------------------------------------------- + +template <typename Derived, typename Key, typename T, + WireFormatLite::FieldType kKeyFieldType, + WireFormatLite::FieldType kValueFieldType> +int MapField<Derived, Key, T, kKeyFieldType, kValueFieldType>::size() const { + MapFieldBase::SyncMapWithRepeatedField(); + return static_cast<int>(impl_.GetMap().size()); +} + +template <typename Derived, typename Key, typename T, + WireFormatLite::FieldType kKeyFieldType, + WireFormatLite::FieldType kValueFieldType> +void MapField<Derived, Key, T, kKeyFieldType, kValueFieldType>::Clear() { + if (this->MapFieldBase::repeated_field_ != nullptr) { + RepeatedPtrField<EntryType>* repeated_field = + reinterpret_cast<RepeatedPtrField<EntryType>*>( + this->MapFieldBase::repeated_field_); + repeated_field->Clear(); + } + + impl_.MutableMap()->clear(); + // Data in map and repeated field are both empty, but we can't set status + // CLEAN. Because clear is a generated API, we cannot invalidate previous + // reference to map. + MapFieldBase::SetMapDirty(); +} + +template <typename Derived, typename Key, typename T, + WireFormatLite::FieldType kKeyFieldType, + WireFormatLite::FieldType kValueFieldType> +void MapField<Derived, Key, T, kKeyFieldType, + kValueFieldType>::SetMapIteratorValue(MapIterator* map_iter) + const { + const Map<Key, T>& map = impl_.GetMap(); + typename Map<Key, T>::const_iterator iter = + TypeDefinedMapFieldBase<Key, T>::InternalGetIterator(map_iter); + if (iter == map.end()) return; + SetMapKey(&map_iter->key_, iter->first); + map_iter->value_.SetValue(&iter->second); +} + +template <typename Derived, typename Key, typename T, + WireFormatLite::FieldType kKeyFieldType, + WireFormatLite::FieldType kValueFieldType> +bool MapField<Derived, Key, T, kKeyFieldType, kValueFieldType>::ContainsMapKey( + const MapKey& map_key) const { + const Map<Key, T>& map = impl_.GetMap(); + const Key& key = UnwrapMapKey<Key>(map_key); + typename Map<Key, T>::const_iterator iter = map.find(key); + return iter != map.end(); +} + +template <typename Derived, typename Key, typename T, + WireFormatLite::FieldType kKeyFieldType, + WireFormatLite::FieldType kValueFieldType> +bool MapField<Derived, Key, T, kKeyFieldType, + kValueFieldType>::InsertOrLookupMapValue(const MapKey& map_key, + MapValueRef* val) { + // Always use mutable map because users may change the map value by + // MapValueRef. + Map<Key, T>* map = MutableMap(); + const Key& key = UnwrapMapKey<Key>(map_key); + typename Map<Key, T>::iterator iter = map->find(key); + if (map->end() == iter) { + val->SetValue(&((*map)[key])); + return true; + } + // Key is already in the map. Make sure (*map)[key] is not called. + // [] may reorder the map and iterators. + val->SetValue(&(iter->second)); + return false; +} + +template <typename Derived, typename Key, typename T, + WireFormatLite::FieldType kKeyFieldType, + WireFormatLite::FieldType kValueFieldType> +bool MapField<Derived, Key, T, kKeyFieldType, kValueFieldType>::LookupMapValue( + const MapKey& map_key, MapValueConstRef* val) const { + const Map<Key, T>& map = GetMap(); + const Key& key = UnwrapMapKey<Key>(map_key); + typename Map<Key, T>::const_iterator iter = map.find(key); + if (map.end() == iter) { + return false; + } + // Key is already in the map. Make sure (*map)[key] is not called. + // [] may reorder the map and iterators. + val->SetValue(&(iter->second)); + return true; +} + +template <typename Derived, typename Key, typename T, + WireFormatLite::FieldType kKeyFieldType, + WireFormatLite::FieldType kValueFieldType> +bool MapField<Derived, Key, T, kKeyFieldType, kValueFieldType>::DeleteMapValue( + const MapKey& map_key) { + const Key& key = UnwrapMapKey<Key>(map_key); + return MutableMap()->erase(key); +} + +template <typename Derived, typename Key, typename T, + WireFormatLite::FieldType kKeyFieldType, + WireFormatLite::FieldType kValueFieldType> +void MapField<Derived, Key, T, kKeyFieldType, kValueFieldType>::MergeFrom( + const MapFieldBase& other) { + MapFieldBase::SyncMapWithRepeatedField(); + const MapField& other_field = static_cast<const MapField&>(other); + other_field.SyncMapWithRepeatedField(); + impl_.MergeFrom(other_field.impl_); + MapFieldBase::SetMapDirty(); +} + +template <typename Derived, typename Key, typename T, + WireFormatLite::FieldType kKeyFieldType, + WireFormatLite::FieldType kValueFieldType> +void MapField<Derived, Key, T, kKeyFieldType, kValueFieldType>::Swap( + MapFieldBase* other) { + MapFieldBase::Swap(other); + MapField* other_field = down_cast<MapField*>(other); + impl_.Swap(&other_field->impl_); +} + +template <typename Derived, typename Key, typename T, + WireFormatLite::FieldType kKeyFieldType, + WireFormatLite::FieldType kValueFieldType> +void MapField<Derived, Key, T, kKeyFieldType, + kValueFieldType>::UnsafeShallowSwap(MapFieldBase* other) { + InternalSwap(down_cast<MapField*>(other)); +} + +template <typename Derived, typename Key, typename T, + WireFormatLite::FieldType kKeyFieldType, + WireFormatLite::FieldType kValueFieldType> +void MapField<Derived, Key, T, kKeyFieldType, kValueFieldType>::InternalSwap( + MapField* other) { + MapFieldBase::InternalSwap(other); + impl_.InternalSwap(&other->impl_); +} + +template <typename Derived, typename Key, typename T, + WireFormatLite::FieldType kKeyFieldType, + WireFormatLite::FieldType kValueFieldType> +void MapField<Derived, Key, T, kKeyFieldType, + kValueFieldType>::SyncRepeatedFieldWithMapNoLock() const { + if (this->MapFieldBase::repeated_field_ == nullptr) { + this->MapFieldBase::repeated_field_ = + Arena::CreateMessage<RepeatedPtrField<Message> >( + this->MapFieldBase::arena_); + } + const Map<Key, T>& map = impl_.GetMap(); + RepeatedPtrField<EntryType>* repeated_field = + reinterpret_cast<RepeatedPtrField<EntryType>*>( + this->MapFieldBase::repeated_field_); + + repeated_field->Clear(); + + // The only way we can get at this point is through reflection and the + // only way we can get the reflection object is by having called GetReflection + // on the encompassing field. So that type must have existed and hence we + // know that this MapEntry default_type has also already been constructed. + // So it's safe to just call internal_default_instance(). + const Message* default_entry = Derived::internal_default_instance(); + for (typename Map<Key, T>::const_iterator it = map.begin(); it != map.end(); + ++it) { + EntryType* new_entry = + down_cast<EntryType*>(default_entry->New(this->MapFieldBase::arena_)); + repeated_field->AddAllocated(new_entry); + (*new_entry->mutable_key()) = it->first; + (*new_entry->mutable_value()) = it->second; + } +} + +template <typename Derived, typename Key, typename T, + WireFormatLite::FieldType kKeyFieldType, + WireFormatLite::FieldType kValueFieldType> +void MapField<Derived, Key, T, kKeyFieldType, + kValueFieldType>::SyncMapWithRepeatedFieldNoLock() const { + Map<Key, T>* map = const_cast<MapField*>(this)->impl_.MutableMap(); + RepeatedPtrField<EntryType>* repeated_field = + reinterpret_cast<RepeatedPtrField<EntryType>*>( + this->MapFieldBase::repeated_field_); + GOOGLE_CHECK(this->MapFieldBase::repeated_field_ != nullptr); + map->clear(); + for (typename RepeatedPtrField<EntryType>::iterator it = + repeated_field->begin(); + it != repeated_field->end(); ++it) { + // Cast is needed because Map's api and internal storage is different when + // value is enum. For enum, we cannot cast an int to enum. Thus, we have to + // copy value. For other types, they have same exposed api type and internal + // stored type. We should not introduce value copy for them. We achieve this + // by casting to value for enum while casting to reference for other types. + (*map)[it->key()] = static_cast<CastValueType>(it->value()); + } +} + +template <typename Derived, typename Key, typename T, + WireFormatLite::FieldType kKeyFieldType, + WireFormatLite::FieldType kValueFieldType> +size_t MapField<Derived, Key, T, kKeyFieldType, + kValueFieldType>::SpaceUsedExcludingSelfNoLock() const { + size_t size = 0; + if (this->MapFieldBase::repeated_field_ != nullptr) { + size += this->MapFieldBase::repeated_field_->SpaceUsedExcludingSelfLong(); + } + size += impl_.GetMap().SpaceUsedExcludingSelfLong(); + + return size; +} +} // namespace internal +} // namespace protobuf +} // namespace google + +#endif // GOOGLE_PROTOBUF_MAP_FIELD_INL_H__ diff --git a/toolkit/components/protobuf/src/google/protobuf/map_field_lite.h b/toolkit/components/protobuf/src/google/protobuf/map_field_lite.h new file mode 100644 index 0000000000..53bf7a0811 --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/map_field_lite.h @@ -0,0 +1,209 @@ +// 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. + +#ifndef GOOGLE_PROTOBUF_MAP_FIELD_LITE_H__ +#define GOOGLE_PROTOBUF_MAP_FIELD_LITE_H__ + +#include <type_traits> + +#include <google/protobuf/io/coded_stream.h> +#include <google/protobuf/port.h> +#include <google/protobuf/map.h> +#include <google/protobuf/map_entry_lite.h> +#include <google/protobuf/parse_context.h> +#include <google/protobuf/wire_format_lite.h> + +// Must be included last. +#include <google/protobuf/port_def.inc> + +#ifdef SWIG +#error "You cannot SWIG proto headers" +#endif + +namespace google { +namespace protobuf { +namespace internal { + +#ifndef NDEBUG +void MapFieldLiteNotDestructed(void* map_field_lite); +#endif + +// This class provides access to map field using generated api. It is used for +// internal generated message implementation only. Users should never use this +// directly. +template <typename Derived, typename Key, typename T, + WireFormatLite::FieldType key_wire_type, + WireFormatLite::FieldType value_wire_type> +class MapFieldLite { + // Define message type for internal repeated field. + typedef Derived EntryType; + + public: + typedef Map<Key, T> MapType; + + constexpr MapFieldLite() : map_() {} + explicit MapFieldLite(Arena* arena) : map_(arena) {} + MapFieldLite(ArenaInitialized, Arena* arena) : MapFieldLite(arena) {} + +#ifdef NDEBUG + void Destruct() { map_.~Map(); } + ~MapFieldLite() {} +#else + void Destruct() { + // We want to destruct the map in such a way that we can verify + // that we've done that, but also be sure that we've deallocated + // everything (as opposed to leaving an allocation behind with no + // data in it, as would happen if a vector was resize'd to zero. + // Map::Swap with an empty map accomplishes that. + decltype(map_) swapped_map(map_.arena()); + map_.InternalSwap(swapped_map); + } + ~MapFieldLite() { + if (map_.arena() == nullptr && !map_.empty()) { + MapFieldLiteNotDestructed(this); + } + } +#endif + // Accessors + const Map<Key, T>& GetMap() const { return map_; } + Map<Key, T>* MutableMap() { return &map_; } + + // Convenient methods for generated message implementation. + int size() const { return static_cast<int>(map_.size()); } + void Clear() { return map_.clear(); } + void MergeFrom(const MapFieldLite& other) { + for (typename Map<Key, T>::const_iterator it = other.map_.begin(); + it != other.map_.end(); ++it) { + map_[it->first] = it->second; + } + } + void Swap(MapFieldLite* other) { map_.swap(other->map_); } + void InternalSwap(MapFieldLite* other) { map_.InternalSwap(other->map_); } + + // Used in the implementation of parsing. Caller should take the ownership iff + // arena_ is nullptr. + EntryType* NewEntry() const { + return Arena::CreateMessage<EntryType>(map_.arena()); + } + + const char* _InternalParse(const char* ptr, ParseContext* ctx) { + typename Derived::template Parser<MapFieldLite, Map<Key, T>> parser(this); + return parser._InternalParse(ptr, ctx); + } + + template <typename UnknownType> + const char* ParseWithEnumValidation(const char* ptr, ParseContext* ctx, + bool (*is_valid)(int), uint32_t field_num, + InternalMetadata* metadata) { + typename Derived::template Parser<MapFieldLite, Map<Key, T>> parser(this); + return parser.template ParseWithEnumValidation<UnknownType>( + ptr, ctx, is_valid, field_num, metadata); + } + + private: + typedef void DestructorSkippable_; + + // map_ is inside an anonymous union so we can explicitly control its + // destruction + union { + Map<Key, T> map_; + }; + + friend class ::PROTOBUF_NAMESPACE_ID::Arena; +}; + +template <typename UnknownType, typename T> +struct EnumParseWrapper { + const char* _InternalParse(const char* ptr, ParseContext* ctx) { + return map_field->template ParseWithEnumValidation<UnknownType>( + ptr, ctx, is_valid, field_num, metadata); + } + T* map_field; + bool (*is_valid)(int); + uint32_t field_num; + InternalMetadata* metadata; +}; + +// Helper function because the typenames of maps are horrendous to print. This +// leverages compiler type deduction, to keep all type data out of the +// generated code +template <typename UnknownType, typename T> +EnumParseWrapper<UnknownType, T> InitEnumParseWrapper( + T* map_field, bool (*is_valid)(int), uint32_t field_num, + InternalMetadata* metadata) { + return EnumParseWrapper<UnknownType, T>{map_field, is_valid, field_num, + metadata}; +} + +// True if IsInitialized() is true for value field in all elements of t. T is +// expected to be message. It's useful to have this helper here to keep the +// protobuf compiler from ever having to emit loops in IsInitialized() methods. +// We want the C++ compiler to inline this or not as it sees fit. +template <typename Derived, typename Key, typename T, + WireFormatLite::FieldType key_wire_type, + WireFormatLite::FieldType value_wire_type> +bool AllAreInitialized(const MapFieldLite<Derived, Key, T, key_wire_type, + value_wire_type>& field) { + const auto& t = field.GetMap(); + for (typename Map<Key, T>::const_iterator it = t.begin(); it != t.end(); + ++it) { + if (!it->second.IsInitialized()) return false; + } + return true; +} + +template <typename MEntry> +struct MapEntryToMapField : MapEntryToMapField<typename MEntry::SuperType> {}; + +template <typename T, typename Key, typename Value, + WireFormatLite::FieldType kKeyFieldType, + WireFormatLite::FieldType kValueFieldType> +struct MapEntryToMapField< + MapEntryLite<T, Key, Value, kKeyFieldType, kValueFieldType>> { + typedef MapFieldLite< + MapEntryLite<T, Key, Value, kKeyFieldType, kValueFieldType>, Key, Value, + kKeyFieldType, kValueFieldType> + MapFieldType; +}; + +#ifndef NDEBUG +inline PROTOBUF_NOINLINE void MapFieldLiteNotDestructed(void* map_field_lite) { + bool proper_destruct = false; + GOOGLE_CHECK(proper_destruct) << map_field_lite; +} +#endif + +} // namespace internal +} // namespace protobuf +} // namespace google + +#include <google/protobuf/port_undef.inc> + +#endif // GOOGLE_PROTOBUF_MAP_FIELD_LITE_H__ diff --git a/toolkit/components/protobuf/src/google/protobuf/map_type_handler.h b/toolkit/components/protobuf/src/google/protobuf/map_type_handler.h new file mode 100644 index 0000000000..c210c63db5 --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/map_type_handler.h @@ -0,0 +1,736 @@ +// 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. + +#ifndef GOOGLE_PROTOBUF_MAP_TYPE_HANDLER_H__ +#define GOOGLE_PROTOBUF_MAP_TYPE_HANDLER_H__ + +#include <google/protobuf/io/coded_stream.h> +#include <google/protobuf/arena.h> +#include <google/protobuf/arenastring.h> +#include <google/protobuf/parse_context.h> +#include <google/protobuf/wire_format_lite.h> + +#ifdef SWIG +#error "You cannot SWIG proto headers" +#endif + +namespace google { +namespace protobuf { +namespace internal { + +// Used for compile time type selection. MapIf::type will be TrueType if Flag is +// true and FalseType otherwise. +template <bool Flag, typename TrueType, typename FalseType> +struct MapIf; + +template <typename TrueType, typename FalseType> +struct MapIf<true, TrueType, FalseType> { + typedef TrueType type; +}; + +template <typename TrueType, typename FalseType> +struct MapIf<false, TrueType, FalseType> { + typedef FalseType type; +}; + +template <typename Type, bool is_arena_constructable> +class MapArenaMessageCreator { + public: + // Use arena to create message if Type is arena constructable. Otherwise, + // create the message on heap. + static inline Type* CreateMessage(Arena* arena); +}; +template <typename Type> +class MapArenaMessageCreator<Type, true> { + public: + static inline Type* CreateMessage(Arena* arena) { + return Arena::CreateMessage<Type>(arena); + } +}; +template <typename Type> +class MapArenaMessageCreator<Type, false> { + public: + static inline Type* CreateMessage(Arena* arena) { + return Arena::Create<Type>(arena); + } +}; + +// Define constants for given wire field type +template <WireFormatLite::FieldType field_type, typename Type> +class MapWireFieldTypeTraits {}; + +#define TYPE_TRAITS(FieldType, CType, WireFormatType, IsMessage, IsEnum) \ + template <typename Type> \ + class MapWireFieldTypeTraits<WireFormatLite::TYPE_##FieldType, Type> { \ + public: \ + static const bool kIsMessage = IsMessage; \ + static const bool kIsEnum = IsEnum; \ + typedef typename MapIf<kIsMessage, Type*, CType>::type TypeOnMemory; \ + typedef typename MapIf<kIsEnum, int, Type>::type MapEntryAccessorType; \ + static const WireFormatLite::WireType kWireType = \ + WireFormatLite::WIRETYPE_##WireFormatType; \ + }; + +TYPE_TRAITS(MESSAGE, Type, LENGTH_DELIMITED, true, false) +TYPE_TRAITS(STRING, ArenaStringPtr, LENGTH_DELIMITED, false, false) +TYPE_TRAITS(BYTES, ArenaStringPtr, LENGTH_DELIMITED, false, false) +TYPE_TRAITS(INT64, int64_t, VARINT, false, false) +TYPE_TRAITS(UINT64, uint64_t, VARINT, false, false) +TYPE_TRAITS(INT32, int32_t, VARINT, false, false) +TYPE_TRAITS(UINT32, uint32_t, VARINT, false, false) +TYPE_TRAITS(SINT64, int64_t, VARINT, false, false) +TYPE_TRAITS(SINT32, int32_t, VARINT, false, false) +TYPE_TRAITS(ENUM, int, VARINT, false, true) +TYPE_TRAITS(DOUBLE, double, FIXED64, false, false) +TYPE_TRAITS(FLOAT, float, FIXED32, false, false) +TYPE_TRAITS(FIXED64, uint64_t, FIXED64, false, false) +TYPE_TRAITS(FIXED32, uint32_t, FIXED32, false, false) +TYPE_TRAITS(SFIXED64, int64_t, FIXED64, false, false) +TYPE_TRAITS(SFIXED32, int32_t, FIXED32, false, false) +TYPE_TRAITS(BOOL, bool, VARINT, false, false) + +#undef TYPE_TRAITS + +template <WireFormatLite::FieldType field_type, typename Type> +class MapTypeHandler {}; + +template <typename Type> +class MapTypeHandler<WireFormatLite::TYPE_MESSAGE, Type> { + public: + // Enum type cannot be used for MapTypeHandler::Read. Define a type which will + // replace Enum with int. + typedef typename MapWireFieldTypeTraits<WireFormatLite::TYPE_MESSAGE, + Type>::MapEntryAccessorType + MapEntryAccessorType; + // Internal stored type in MapEntryLite for given wire field type. + typedef typename MapWireFieldTypeTraits<WireFormatLite::TYPE_MESSAGE, + Type>::TypeOnMemory TypeOnMemory; + // Corresponding wire type for field type. + static constexpr WireFormatLite::WireType kWireType = + MapWireFieldTypeTraits<WireFormatLite::TYPE_MESSAGE, Type>::kWireType; + // Whether wire type is for message. + static constexpr bool kIsMessage = + MapWireFieldTypeTraits<WireFormatLite::TYPE_MESSAGE, Type>::kIsMessage; + // Whether wire type is for enum. + static constexpr bool kIsEnum = + MapWireFieldTypeTraits<WireFormatLite::TYPE_MESSAGE, Type>::kIsEnum; + + // Functions used in parsing and serialization. =================== + static inline size_t ByteSize(const MapEntryAccessorType& value); + static inline int GetCachedSize(const MapEntryAccessorType& value); + static inline bool Read(io::CodedInputStream* input, + MapEntryAccessorType* value); + static inline const char* Read(const char* ptr, ParseContext* ctx, + MapEntryAccessorType* value); + + static inline uint8_t* Write(int field, const MapEntryAccessorType& value, + uint8_t* ptr, io::EpsCopyOutputStream* stream); + + // Functions to manipulate data on memory. ======================== + static inline const Type& GetExternalReference(const Type* value); + static inline void DeleteNoArena(const Type* x); + static inline void Merge(const Type& from, Type** to, Arena* arena); + static inline void Clear(Type** value, Arena* arena); + static constexpr TypeOnMemory Constinit(); + + static inline Type* EnsureMutable(Type** value, Arena* arena); + // SpaceUsedInMapEntry: Return bytes used by value in MapEntry, excluding + // those already calculate in sizeof(MapField). + static inline size_t SpaceUsedInMapEntryLong(const Type* value); + // Return default instance if value is not initialized when calling const + // reference accessor. + static inline const Type& DefaultIfNotInitialized(const Type* value); + // Check if all required fields have values set. + static inline bool IsInitialized(Type* value); +}; + +#define MAP_HANDLER(FieldType) \ + template <typename Type> \ + class MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type> { \ + public: \ + typedef typename MapWireFieldTypeTraits<WireFormatLite::TYPE_##FieldType, \ + Type>::MapEntryAccessorType \ + MapEntryAccessorType; \ + typedef typename MapWireFieldTypeTraits<WireFormatLite::TYPE_##FieldType, \ + Type>::TypeOnMemory TypeOnMemory; \ + static const WireFormatLite::WireType kWireType = \ + MapWireFieldTypeTraits<WireFormatLite::TYPE_##FieldType, \ + Type>::kWireType; \ + static const bool kIsMessage = \ + MapWireFieldTypeTraits<WireFormatLite::TYPE_##FieldType, \ + Type>::kIsMessage; \ + static const bool kIsEnum = \ + MapWireFieldTypeTraits<WireFormatLite::TYPE_##FieldType, \ + Type>::kIsEnum; \ + static inline int ByteSize(const MapEntryAccessorType& value); \ + static inline int GetCachedSize(const MapEntryAccessorType& value); \ + static inline bool Read(io::CodedInputStream* input, \ + MapEntryAccessorType* value); \ + static inline const char* Read(const char* begin, ParseContext* ctx, \ + MapEntryAccessorType* value); \ + static inline uint8_t* Write(int field, const MapEntryAccessorType& value, \ + uint8_t* ptr, \ + io::EpsCopyOutputStream* stream); \ + static inline const MapEntryAccessorType& GetExternalReference( \ + const TypeOnMemory& value); \ + static inline void DeleteNoArena(const TypeOnMemory& x); \ + static inline void Merge(const MapEntryAccessorType& from, \ + TypeOnMemory* to, Arena* arena); \ + static inline void Clear(TypeOnMemory* value, Arena* arena); \ + static inline size_t SpaceUsedInMapEntryLong(const TypeOnMemory& value); \ + static inline const MapEntryAccessorType& DefaultIfNotInitialized( \ + const TypeOnMemory& value); \ + static inline bool IsInitialized(const TypeOnMemory& value); \ + static void DeleteNoArena(TypeOnMemory& value); \ + static constexpr TypeOnMemory Constinit(); \ + static inline MapEntryAccessorType* EnsureMutable(TypeOnMemory* value, \ + Arena* arena); \ + }; +MAP_HANDLER(STRING) +MAP_HANDLER(BYTES) +MAP_HANDLER(INT64) +MAP_HANDLER(UINT64) +MAP_HANDLER(INT32) +MAP_HANDLER(UINT32) +MAP_HANDLER(SINT64) +MAP_HANDLER(SINT32) +MAP_HANDLER(ENUM) +MAP_HANDLER(DOUBLE) +MAP_HANDLER(FLOAT) +MAP_HANDLER(FIXED64) +MAP_HANDLER(FIXED32) +MAP_HANDLER(SFIXED64) +MAP_HANDLER(SFIXED32) +MAP_HANDLER(BOOL) +#undef MAP_HANDLER + +template <typename Type> +inline size_t MapTypeHandler<WireFormatLite::TYPE_MESSAGE, Type>::ByteSize( + const MapEntryAccessorType& value) { + return WireFormatLite::MessageSizeNoVirtual(value); +} + +#define GOOGLE_PROTOBUF_BYTE_SIZE(FieldType, DeclaredType) \ + template <typename Type> \ + inline int MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>::ByteSize( \ + const MapEntryAccessorType& value) { \ + return static_cast<int>(WireFormatLite::DeclaredType##Size(value)); \ + } + +GOOGLE_PROTOBUF_BYTE_SIZE(STRING, String) +GOOGLE_PROTOBUF_BYTE_SIZE(BYTES, Bytes) +GOOGLE_PROTOBUF_BYTE_SIZE(INT64, Int64) +GOOGLE_PROTOBUF_BYTE_SIZE(UINT64, UInt64) +GOOGLE_PROTOBUF_BYTE_SIZE(INT32, Int32) +GOOGLE_PROTOBUF_BYTE_SIZE(UINT32, UInt32) +GOOGLE_PROTOBUF_BYTE_SIZE(SINT64, SInt64) +GOOGLE_PROTOBUF_BYTE_SIZE(SINT32, SInt32) +GOOGLE_PROTOBUF_BYTE_SIZE(ENUM, Enum) + +#undef GOOGLE_PROTOBUF_BYTE_SIZE + +#define FIXED_BYTE_SIZE(FieldType, DeclaredType) \ + template <typename Type> \ + inline int MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>::ByteSize( \ + const MapEntryAccessorType& /* value */) { \ + return WireFormatLite::k##DeclaredType##Size; \ + } + +FIXED_BYTE_SIZE(DOUBLE, Double) +FIXED_BYTE_SIZE(FLOAT, Float) +FIXED_BYTE_SIZE(FIXED64, Fixed64) +FIXED_BYTE_SIZE(FIXED32, Fixed32) +FIXED_BYTE_SIZE(SFIXED64, SFixed64) +FIXED_BYTE_SIZE(SFIXED32, SFixed32) +FIXED_BYTE_SIZE(BOOL, Bool) + +#undef FIXED_BYTE_SIZE + +template <typename Type> +inline int MapTypeHandler<WireFormatLite::TYPE_MESSAGE, Type>::GetCachedSize( + const MapEntryAccessorType& value) { + return static_cast<int>(WireFormatLite::LengthDelimitedSize( + static_cast<size_t>(value.GetCachedSize()))); +} + +#define GET_CACHED_SIZE(FieldType, DeclaredType) \ + template <typename Type> \ + inline int \ + MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>::GetCachedSize( \ + const MapEntryAccessorType& value) { \ + return static_cast<int>(WireFormatLite::DeclaredType##Size(value)); \ + } + +GET_CACHED_SIZE(STRING, String) +GET_CACHED_SIZE(BYTES, Bytes) +GET_CACHED_SIZE(INT64, Int64) +GET_CACHED_SIZE(UINT64, UInt64) +GET_CACHED_SIZE(INT32, Int32) +GET_CACHED_SIZE(UINT32, UInt32) +GET_CACHED_SIZE(SINT64, SInt64) +GET_CACHED_SIZE(SINT32, SInt32) +GET_CACHED_SIZE(ENUM, Enum) + +#undef GET_CACHED_SIZE + +#define GET_FIXED_CACHED_SIZE(FieldType, DeclaredType) \ + template <typename Type> \ + inline int \ + MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>::GetCachedSize( \ + const MapEntryAccessorType& /* value */) { \ + return WireFormatLite::k##DeclaredType##Size; \ + } + +GET_FIXED_CACHED_SIZE(DOUBLE, Double) +GET_FIXED_CACHED_SIZE(FLOAT, Float) +GET_FIXED_CACHED_SIZE(FIXED64, Fixed64) +GET_FIXED_CACHED_SIZE(FIXED32, Fixed32) +GET_FIXED_CACHED_SIZE(SFIXED64, SFixed64) +GET_FIXED_CACHED_SIZE(SFIXED32, SFixed32) +GET_FIXED_CACHED_SIZE(BOOL, Bool) + +#undef GET_FIXED_CACHED_SIZE + +template <typename Type> +inline uint8_t* MapTypeHandler<WireFormatLite::TYPE_MESSAGE, Type>::Write( + int field, const MapEntryAccessorType& value, uint8_t* ptr, + io::EpsCopyOutputStream* stream) { + ptr = stream->EnsureSpace(ptr); + return WireFormatLite::InternalWriteMessage( + field, value, value.GetCachedSize(), ptr, stream); +} + +#define WRITE_METHOD(FieldType, DeclaredType) \ + template <typename Type> \ + inline uint8_t* \ + MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>::Write( \ + int field, const MapEntryAccessorType& value, uint8_t* ptr, \ + io::EpsCopyOutputStream* stream) { \ + ptr = stream->EnsureSpace(ptr); \ + return stream->Write##DeclaredType(field, value, ptr); \ + } + +WRITE_METHOD(STRING, String) +WRITE_METHOD(BYTES, Bytes) + +#undef WRITE_METHOD +#define WRITE_METHOD(FieldType, DeclaredType) \ + template <typename Type> \ + inline uint8_t* \ + MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>::Write( \ + int field, const MapEntryAccessorType& value, uint8_t* ptr, \ + io::EpsCopyOutputStream* stream) { \ + ptr = stream->EnsureSpace(ptr); \ + return WireFormatLite::Write##DeclaredType##ToArray(field, value, ptr); \ + } + +WRITE_METHOD(INT64, Int64) +WRITE_METHOD(UINT64, UInt64) +WRITE_METHOD(INT32, Int32) +WRITE_METHOD(UINT32, UInt32) +WRITE_METHOD(SINT64, SInt64) +WRITE_METHOD(SINT32, SInt32) +WRITE_METHOD(ENUM, Enum) +WRITE_METHOD(DOUBLE, Double) +WRITE_METHOD(FLOAT, Float) +WRITE_METHOD(FIXED64, Fixed64) +WRITE_METHOD(FIXED32, Fixed32) +WRITE_METHOD(SFIXED64, SFixed64) +WRITE_METHOD(SFIXED32, SFixed32) +WRITE_METHOD(BOOL, Bool) + +#undef WRITE_METHOD + +template <typename Type> +inline bool MapTypeHandler<WireFormatLite::TYPE_MESSAGE, Type>::Read( + io::CodedInputStream* input, MapEntryAccessorType* value) { + return WireFormatLite::ReadMessageNoVirtual(input, value); +} + +template <typename Type> +inline bool MapTypeHandler<WireFormatLite::TYPE_STRING, Type>::Read( + io::CodedInputStream* input, MapEntryAccessorType* value) { + return WireFormatLite::ReadString(input, value); +} + +template <typename Type> +inline bool MapTypeHandler<WireFormatLite::TYPE_BYTES, Type>::Read( + io::CodedInputStream* input, MapEntryAccessorType* value) { + return WireFormatLite::ReadBytes(input, value); +} + +template <typename Type> +const char* MapTypeHandler<WireFormatLite::TYPE_MESSAGE, Type>::Read( + const char* ptr, ParseContext* ctx, MapEntryAccessorType* value) { + return ctx->ParseMessage(value, ptr); +} + +template <typename Type> +const char* MapTypeHandler<WireFormatLite::TYPE_STRING, Type>::Read( + const char* ptr, ParseContext* ctx, MapEntryAccessorType* value) { + int size = ReadSize(&ptr); + GOOGLE_PROTOBUF_PARSER_ASSERT(ptr); + return ctx->ReadString(ptr, size, value); +} + +template <typename Type> +const char* MapTypeHandler<WireFormatLite::TYPE_BYTES, Type>::Read( + const char* ptr, ParseContext* ctx, MapEntryAccessorType* value) { + int size = ReadSize(&ptr); + GOOGLE_PROTOBUF_PARSER_ASSERT(ptr); + return ctx->ReadString(ptr, size, value); +} + +inline const char* ReadINT64(const char* ptr, int64_t* value) { + return VarintParse(ptr, reinterpret_cast<uint64_t*>(value)); +} +inline const char* ReadUINT64(const char* ptr, uint64_t* value) { + return VarintParse(ptr, value); +} +inline const char* ReadINT32(const char* ptr, int32_t* value) { + return VarintParse(ptr, reinterpret_cast<uint32_t*>(value)); +} +inline const char* ReadUINT32(const char* ptr, uint32_t* value) { + return VarintParse(ptr, value); +} +inline const char* ReadSINT64(const char* ptr, int64_t* value) { + *value = ReadVarintZigZag64(&ptr); + return ptr; +} +inline const char* ReadSINT32(const char* ptr, int32_t* value) { + *value = ReadVarintZigZag32(&ptr); + return ptr; +} +template <typename E> +inline const char* ReadENUM(const char* ptr, E* value) { + *value = static_cast<E>(ReadVarint32(&ptr)); + return ptr; +} +inline const char* ReadBOOL(const char* ptr, bool* value) { + *value = static_cast<bool>(ReadVarint32(&ptr)); + return ptr; +} + +template <typename F> +inline const char* ReadUnaligned(const char* ptr, F* value) { + *value = UnalignedLoad<F>(ptr); + return ptr + sizeof(F); +} +inline const char* ReadFLOAT(const char* ptr, float* value) { + return ReadUnaligned(ptr, value); +} +inline const char* ReadDOUBLE(const char* ptr, double* value) { + return ReadUnaligned(ptr, value); +} +inline const char* ReadFIXED64(const char* ptr, uint64_t* value) { + return ReadUnaligned(ptr, value); +} +inline const char* ReadFIXED32(const char* ptr, uint32_t* value) { + return ReadUnaligned(ptr, value); +} +inline const char* ReadSFIXED64(const char* ptr, int64_t* value) { + return ReadUnaligned(ptr, value); +} +inline const char* ReadSFIXED32(const char* ptr, int32_t* value) { + return ReadUnaligned(ptr, value); +} + +#define READ_METHOD(FieldType) \ + template <typename Type> \ + inline bool MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>::Read( \ + io::CodedInputStream* input, MapEntryAccessorType* value) { \ + return WireFormatLite::ReadPrimitive<TypeOnMemory, \ + WireFormatLite::TYPE_##FieldType>( \ + input, value); \ + } \ + template <typename Type> \ + const char* MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>::Read( \ + const char* begin, ParseContext* ctx, MapEntryAccessorType* value) { \ + (void)ctx; \ + return Read##FieldType(begin, value); \ + } + +READ_METHOD(INT64) +READ_METHOD(UINT64) +READ_METHOD(INT32) +READ_METHOD(UINT32) +READ_METHOD(SINT64) +READ_METHOD(SINT32) +READ_METHOD(ENUM) +READ_METHOD(DOUBLE) +READ_METHOD(FLOAT) +READ_METHOD(FIXED64) +READ_METHOD(FIXED32) +READ_METHOD(SFIXED64) +READ_METHOD(SFIXED32) +READ_METHOD(BOOL) + +#undef READ_METHOD + +// Definition for message handler + +template <typename Type> +inline const Type& +MapTypeHandler<WireFormatLite::TYPE_MESSAGE, Type>::GetExternalReference( + const Type* value) { + return *value; +} + +template <typename Type> +inline size_t MapTypeHandler<WireFormatLite::TYPE_MESSAGE, + Type>::SpaceUsedInMapEntryLong(const Type* value) { + return value->SpaceUsedLong(); +} + +template <typename Type> +inline void MapTypeHandler<WireFormatLite::TYPE_MESSAGE, Type>::Clear( + Type** value, Arena* /* arena */) { + if (*value != nullptr) (*value)->Clear(); +} +template <typename Type> +inline void MapTypeHandler<WireFormatLite::TYPE_MESSAGE, Type>::Merge( + const Type& from, Type** to, Arena* /* arena */) { + (*to)->MergeFrom(from); +} + +template <typename Type> +void MapTypeHandler<WireFormatLite::TYPE_MESSAGE, Type>::DeleteNoArena( + const Type* ptr) { + delete ptr; +} + +template <typename Type> +constexpr auto MapTypeHandler<WireFormatLite::TYPE_MESSAGE, Type>::Constinit() + -> TypeOnMemory { + return nullptr; +} + +template <typename Type> +inline Type* MapTypeHandler<WireFormatLite::TYPE_MESSAGE, Type>::EnsureMutable( + Type** value, Arena* arena) { + if (*value == nullptr) { + *value = MapArenaMessageCreator< + Type, + Arena::is_arena_constructable<Type>::type::value>::CreateMessage(arena); + } + return *value; +} + +template <typename Type> +inline const Type& +MapTypeHandler<WireFormatLite::TYPE_MESSAGE, Type>::DefaultIfNotInitialized( + const Type* value) { + return value != nullptr ? *value : *Type::internal_default_instance(); +} + +template <typename Type> +inline bool MapTypeHandler<WireFormatLite::TYPE_MESSAGE, Type>::IsInitialized( + Type* value) { + return value ? value->IsInitialized() : false; +} + +// Definition for string/bytes handler + +#define STRING_OR_BYTES_HANDLER_FUNCTIONS(FieldType) \ + template <typename Type> \ + inline const typename MapTypeHandler<WireFormatLite::TYPE_##FieldType, \ + Type>::MapEntryAccessorType& \ + MapTypeHandler<WireFormatLite::TYPE_##FieldType, \ + Type>::GetExternalReference(const TypeOnMemory& value) { \ + return value.Get(); \ + } \ + template <typename Type> \ + inline size_t \ + MapTypeHandler<WireFormatLite::TYPE_##FieldType, \ + Type>::SpaceUsedInMapEntryLong(const TypeOnMemory& value) { \ + return sizeof(value); \ + } \ + template <typename Type> \ + inline void MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>::Clear( \ + TypeOnMemory* value, Arena* /* arena */) { \ + value->ClearToEmpty(); \ + } \ + template <typename Type> \ + inline void MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>::Merge( \ + const MapEntryAccessorType& from, TypeOnMemory* to, Arena* arena) { \ + to->Set(from, arena); \ + } \ + template <typename Type> \ + void MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>::DeleteNoArena( \ + TypeOnMemory& value) { \ + value.Destroy(); \ + } \ + template <typename Type> \ + constexpr auto \ + MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>::Constinit() \ + ->TypeOnMemory { \ + return TypeOnMemory(&internal::fixed_address_empty_string, \ + ConstantInitialized{}); \ + } \ + template <typename Type> \ + inline typename MapTypeHandler<WireFormatLite::TYPE_##FieldType, \ + Type>::MapEntryAccessorType* \ + MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>::EnsureMutable( \ + TypeOnMemory* value, Arena* arena) { \ + return value->Mutable(arena); \ + } \ + template <typename Type> \ + inline const typename MapTypeHandler<WireFormatLite::TYPE_##FieldType, \ + Type>::MapEntryAccessorType& \ + MapTypeHandler<WireFormatLite::TYPE_##FieldType, \ + Type>::DefaultIfNotInitialized(const TypeOnMemory& value) { \ + return value.Get(); \ + } \ + template <typename Type> \ + inline bool \ + MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>::IsInitialized( \ + const TypeOnMemory& /* value */) { \ + return true; \ + } +STRING_OR_BYTES_HANDLER_FUNCTIONS(STRING) +STRING_OR_BYTES_HANDLER_FUNCTIONS(BYTES) +#undef STRING_OR_BYTES_HANDLER_FUNCTIONS + +#define PRIMITIVE_HANDLER_FUNCTIONS(FieldType) \ + template <typename Type> \ + inline const typename MapTypeHandler<WireFormatLite::TYPE_##FieldType, \ + Type>::MapEntryAccessorType& \ + MapTypeHandler<WireFormatLite::TYPE_##FieldType, \ + Type>::GetExternalReference(const TypeOnMemory& value) { \ + return value; \ + } \ + template <typename Type> \ + inline size_t MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>:: \ + SpaceUsedInMapEntryLong(const TypeOnMemory& /* value */) { \ + return 0; \ + } \ + template <typename Type> \ + inline void MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>::Clear( \ + TypeOnMemory* value, Arena* /* arena */) { \ + *value = 0; \ + } \ + template <typename Type> \ + inline void MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>::Merge( \ + const MapEntryAccessorType& from, TypeOnMemory* to, \ + Arena* /* arena */) { \ + *to = from; \ + } \ + template <typename Type> \ + inline void MapTypeHandler<WireFormatLite::TYPE_##FieldType, \ + Type>::DeleteNoArena(TypeOnMemory& /* x */) {} \ + template <typename Type> \ + constexpr auto \ + MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>::Constinit() \ + ->TypeOnMemory { \ + return 0; \ + } \ + template <typename Type> \ + inline typename MapTypeHandler<WireFormatLite::TYPE_##FieldType, \ + Type>::MapEntryAccessorType* \ + MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>::EnsureMutable( \ + TypeOnMemory* value, Arena* /* arena */) { \ + return value; \ + } \ + template <typename Type> \ + inline const typename MapTypeHandler<WireFormatLite::TYPE_##FieldType, \ + Type>::MapEntryAccessorType& \ + MapTypeHandler<WireFormatLite::TYPE_##FieldType, \ + Type>::DefaultIfNotInitialized(const TypeOnMemory& value) { \ + return value; \ + } \ + template <typename Type> \ + inline bool \ + MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>::IsInitialized( \ + const TypeOnMemory& /* value */) { \ + return true; \ + } +PRIMITIVE_HANDLER_FUNCTIONS(INT64) +PRIMITIVE_HANDLER_FUNCTIONS(UINT64) +PRIMITIVE_HANDLER_FUNCTIONS(INT32) +PRIMITIVE_HANDLER_FUNCTIONS(UINT32) +PRIMITIVE_HANDLER_FUNCTIONS(SINT64) +PRIMITIVE_HANDLER_FUNCTIONS(SINT32) +PRIMITIVE_HANDLER_FUNCTIONS(ENUM) +PRIMITIVE_HANDLER_FUNCTIONS(DOUBLE) +PRIMITIVE_HANDLER_FUNCTIONS(FLOAT) +PRIMITIVE_HANDLER_FUNCTIONS(FIXED64) +PRIMITIVE_HANDLER_FUNCTIONS(FIXED32) +PRIMITIVE_HANDLER_FUNCTIONS(SFIXED64) +PRIMITIVE_HANDLER_FUNCTIONS(SFIXED32) +PRIMITIVE_HANDLER_FUNCTIONS(BOOL) +#undef PRIMITIVE_HANDLER_FUNCTIONS + +// Functions for operating on a map entry using type handlers. +// +// Does not contain any representation (this class is not intended to be +// instantiated). +template <typename Key, typename Value, WireFormatLite::FieldType kKeyFieldType, + WireFormatLite::FieldType kValueFieldType> +struct MapEntryFuncs { + typedef MapTypeHandler<kKeyFieldType, Key> KeyTypeHandler; + typedef MapTypeHandler<kValueFieldType, Value> ValueTypeHandler; + enum : int { + kKeyFieldNumber = 1, + kValueFieldNumber = 2 + }; + + static uint8_t* InternalSerialize(int field_number, const Key& key, + const Value& value, uint8_t* ptr, + io::EpsCopyOutputStream* stream) { + ptr = stream->EnsureSpace(ptr); + ptr = WireFormatLite::WriteTagToArray( + field_number, WireFormatLite::WIRETYPE_LENGTH_DELIMITED, ptr); + ptr = io::CodedOutputStream::WriteVarint32ToArray(GetCachedSize(key, value), + ptr); + + ptr = KeyTypeHandler::Write(kKeyFieldNumber, key, ptr, stream); + return ValueTypeHandler::Write(kValueFieldNumber, value, ptr, stream); + } + + static size_t ByteSizeLong(const Key& key, const Value& value) { + // Tags for key and value will both be one byte (field numbers 1 and 2). + size_t inner_length = + 2 + KeyTypeHandler::ByteSize(key) + ValueTypeHandler::ByteSize(value); + return inner_length + io::CodedOutputStream::VarintSize32( + static_cast<uint32_t>(inner_length)); + } + + static int GetCachedSize(const Key& key, const Value& value) { + // Tags for key and value will both be one byte (field numbers 1 and 2). + return 2 + KeyTypeHandler::GetCachedSize(key) + + ValueTypeHandler::GetCachedSize(value); + } +}; + +} // namespace internal +} // namespace protobuf +} // namespace google + +#endif // GOOGLE_PROTOBUF_MAP_TYPE_HANDLER_H__ diff --git a/toolkit/components/protobuf/src/google/protobuf/message.cc b/toolkit/components/protobuf/src/google/protobuf/message.cc new file mode 100644 index 0000000000..6cdc6c8393 --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/message.cc @@ -0,0 +1,404 @@ +// 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. + +// Author: kenton@google.com (Kenton Varda) +// Based on original Protocol Buffers design by +// Sanjay Ghemawat, Jeff Dean, and others. + +#include <google/protobuf/message.h> + +#include <iostream> +#include <stack> +#include <unordered_map> + +#include <google/protobuf/stubs/casts.h> +#include <google/protobuf/stubs/logging.h> +#include <google/protobuf/stubs/common.h> +#include <google/protobuf/io/coded_stream.h> +#include <google/protobuf/io/zero_copy_stream_impl.h> +#include <google/protobuf/stubs/strutil.h> +#include <google/protobuf/descriptor.h> +#include <google/protobuf/descriptor.pb.h> +#include <google/protobuf/generated_message_reflection.h> +#include <google/protobuf/generated_message_util.h> +#include <google/protobuf/map_field.h> +#include <google/protobuf/map_field_inl.h> +#include <google/protobuf/parse_context.h> +#include <google/protobuf/reflection_internal.h> +#include <google/protobuf/reflection_ops.h> +#include <google/protobuf/unknown_field_set.h> +#include <google/protobuf/wire_format.h> +#include <google/protobuf/wire_format_lite.h> +#include <google/protobuf/stubs/map_util.h> +#include <google/protobuf/stubs/stl_util.h> +#include <google/protobuf/stubs/hash.h> + +// Must be included last. +#include <google/protobuf/port_def.inc> + +namespace google { +namespace protobuf { + +namespace internal { + +// TODO(gerbens) make this factorized better. This should not have to hop +// to reflection. Currently uses GeneratedMessageReflection and thus is +// defined in generated_message_reflection.cc +void RegisterFileLevelMetadata(const DescriptorTable* descriptor_table); + +} // namespace internal + +using internal::ReflectionOps; +using internal::WireFormat; +using internal::WireFormatLite; + +void Message::MergeFrom(const Message& from) { + auto* class_to = GetClassData(); + auto* class_from = from.GetClassData(); + auto* merge_to_from = class_to ? class_to->merge_to_from : nullptr; + if (class_to == nullptr || class_to != class_from) { + merge_to_from = [](Message& to, const Message& from) { + ReflectionOps::Merge(from, &to); + }; + } + merge_to_from(*this, from); +} + +void Message::CheckTypeAndMergeFrom(const MessageLite& other) { + MergeFrom(*down_cast<const Message*>(&other)); +} + +void Message::CopyFrom(const Message& from) { + if (&from == this) return; + + auto* class_to = GetClassData(); + auto* class_from = from.GetClassData(); + auto* copy_to_from = class_to ? class_to->copy_to_from : nullptr; + + if (class_to == nullptr || class_to != class_from) { + const Descriptor* descriptor = GetDescriptor(); + GOOGLE_CHECK_EQ(from.GetDescriptor(), descriptor) + << ": Tried to copy from a message with a different type. " + "to: " + << descriptor->full_name() + << ", " + "from: " + << from.GetDescriptor()->full_name(); + copy_to_from = [](Message& to, const Message& from) { + ReflectionOps::Copy(from, &to); + }; + } + copy_to_from(*this, from); +} + +void Message::CopyWithSourceCheck(Message& to, const Message& from) { +#ifndef NDEBUG + FailIfCopyFromDescendant(to, from); +#endif + to.Clear(); + to.GetClassData()->merge_to_from(to, from); +} + +void Message::FailIfCopyFromDescendant(Message& to, const Message& from) { + auto* arena = to.GetArenaForAllocation(); + bool same_message_owned_arena = to.GetOwningArena() == nullptr && + arena != nullptr && + arena == from.GetOwningArena(); + GOOGLE_CHECK(!same_message_owned_arena && !internal::IsDescendant(to, from)) + << "Source of CopyFrom cannot be a descendant of the target."; +} + +std::string Message::GetTypeName() const { + return GetDescriptor()->full_name(); +} + +void Message::Clear() { ReflectionOps::Clear(this); } + +bool Message::IsInitialized() const { + return ReflectionOps::IsInitialized(*this); +} + +void Message::FindInitializationErrors(std::vector<std::string>* errors) const { + return ReflectionOps::FindInitializationErrors(*this, "", errors); +} + +std::string Message::InitializationErrorString() const { + std::vector<std::string> errors; + FindInitializationErrors(&errors); + return Join(errors, ", "); +} + +void Message::CheckInitialized() const { + GOOGLE_CHECK(IsInitialized()) << "Message of type \"" << GetDescriptor()->full_name() + << "\" is missing required fields: " + << InitializationErrorString(); +} + +void Message::DiscardUnknownFields() { + return ReflectionOps::DiscardUnknownFields(this); +} + +const char* Message::_InternalParse(const char* ptr, + internal::ParseContext* ctx) { + return WireFormat::_InternalParse(this, ptr, ctx); +} + +uint8_t* Message::_InternalSerialize(uint8_t* target, + io::EpsCopyOutputStream* stream) const { + return WireFormat::_InternalSerialize(*this, target, stream); +} + +size_t Message::ByteSizeLong() const { + size_t size = WireFormat::ByteSize(*this); + SetCachedSize(internal::ToCachedSize(size)); + return size; +} + +void Message::SetCachedSize(int /* size */) const { + GOOGLE_LOG(FATAL) << "Message class \"" << GetDescriptor()->full_name() + << "\" implements neither SetCachedSize() nor ByteSize(). " + "Must implement one or the other."; +} + +size_t Message::ComputeUnknownFieldsSize( + size_t total_size, internal::CachedSize* cached_size) const { + total_size += WireFormat::ComputeUnknownFieldsSize( + _internal_metadata_.unknown_fields<UnknownFieldSet>( + UnknownFieldSet::default_instance)); + cached_size->Set(internal::ToCachedSize(total_size)); + return total_size; +} + +size_t Message::MaybeComputeUnknownFieldsSize( + size_t total_size, internal::CachedSize* cached_size) const { + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + return ComputeUnknownFieldsSize(total_size, cached_size); + } + cached_size->Set(internal::ToCachedSize(total_size)); + return total_size; +} + +size_t Message::SpaceUsedLong() const { + return GetReflection()->SpaceUsedLong(*this); +} + +uint64_t Message::GetInvariantPerBuild(uint64_t salt) { + return salt; +} + +// ============================================================================= +// MessageFactory + +MessageFactory::~MessageFactory() {} + +namespace { + + +#define HASH_MAP std::unordered_map +#define STR_HASH_FXN hash<::google::protobuf::StringPiece> + + +class GeneratedMessageFactory final : public MessageFactory { + public: + static GeneratedMessageFactory* singleton(); + + void RegisterFile(const google::protobuf::internal::DescriptorTable* table); + void RegisterType(const Descriptor* descriptor, const Message* prototype); + + // implements MessageFactory --------------------------------------- + const Message* GetPrototype(const Descriptor* type) override; + + private: + // Only written at static init time, so does not require locking. + HASH_MAP<StringPiece, const google::protobuf::internal::DescriptorTable*, + STR_HASH_FXN> + file_map_; + + internal::WrappedMutex mutex_; + // Initialized lazily, so requires locking. + std::unordered_map<const Descriptor*, const Message*> type_map_; +}; + +GeneratedMessageFactory* GeneratedMessageFactory::singleton() { + static auto instance = + internal::OnShutdownDelete(new GeneratedMessageFactory); + return instance; +} + +void GeneratedMessageFactory::RegisterFile( + const google::protobuf::internal::DescriptorTable* table) { + if (!InsertIfNotPresent(&file_map_, table->filename, table)) { + GOOGLE_LOG(FATAL) << "File is already registered: " << table->filename; + } +} + +void GeneratedMessageFactory::RegisterType(const Descriptor* descriptor, + const Message* prototype) { + GOOGLE_DCHECK_EQ(descriptor->file()->pool(), DescriptorPool::generated_pool()) + << "Tried to register a non-generated type with the generated " + "type registry."; + + // This should only be called as a result of calling a file registration + // function during GetPrototype(), in which case we already have locked + // the mutex. + mutex_.AssertHeld(); + if (!InsertIfNotPresent(&type_map_, descriptor, prototype)) { + GOOGLE_LOG(DFATAL) << "Type is already registered: " << descriptor->full_name(); + } +} + + +const Message* GeneratedMessageFactory::GetPrototype(const Descriptor* type) { + { + ReaderMutexLock lock(&mutex_); + const Message* result = FindPtrOrNull(type_map_, type); + if (result != nullptr) return result; + } + + // If the type is not in the generated pool, then we can't possibly handle + // it. + if (type->file()->pool() != DescriptorPool::generated_pool()) return nullptr; + + // Apparently the file hasn't been registered yet. Let's do that now. + const internal::DescriptorTable* registration_data = + FindPtrOrNull(file_map_, type->file()->name().c_str()); + if (registration_data == nullptr) { + GOOGLE_LOG(DFATAL) << "File appears to be in generated pool but wasn't " + "registered: " + << type->file()->name(); + return nullptr; + } + + WriterMutexLock lock(&mutex_); + + // Check if another thread preempted us. + const Message* result = FindPtrOrNull(type_map_, type); + if (result == nullptr) { + // Nope. OK, register everything. + internal::RegisterFileLevelMetadata(registration_data); + // Should be here now. + result = FindPtrOrNull(type_map_, type); + } + + if (result == nullptr) { + GOOGLE_LOG(DFATAL) << "Type appears to be in generated pool but wasn't " + << "registered: " << type->full_name(); + } + + return result; +} + +} // namespace + +MessageFactory* MessageFactory::generated_factory() { + return GeneratedMessageFactory::singleton(); +} + +void MessageFactory::InternalRegisterGeneratedFile( + const google::protobuf::internal::DescriptorTable* table) { + GeneratedMessageFactory::singleton()->RegisterFile(table); +} + +void MessageFactory::InternalRegisterGeneratedMessage( + const Descriptor* descriptor, const Message* prototype) { + GeneratedMessageFactory::singleton()->RegisterType(descriptor, prototype); +} + + +namespace { +template <typename T> +T* GetSingleton() { + static T singleton; + return &singleton; +} +} // namespace + +const internal::RepeatedFieldAccessor* Reflection::RepeatedFieldAccessor( + const FieldDescriptor* field) const { + GOOGLE_CHECK(field->is_repeated()); + switch (field->cpp_type()) { +#define HANDLE_PRIMITIVE_TYPE(TYPE, type) \ + case FieldDescriptor::CPPTYPE_##TYPE: \ + return GetSingleton<internal::RepeatedFieldPrimitiveAccessor<type> >(); + HANDLE_PRIMITIVE_TYPE(INT32, int32_t) + HANDLE_PRIMITIVE_TYPE(UINT32, uint32_t) + HANDLE_PRIMITIVE_TYPE(INT64, int64_t) + HANDLE_PRIMITIVE_TYPE(UINT64, uint64_t) + HANDLE_PRIMITIVE_TYPE(FLOAT, float) + HANDLE_PRIMITIVE_TYPE(DOUBLE, double) + HANDLE_PRIMITIVE_TYPE(BOOL, bool) + HANDLE_PRIMITIVE_TYPE(ENUM, int32_t) +#undef HANDLE_PRIMITIVE_TYPE + case FieldDescriptor::CPPTYPE_STRING: + switch (field->options().ctype()) { + default: + case FieldOptions::STRING: + return GetSingleton<internal::RepeatedPtrFieldStringAccessor>(); + } + break; + case FieldDescriptor::CPPTYPE_MESSAGE: + if (field->is_map()) { + return GetSingleton<internal::MapFieldAccessor>(); + } else { + return GetSingleton<internal::RepeatedPtrFieldMessageAccessor>(); + } + } + GOOGLE_LOG(FATAL) << "Should not reach here."; + return nullptr; +} + +namespace internal { +template <> +#if defined(_MSC_VER) && (_MSC_VER >= 1800) +// Note: force noinline to workaround MSVC compiler bug with /Zc:inline, issue +// #240 +PROTOBUF_NOINLINE +#endif + Message* + GenericTypeHandler<Message>::NewFromPrototype(const Message* prototype, + Arena* arena) { + return prototype->New(arena); +} +template <> +#if defined(_MSC_VER) && (_MSC_VER >= 1800) +// Note: force noinline to workaround MSVC compiler bug with /Zc:inline, issue +// #240 +PROTOBUF_NOINLINE +#endif + Arena* + GenericTypeHandler<Message>::GetOwningArena(Message* value) { + return value->GetOwningArena(); +} +} // namespace internal + +} // namespace protobuf +} // namespace google + +#include <google/protobuf/port_undef.inc> diff --git a/toolkit/components/protobuf/src/google/protobuf/message.h b/toolkit/components/protobuf/src/google/protobuf/message.h new file mode 100644 index 0000000000..39ec154c34 --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/message.h @@ -0,0 +1,1497 @@ +// 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. + +// Author: kenton@google.com (Kenton Varda) +// Based on original Protocol Buffers design by +// Sanjay Ghemawat, Jeff Dean, and others. +// +// Defines Message, the abstract interface implemented by non-lite +// protocol message objects. Although it's possible to implement this +// interface manually, most users will use the protocol compiler to +// generate implementations. +// +// Example usage: +// +// Say you have a message defined as: +// +// message Foo { +// optional string text = 1; +// repeated int32 numbers = 2; +// } +// +// Then, if you used the protocol compiler to generate a class from the above +// definition, you could use it like so: +// +// std::string data; // Will store a serialized version of the message. +// +// { +// // Create a message and serialize it. +// Foo foo; +// foo.set_text("Hello World!"); +// foo.add_numbers(1); +// foo.add_numbers(5); +// foo.add_numbers(42); +// +// foo.SerializeToString(&data); +// } +// +// { +// // Parse the serialized message and check that it contains the +// // correct data. +// Foo foo; +// foo.ParseFromString(data); +// +// assert(foo.text() == "Hello World!"); +// assert(foo.numbers_size() == 3); +// assert(foo.numbers(0) == 1); +// assert(foo.numbers(1) == 5); +// assert(foo.numbers(2) == 42); +// } +// +// { +// // Same as the last block, but do it dynamically via the Message +// // reflection interface. +// Message* foo = new Foo; +// const Descriptor* descriptor = foo->GetDescriptor(); +// +// // Get the descriptors for the fields we're interested in and verify +// // their types. +// const FieldDescriptor* text_field = descriptor->FindFieldByName("text"); +// assert(text_field != nullptr); +// assert(text_field->type() == FieldDescriptor::TYPE_STRING); +// assert(text_field->label() == FieldDescriptor::LABEL_OPTIONAL); +// const FieldDescriptor* numbers_field = descriptor-> +// FindFieldByName("numbers"); +// assert(numbers_field != nullptr); +// assert(numbers_field->type() == FieldDescriptor::TYPE_INT32); +// assert(numbers_field->label() == FieldDescriptor::LABEL_REPEATED); +// +// // Parse the message. +// foo->ParseFromString(data); +// +// // Use the reflection interface to examine the contents. +// const Reflection* reflection = foo->GetReflection(); +// assert(reflection->GetString(*foo, text_field) == "Hello World!"); +// assert(reflection->FieldSize(*foo, numbers_field) == 3); +// assert(reflection->GetRepeatedInt32(*foo, numbers_field, 0) == 1); +// assert(reflection->GetRepeatedInt32(*foo, numbers_field, 1) == 5); +// assert(reflection->GetRepeatedInt32(*foo, numbers_field, 2) == 42); +// +// delete foo; +// } + +#ifndef GOOGLE_PROTOBUF_MESSAGE_H__ +#define GOOGLE_PROTOBUF_MESSAGE_H__ + + +#include <iosfwd> +#include <string> +#include <type_traits> +#include <vector> + +#include <google/protobuf/stubs/casts.h> +#include <google/protobuf/stubs/common.h> +#include <google/protobuf/arena.h> +#include <google/protobuf/port.h> +#include <google/protobuf/descriptor.h> +#include <google/protobuf/generated_message_reflection.h> +#include <google/protobuf/generated_message_util.h> +#include <google/protobuf/map.h> // TODO(b/211442718): cleanup +#include <google/protobuf/message_lite.h> + + +// Must be included last. +#include <google/protobuf/port_def.inc> + +#ifdef SWIG +#error "You cannot SWIG proto headers" +#endif + +namespace google { +namespace protobuf { + +// Defined in this file. +class Message; +class Reflection; +class MessageFactory; + +// Defined in other files. +class AssignDescriptorsHelper; +class DynamicMessageFactory; +class GeneratedMessageReflectionTestHelper; +class MapKey; +class MapValueConstRef; +class MapValueRef; +class MapIterator; +class MapReflectionTester; + +namespace internal { +struct DescriptorTable; +class MapFieldBase; +class SwapFieldHelper; +class CachedSize; +} // namespace internal +class UnknownFieldSet; // unknown_field_set.h +namespace io { +class ZeroCopyInputStream; // zero_copy_stream.h +class ZeroCopyOutputStream; // zero_copy_stream.h +class CodedInputStream; // coded_stream.h +class CodedOutputStream; // coded_stream.h +} // namespace io +namespace python { +class MapReflectionFriend; // scalar_map_container.h +class MessageReflectionFriend; +} // namespace python +namespace expr { +class CelMapReflectionFriend; // field_backed_map_impl.cc +} + +namespace internal { +class MapFieldPrinterHelper; // text_format.cc +} +namespace util { +class MessageDifferencer; +} + + +namespace internal { +class ReflectionAccessor; // message.cc +class ReflectionOps; // reflection_ops.h +class MapKeySorter; // wire_format.cc +class WireFormat; // wire_format.h +class MapFieldReflectionTest; // map_test.cc +} // namespace internal + +template <typename T> +class RepeatedField; // repeated_field.h + +template <typename T> +class RepeatedPtrField; // repeated_field.h + +// A container to hold message metadata. +struct Metadata { + const Descriptor* descriptor; + const Reflection* reflection; +}; + +namespace internal { +template <class To> +inline To* GetPointerAtOffset(Message* message, uint32_t offset) { + return reinterpret_cast<To*>(reinterpret_cast<char*>(message) + offset); +} + +template <class To> +const To* GetConstPointerAtOffset(const Message* message, uint32_t offset) { + return reinterpret_cast<const To*>(reinterpret_cast<const char*>(message) + + offset); +} + +template <class To> +const To& GetConstRefAtOffset(const Message& message, uint32_t offset) { + return *GetConstPointerAtOffset<To>(&message, offset); +} + +bool CreateUnknownEnumValues(const FieldDescriptor* field); + +// Returns true if "message" is a descendant of "root". +PROTOBUF_EXPORT bool IsDescendant(Message& root, const Message& message); +} // namespace internal + +// Abstract interface for protocol messages. +// +// See also MessageLite, which contains most every-day operations. Message +// adds descriptors and reflection on top of that. +// +// The methods of this class that are virtual but not pure-virtual have +// default implementations based on reflection. Message classes which are +// optimized for speed will want to override these with faster implementations, +// but classes optimized for code size may be happy with keeping them. See +// the optimize_for option in descriptor.proto. +// +// Users must not derive from this class. Only the protocol compiler and +// the internal library are allowed to create subclasses. +class PROTOBUF_EXPORT Message : public MessageLite { + public: + constexpr Message() {} + + // Basic Operations ------------------------------------------------ + + // Construct a new instance of the same type. Ownership is passed to the + // caller. (This is also defined in MessageLite, but is defined again here + // for return-type covariance.) + Message* New() const { return New(nullptr); } + + // Construct a new instance on the arena. Ownership is passed to the caller + // if arena is a nullptr. + Message* New(Arena* arena) const override = 0; + + // Make this message into a copy of the given message. The given message + // must have the same descriptor, but need not necessarily be the same class. + // By default this is just implemented as "Clear(); MergeFrom(from);". + void CopyFrom(const Message& from); + + // Merge the fields from the given message into this message. Singular + // fields will be overwritten, if specified in from, except for embedded + // messages which will be merged. Repeated fields will be concatenated. + // The given message must be of the same type as this message (i.e. the + // exact same class). + virtual void MergeFrom(const Message& from); + + // Verifies that IsInitialized() returns true. GOOGLE_CHECK-fails otherwise, with + // a nice error message. + void CheckInitialized() const; + + // Slowly build a list of all required fields that are not set. + // This is much, much slower than IsInitialized() as it is implemented + // purely via reflection. Generally, you should not call this unless you + // have already determined that an error exists by calling IsInitialized(). + void FindInitializationErrors(std::vector<std::string>* errors) const; + + // Like FindInitializationErrors, but joins all the strings, delimited by + // commas, and returns them. + std::string InitializationErrorString() const override; + + // Clears all unknown fields from this message and all embedded messages. + // Normally, if unknown tag numbers are encountered when parsing a message, + // the tag and value are stored in the message's UnknownFieldSet and + // then written back out when the message is serialized. This allows servers + // which simply route messages to other servers to pass through messages + // that have new field definitions which they don't yet know about. However, + // this behavior can have security implications. To avoid it, call this + // method after parsing. + // + // See Reflection::GetUnknownFields() for more on unknown fields. + void DiscardUnknownFields(); + + // Computes (an estimate of) the total number of bytes currently used for + // storing the message in memory. The default implementation calls the + // Reflection object's SpaceUsed() method. + // + // SpaceUsed() is noticeably slower than ByteSize(), as it is implemented + // using reflection (rather than the generated code implementation for + // ByteSize()). Like ByteSize(), its CPU time is linear in the number of + // fields defined for the proto. + virtual size_t SpaceUsedLong() const; + + PROTOBUF_DEPRECATED_MSG("Please use SpaceUsedLong() instead") + int SpaceUsed() const { return internal::ToIntSize(SpaceUsedLong()); } + + // Debugging & Testing---------------------------------------------- + + // Generates a human-readable form of this message for debugging purposes. + // Note that the format and content of a debug string is not guaranteed, may + // change without notice, and should not be depended on. Code that does + // anything except display a string to assist in debugging should use + // TextFormat instead. + std::string DebugString() const; + // Like DebugString(), but with less whitespace. + std::string ShortDebugString() const; + // Like DebugString(), but do not escape UTF-8 byte sequences. + std::string Utf8DebugString() const; + // Convenience function useful in GDB. Prints DebugString() to stdout. + void PrintDebugString() const; + + // Reflection-based methods ---------------------------------------- + // These methods are pure-virtual in MessageLite, but Message provides + // reflection-based default implementations. + + std::string GetTypeName() const override; + void Clear() override; + + // Returns whether all required fields have been set. Note that required + // fields no longer exist starting in proto3. + bool IsInitialized() const override; + + void CheckTypeAndMergeFrom(const MessageLite& other) override; + // Reflective parser + const char* _InternalParse(const char* ptr, + internal::ParseContext* ctx) override; + size_t ByteSizeLong() const override; + uint8_t* _InternalSerialize(uint8_t* target, + io::EpsCopyOutputStream* stream) const override; + + private: + // This is called only by the default implementation of ByteSize(), to + // update the cached size. If you override ByteSize(), you do not need + // to override this. If you do not override ByteSize(), you MUST override + // this; the default implementation will crash. + // + // The method is private because subclasses should never call it; only + // override it. Yes, C++ lets you do that. Crazy, huh? + virtual void SetCachedSize(int size) const; + + public: + // Introspection --------------------------------------------------- + + + // Get a non-owning pointer to a Descriptor for this message's type. This + // describes what fields the message contains, the types of those fields, etc. + // This object remains property of the Message. + const Descriptor* GetDescriptor() const { return GetMetadata().descriptor; } + + // Get a non-owning pointer to the Reflection interface for this Message, + // which can be used to read and modify the fields of the Message dynamically + // (in other words, without knowing the message type at compile time). This + // object remains property of the Message. + const Reflection* GetReflection() const { return GetMetadata().reflection; } + + protected: + // Get a struct containing the metadata for the Message, which is used in turn + // to implement GetDescriptor() and GetReflection() above. + virtual Metadata GetMetadata() const = 0; + + struct ClassData { + // Note: The order of arguments (to, then from) is chosen so that the ABI + // of this function is the same as the CopyFrom method. That is, the + // hidden "this" parameter comes first. + void (*copy_to_from)(Message& to, const Message& from_msg); + void (*merge_to_from)(Message& to, const Message& from_msg); + }; + // GetClassData() returns a pointer to a ClassData struct which + // exists in global memory and is unique to each subclass. This uniqueness + // property is used in order to quickly determine whether two messages are + // of the same type. + // TODO(jorg): change to pure virtual + virtual const ClassData* GetClassData() const { return nullptr; } + + // CopyWithSourceCheck calls Clear() and then MergeFrom(), and in debug + // builds, checks that calling Clear() on the destination message doesn't + // alter the source. It assumes the messages are known to be of the same + // type, and thus uses GetClassData(). + static void CopyWithSourceCheck(Message& to, const Message& from); + + // Fail if "from" is a descendant of "to" as such copy is not allowed. + static void FailIfCopyFromDescendant(Message& to, const Message& from); + + inline explicit Message(Arena* arena, bool is_message_owned = false) + : MessageLite(arena, is_message_owned) {} + size_t ComputeUnknownFieldsSize(size_t total_size, + internal::CachedSize* cached_size) const; + size_t MaybeComputeUnknownFieldsSize(size_t total_size, + internal::CachedSize* cached_size) const; + + + protected: + static uint64_t GetInvariantPerBuild(uint64_t salt); + + private: + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Message); +}; + +namespace internal { +// Forward-declare interfaces used to implement RepeatedFieldRef. +// These are protobuf internals that users shouldn't care about. +class RepeatedFieldAccessor; +} // namespace internal + +// Forward-declare RepeatedFieldRef templates. The second type parameter is +// used for SFINAE tricks. Users should ignore it. +template <typename T, typename Enable = void> +class RepeatedFieldRef; + +template <typename T, typename Enable = void> +class MutableRepeatedFieldRef; + +// This interface contains methods that can be used to dynamically access +// and modify the fields of a protocol message. Their semantics are +// similar to the accessors the protocol compiler generates. +// +// To get the Reflection for a given Message, call Message::GetReflection(). +// +// This interface is separate from Message only for efficiency reasons; +// the vast majority of implementations of Message will share the same +// implementation of Reflection (GeneratedMessageReflection, +// defined in generated_message.h), and all Messages of a particular class +// should share the same Reflection object (though you should not rely on +// the latter fact). +// +// There are several ways that these methods can be used incorrectly. For +// example, any of the following conditions will lead to undefined +// results (probably assertion failures): +// - The FieldDescriptor is not a field of this message type. +// - The method called is not appropriate for the field's type. For +// each field type in FieldDescriptor::TYPE_*, there is only one +// Get*() method, one Set*() method, and one Add*() method that is +// valid for that type. It should be obvious which (except maybe +// for TYPE_BYTES, which are represented using strings in C++). +// - A Get*() or Set*() method for singular fields is called on a repeated +// field. +// - GetRepeated*(), SetRepeated*(), or Add*() is called on a non-repeated +// field. +// - The Message object passed to any method is not of the right type for +// this Reflection object (i.e. message.GetReflection() != reflection). +// +// You might wonder why there is not any abstract representation for a field +// of arbitrary type. E.g., why isn't there just a "GetField()" method that +// returns "const Field&", where "Field" is some class with accessors like +// "GetInt32Value()". The problem is that someone would have to deal with +// allocating these Field objects. For generated message classes, having to +// allocate space for an additional object to wrap every field would at least +// double the message's memory footprint, probably worse. Allocating the +// objects on-demand, on the other hand, would be expensive and prone to +// memory leaks. So, instead we ended up with this flat interface. +class PROTOBUF_EXPORT Reflection final { + public: + // Get the UnknownFieldSet for the message. This contains fields which + // were seen when the Message was parsed but were not recognized according + // to the Message's definition. + const UnknownFieldSet& GetUnknownFields(const Message& message) const; + // Get a mutable pointer to the UnknownFieldSet for the message. This + // contains fields which were seen when the Message was parsed but were not + // recognized according to the Message's definition. + UnknownFieldSet* MutableUnknownFields(Message* message) const; + + // Estimate the amount of memory used by the message object. + size_t SpaceUsedLong(const Message& message) const; + + PROTOBUF_DEPRECATED_MSG("Please use SpaceUsedLong() instead") + int SpaceUsed(const Message& message) const { + return internal::ToIntSize(SpaceUsedLong(message)); + } + + // Check if the given non-repeated field is set. + bool HasField(const Message& message, const FieldDescriptor* field) const; + + // Get the number of elements of a repeated field. + int FieldSize(const Message& message, const FieldDescriptor* field) const; + + // Clear the value of a field, so that HasField() returns false or + // FieldSize() returns zero. + void ClearField(Message* message, const FieldDescriptor* field) const; + + // Check if the oneof is set. Returns true if any field in oneof + // is set, false otherwise. + bool HasOneof(const Message& message, + const OneofDescriptor* oneof_descriptor) const; + + void ClearOneof(Message* message, + const OneofDescriptor* oneof_descriptor) const; + + // Returns the field descriptor if the oneof is set. nullptr otherwise. + const FieldDescriptor* GetOneofFieldDescriptor( + const Message& message, const OneofDescriptor* oneof_descriptor) const; + + // Removes the last element of a repeated field. + // We don't provide a way to remove any element other than the last + // because it invites inefficient use, such as O(n^2) filtering loops + // that should have been O(n). If you want to remove an element other + // than the last, the best way to do it is to re-arrange the elements + // (using Swap()) so that the one you want removed is at the end, then + // call RemoveLast(). + void RemoveLast(Message* message, const FieldDescriptor* field) const; + // Removes the last element of a repeated message field, and returns the + // pointer to the caller. Caller takes ownership of the returned pointer. + PROTOBUF_NODISCARD Message* ReleaseLast(Message* message, + const FieldDescriptor* field) const; + + // Similar to ReleaseLast() without internal safety and ownershp checks. This + // method should only be used when the objects are on the same arena or paired + // with a call to `UnsafeArenaAddAllocatedMessage`. + Message* UnsafeArenaReleaseLast(Message* message, + const FieldDescriptor* field) const; + + // Swap the complete contents of two messages. + void Swap(Message* message1, Message* message2) const; + + // Swap fields listed in fields vector of two messages. + void SwapFields(Message* message1, Message* message2, + const std::vector<const FieldDescriptor*>& fields) const; + + // Swap two elements of a repeated field. + void SwapElements(Message* message, const FieldDescriptor* field, int index1, + int index2) const; + + // Swap without internal safety and ownership checks. This method should only + // be used when the objects are on the same arena. + void UnsafeArenaSwap(Message* lhs, Message* rhs) const; + + // SwapFields without internal safety and ownership checks. This method should + // only be used when the objects are on the same arena. + void UnsafeArenaSwapFields( + Message* lhs, Message* rhs, + const std::vector<const FieldDescriptor*>& fields) const; + + // List all fields of the message which are currently set, except for unknown + // fields, but including extension known to the parser (i.e. compiled in). + // Singular fields will only be listed if HasField(field) would return true + // and repeated fields will only be listed if FieldSize(field) would return + // non-zero. Fields (both normal fields and extension fields) will be listed + // ordered by field number. + // Use Reflection::GetUnknownFields() or message.unknown_fields() to also get + // access to fields/extensions unknown to the parser. + void ListFields(const Message& message, + std::vector<const FieldDescriptor*>* output) const; + + // Singular field getters ------------------------------------------ + // These get the value of a non-repeated field. They return the default + // value for fields that aren't set. + + int32_t GetInt32(const Message& message, const FieldDescriptor* field) const; + int64_t GetInt64(const Message& message, const FieldDescriptor* field) const; + uint32_t GetUInt32(const Message& message, + const FieldDescriptor* field) const; + uint64_t GetUInt64(const Message& message, + const FieldDescriptor* field) const; + float GetFloat(const Message& message, const FieldDescriptor* field) const; + double GetDouble(const Message& message, const FieldDescriptor* field) const; + bool GetBool(const Message& message, const FieldDescriptor* field) const; + std::string GetString(const Message& message, + const FieldDescriptor* field) const; + const EnumValueDescriptor* GetEnum(const Message& message, + const FieldDescriptor* field) const; + + // GetEnumValue() returns an enum field's value as an integer rather than + // an EnumValueDescriptor*. If the integer value does not correspond to a + // known value descriptor, a new value descriptor is created. (Such a value + // will only be present when the new unknown-enum-value semantics are enabled + // for a message.) + int GetEnumValue(const Message& message, const FieldDescriptor* field) const; + + // See MutableMessage() for the meaning of the "factory" parameter. + const Message& GetMessage(const Message& message, + const FieldDescriptor* field, + MessageFactory* factory = nullptr) const; + + // Get a string value without copying, if possible. + // + // GetString() necessarily returns a copy of the string. This can be + // inefficient when the std::string is already stored in a std::string object + // in the underlying message. GetStringReference() will return a reference to + // the underlying std::string in this case. Otherwise, it will copy the + // string into *scratch and return that. + // + // Note: It is perfectly reasonable and useful to write code like: + // str = reflection->GetStringReference(message, field, &str); + // This line would ensure that only one copy of the string is made + // regardless of the field's underlying representation. When initializing + // a newly-constructed string, though, it's just as fast and more + // readable to use code like: + // std::string str = reflection->GetString(message, field); + const std::string& GetStringReference(const Message& message, + const FieldDescriptor* field, + std::string* scratch) const; + + + // Singular field mutators ----------------------------------------- + // These mutate the value of a non-repeated field. + + void SetInt32(Message* message, const FieldDescriptor* field, + int32_t value) const; + void SetInt64(Message* message, const FieldDescriptor* field, + int64_t value) const; + void SetUInt32(Message* message, const FieldDescriptor* field, + uint32_t value) const; + void SetUInt64(Message* message, const FieldDescriptor* field, + uint64_t value) const; + void SetFloat(Message* message, const FieldDescriptor* field, + float value) const; + void SetDouble(Message* message, const FieldDescriptor* field, + double value) const; + void SetBool(Message* message, const FieldDescriptor* field, + bool value) const; + void SetString(Message* message, const FieldDescriptor* field, + std::string value) const; + void SetEnum(Message* message, const FieldDescriptor* field, + const EnumValueDescriptor* value) const; + // Set an enum field's value with an integer rather than EnumValueDescriptor. + // For proto3 this is just setting the enum field to the value specified, for + // proto2 it's more complicated. If value is a known enum value the field is + // set as usual. If the value is unknown then it is added to the unknown field + // set. Note this matches the behavior of parsing unknown enum values. + // If multiple calls with unknown values happen than they are all added to the + // unknown field set in order of the calls. + void SetEnumValue(Message* message, const FieldDescriptor* field, + int value) const; + + // Get a mutable pointer to a field with a message type. If a MessageFactory + // is provided, it will be used to construct instances of the sub-message; + // otherwise, the default factory is used. If the field is an extension that + // does not live in the same pool as the containing message's descriptor (e.g. + // it lives in an overlay pool), then a MessageFactory must be provided. + // If you have no idea what that meant, then you probably don't need to worry + // about it (don't provide a MessageFactory). WARNING: If the + // FieldDescriptor is for a compiled-in extension, then + // factory->GetPrototype(field->message_type()) MUST return an instance of + // the compiled-in class for this type, NOT DynamicMessage. + Message* MutableMessage(Message* message, const FieldDescriptor* field, + MessageFactory* factory = nullptr) const; + + // Replaces the message specified by 'field' with the already-allocated object + // sub_message, passing ownership to the message. If the field contained a + // message, that message is deleted. If sub_message is nullptr, the field is + // cleared. + void SetAllocatedMessage(Message* message, Message* sub_message, + const FieldDescriptor* field) const; + + // Similar to `SetAllocatedMessage`, but omits all internal safety and + // ownership checks. This method should only be used when the objects are on + // the same arena or paired with a call to `UnsafeArenaReleaseMessage`. + void UnsafeArenaSetAllocatedMessage(Message* message, Message* sub_message, + const FieldDescriptor* field) const; + + // Releases the message specified by 'field' and returns the pointer, + // ReleaseMessage() will return the message the message object if it exists. + // Otherwise, it may or may not return nullptr. In any case, if the return + // value is non-null, the caller takes ownership of the pointer. + // If the field existed (HasField() is true), then the returned pointer will + // be the same as the pointer returned by MutableMessage(). + // This function has the same effect as ClearField(). + PROTOBUF_NODISCARD Message* ReleaseMessage( + Message* message, const FieldDescriptor* field, + MessageFactory* factory = nullptr) const; + + // Similar to `ReleaseMessage`, but omits all internal safety and ownership + // checks. This method should only be used when the objects are on the same + // arena or paired with a call to `UnsafeArenaSetAllocatedMessage`. + Message* UnsafeArenaReleaseMessage(Message* message, + const FieldDescriptor* field, + MessageFactory* factory = nullptr) const; + + + // Repeated field getters ------------------------------------------ + // These get the value of one element of a repeated field. + + int32_t GetRepeatedInt32(const Message& message, const FieldDescriptor* field, + int index) const; + int64_t GetRepeatedInt64(const Message& message, const FieldDescriptor* field, + int index) const; + uint32_t GetRepeatedUInt32(const Message& message, + const FieldDescriptor* field, int index) const; + uint64_t GetRepeatedUInt64(const Message& message, + const FieldDescriptor* field, int index) const; + float GetRepeatedFloat(const Message& message, const FieldDescriptor* field, + int index) const; + double GetRepeatedDouble(const Message& message, const FieldDescriptor* field, + int index) const; + bool GetRepeatedBool(const Message& message, const FieldDescriptor* field, + int index) const; + std::string GetRepeatedString(const Message& message, + const FieldDescriptor* field, int index) const; + const EnumValueDescriptor* GetRepeatedEnum(const Message& message, + const FieldDescriptor* field, + int index) const; + // GetRepeatedEnumValue() returns an enum field's value as an integer rather + // than an EnumValueDescriptor*. If the integer value does not correspond to a + // known value descriptor, a new value descriptor is created. (Such a value + // will only be present when the new unknown-enum-value semantics are enabled + // for a message.) + int GetRepeatedEnumValue(const Message& message, const FieldDescriptor* field, + int index) const; + const Message& GetRepeatedMessage(const Message& message, + const FieldDescriptor* field, + int index) const; + + // See GetStringReference(), above. + const std::string& GetRepeatedStringReference(const Message& message, + const FieldDescriptor* field, + int index, + std::string* scratch) const; + + + // Repeated field mutators ----------------------------------------- + // These mutate the value of one element of a repeated field. + + void SetRepeatedInt32(Message* message, const FieldDescriptor* field, + int index, int32_t value) const; + void SetRepeatedInt64(Message* message, const FieldDescriptor* field, + int index, int64_t value) const; + void SetRepeatedUInt32(Message* message, const FieldDescriptor* field, + int index, uint32_t value) const; + void SetRepeatedUInt64(Message* message, const FieldDescriptor* field, + int index, uint64_t value) const; + void SetRepeatedFloat(Message* message, const FieldDescriptor* field, + int index, float value) const; + void SetRepeatedDouble(Message* message, const FieldDescriptor* field, + int index, double value) const; + void SetRepeatedBool(Message* message, const FieldDescriptor* field, + int index, bool value) const; + void SetRepeatedString(Message* message, const FieldDescriptor* field, + int index, std::string value) const; + void SetRepeatedEnum(Message* message, const FieldDescriptor* field, + int index, const EnumValueDescriptor* value) const; + // Set an enum field's value with an integer rather than EnumValueDescriptor. + // For proto3 this is just setting the enum field to the value specified, for + // proto2 it's more complicated. If value is a known enum value the field is + // set as usual. If the value is unknown then it is added to the unknown field + // set. Note this matches the behavior of parsing unknown enum values. + // If multiple calls with unknown values happen than they are all added to the + // unknown field set in order of the calls. + void SetRepeatedEnumValue(Message* message, const FieldDescriptor* field, + int index, int value) const; + // Get a mutable pointer to an element of a repeated field with a message + // type. + Message* MutableRepeatedMessage(Message* message, + const FieldDescriptor* field, + int index) const; + + + // Repeated field adders ------------------------------------------- + // These add an element to a repeated field. + + void AddInt32(Message* message, const FieldDescriptor* field, + int32_t value) const; + void AddInt64(Message* message, const FieldDescriptor* field, + int64_t value) const; + void AddUInt32(Message* message, const FieldDescriptor* field, + uint32_t value) const; + void AddUInt64(Message* message, const FieldDescriptor* field, + uint64_t value) const; + void AddFloat(Message* message, const FieldDescriptor* field, + float value) const; + void AddDouble(Message* message, const FieldDescriptor* field, + double value) const; + void AddBool(Message* message, const FieldDescriptor* field, + bool value) const; + void AddString(Message* message, const FieldDescriptor* field, + std::string value) const; + void AddEnum(Message* message, const FieldDescriptor* field, + const EnumValueDescriptor* value) const; + // Add an integer value to a repeated enum field rather than + // EnumValueDescriptor. For proto3 this is just setting the enum field to the + // value specified, for proto2 it's more complicated. If value is a known enum + // value the field is set as usual. If the value is unknown then it is added + // to the unknown field set. Note this matches the behavior of parsing unknown + // enum values. If multiple calls with unknown values happen than they are all + // added to the unknown field set in order of the calls. + void AddEnumValue(Message* message, const FieldDescriptor* field, + int value) const; + // See MutableMessage() for comments on the "factory" parameter. + Message* AddMessage(Message* message, const FieldDescriptor* field, + MessageFactory* factory = nullptr) const; + + // Appends an already-allocated object 'new_entry' to the repeated field + // specified by 'field' passing ownership to the message. + void AddAllocatedMessage(Message* message, const FieldDescriptor* field, + Message* new_entry) const; + + // Similar to AddAllocatedMessage() without internal safety and ownership + // checks. This method should only be used when the objects are on the same + // arena or paired with a call to `UnsafeArenaReleaseLast`. + void UnsafeArenaAddAllocatedMessage(Message* message, + const FieldDescriptor* field, + Message* new_entry) const; + + + // Get a RepeatedFieldRef object that can be used to read the underlying + // repeated field. The type parameter T must be set according to the + // field's cpp type. The following table shows the mapping from cpp type + // to acceptable T. + // + // field->cpp_type() T + // CPPTYPE_INT32 int32_t + // CPPTYPE_UINT32 uint32_t + // CPPTYPE_INT64 int64_t + // CPPTYPE_UINT64 uint64_t + // CPPTYPE_DOUBLE double + // CPPTYPE_FLOAT float + // CPPTYPE_BOOL bool + // CPPTYPE_ENUM generated enum type or int32_t + // CPPTYPE_STRING std::string + // CPPTYPE_MESSAGE generated message type or google::protobuf::Message + // + // A RepeatedFieldRef object can be copied and the resulted object will point + // to the same repeated field in the same message. The object can be used as + // long as the message is not destroyed. + // + // Note that to use this method users need to include the header file + // "reflection.h" (which defines the RepeatedFieldRef class templates). + template <typename T> + RepeatedFieldRef<T> GetRepeatedFieldRef(const Message& message, + const FieldDescriptor* field) const; + + // Like GetRepeatedFieldRef() but return an object that can also be used + // manipulate the underlying repeated field. + template <typename T> + MutableRepeatedFieldRef<T> GetMutableRepeatedFieldRef( + Message* message, const FieldDescriptor* field) const; + + // DEPRECATED. Please use Get(Mutable)RepeatedFieldRef() for repeated field + // access. The following repeated field accessors will be removed in the + // future. + // + // Repeated field accessors ------------------------------------------------- + // The methods above, e.g. GetRepeatedInt32(msg, fd, index), provide singular + // access to the data in a RepeatedField. The methods below provide aggregate + // access by exposing the RepeatedField object itself with the Message. + // Applying these templates to inappropriate types will lead to an undefined + // reference at link time (e.g. GetRepeatedField<***double>), or possibly a + // template matching error at compile time (e.g. GetRepeatedPtrField<File>). + // + // Usage example: my_doubs = refl->GetRepeatedField<double>(msg, fd); + + // DEPRECATED. Please use GetRepeatedFieldRef(). + // + // for T = Cord and all protobuf scalar types except enums. + template <typename T> + PROTOBUF_DEPRECATED_MSG("Please use GetRepeatedFieldRef() instead") + const RepeatedField<T>& GetRepeatedField(const Message& msg, + const FieldDescriptor* d) const { + return GetRepeatedFieldInternal<T>(msg, d); + } + + // DEPRECATED. Please use GetMutableRepeatedFieldRef(). + // + // for T = Cord and all protobuf scalar types except enums. + template <typename T> + PROTOBUF_DEPRECATED_MSG("Please use GetMutableRepeatedFieldRef() instead") + RepeatedField<T>* MutableRepeatedField(Message* msg, + const FieldDescriptor* d) const { + return MutableRepeatedFieldInternal<T>(msg, d); + } + + // DEPRECATED. Please use GetRepeatedFieldRef(). + // + // for T = std::string, google::protobuf::internal::StringPieceField + // google::protobuf::Message & descendants. + template <typename T> + PROTOBUF_DEPRECATED_MSG("Please use GetRepeatedFieldRef() instead") + const RepeatedPtrField<T>& GetRepeatedPtrField( + const Message& msg, const FieldDescriptor* d) const { + return GetRepeatedPtrFieldInternal<T>(msg, d); + } + + // DEPRECATED. Please use GetMutableRepeatedFieldRef(). + // + // for T = std::string, google::protobuf::internal::StringPieceField + // google::protobuf::Message & descendants. + template <typename T> + PROTOBUF_DEPRECATED_MSG("Please use GetMutableRepeatedFieldRef() instead") + RepeatedPtrField<T>* MutableRepeatedPtrField(Message* msg, + const FieldDescriptor* d) const { + return MutableRepeatedPtrFieldInternal<T>(msg, d); + } + + // Extensions ---------------------------------------------------------------- + + // Try to find an extension of this message type by fully-qualified field + // name. Returns nullptr if no extension is known for this name or number. + const FieldDescriptor* FindKnownExtensionByName( + const std::string& name) const; + + // Try to find an extension of this message type by field number. + // Returns nullptr if no extension is known for this name or number. + const FieldDescriptor* FindKnownExtensionByNumber(int number) const; + + // Feature Flags ------------------------------------------------------------- + + // Does this message support storing arbitrary integer values in enum fields? + // If |true|, GetEnumValue/SetEnumValue and associated repeated-field versions + // take arbitrary integer values, and the legacy GetEnum() getter will + // dynamically create an EnumValueDescriptor for any integer value without + // one. If |false|, setting an unknown enum value via the integer-based + // setters results in undefined behavior (in practice, GOOGLE_DCHECK-fails). + // + // Generic code that uses reflection to handle messages with enum fields + // should check this flag before using the integer-based setter, and either + // downgrade to a compatible value or use the UnknownFieldSet if not. For + // example: + // + // int new_value = GetValueFromApplicationLogic(); + // if (reflection->SupportsUnknownEnumValues()) { + // reflection->SetEnumValue(message, field, new_value); + // } else { + // if (field_descriptor->enum_type()-> + // FindValueByNumber(new_value) != nullptr) { + // reflection->SetEnumValue(message, field, new_value); + // } else if (emit_unknown_enum_values) { + // reflection->MutableUnknownFields(message)->AddVarint( + // field->number(), new_value); + // } else { + // // convert value to a compatible/default value. + // new_value = CompatibleDowngrade(new_value); + // reflection->SetEnumValue(message, field, new_value); + // } + // } + bool SupportsUnknownEnumValues() const; + + // Returns the MessageFactory associated with this message. This can be + // useful for determining if a message is a generated message or not, for + // example: + // if (message->GetReflection()->GetMessageFactory() == + // google::protobuf::MessageFactory::generated_factory()) { + // // This is a generated message. + // } + // It can also be used to create more messages of this type, though + // Message::New() is an easier way to accomplish this. + MessageFactory* GetMessageFactory() const; + + private: + template <typename T> + const RepeatedField<T>& GetRepeatedFieldInternal( + const Message& message, const FieldDescriptor* field) const; + template <typename T> + RepeatedField<T>* MutableRepeatedFieldInternal( + Message* message, const FieldDescriptor* field) const; + template <typename T> + const RepeatedPtrField<T>& GetRepeatedPtrFieldInternal( + const Message& message, const FieldDescriptor* field) const; + template <typename T> + RepeatedPtrField<T>* MutableRepeatedPtrFieldInternal( + Message* message, const FieldDescriptor* field) const; + // Obtain a pointer to a Repeated Field Structure and do some type checking: + // on field->cpp_type(), + // on field->field_option().ctype() (if ctype >= 0) + // of field->message_type() (if message_type != nullptr). + // We use 2 routine rather than 4 (const vs mutable) x (scalar vs pointer). + void* MutableRawRepeatedField(Message* message, const FieldDescriptor* field, + FieldDescriptor::CppType, int ctype, + const Descriptor* message_type) const; + + const void* GetRawRepeatedField(const Message& message, + const FieldDescriptor* field, + FieldDescriptor::CppType cpptype, int ctype, + const Descriptor* message_type) const; + + // The following methods are used to implement (Mutable)RepeatedFieldRef. + // A Ref object will store a raw pointer to the repeated field data (obtained + // from RepeatedFieldData()) and a pointer to a Accessor (obtained from + // RepeatedFieldAccessor) which will be used to access the raw data. + + // Returns a raw pointer to the repeated field + // + // "cpp_type" and "message_type" are deduced from the type parameter T passed + // to Get(Mutable)RepeatedFieldRef. If T is a generated message type, + // "message_type" should be set to its descriptor. Otherwise "message_type" + // should be set to nullptr. Implementations of this method should check + // whether "cpp_type"/"message_type" is consistent with the actual type of the + // field. We use 1 routine rather than 2 (const vs mutable) because it is + // protected and it doesn't change the message. + void* RepeatedFieldData(Message* message, const FieldDescriptor* field, + FieldDescriptor::CppType cpp_type, + const Descriptor* message_type) const; + + // The returned pointer should point to a singleton instance which implements + // the RepeatedFieldAccessor interface. + const internal::RepeatedFieldAccessor* RepeatedFieldAccessor( + const FieldDescriptor* field) const; + + // Lists all fields of the message which are currently set, except for unknown + // fields and stripped fields. See ListFields for details. + void ListFieldsOmitStripped( + const Message& message, + std::vector<const FieldDescriptor*>* output) const; + + bool IsMessageStripped(const Descriptor* descriptor) const { + return schema_.IsMessageStripped(descriptor); + } + + friend class TextFormat; + + void ListFieldsMayFailOnStripped( + const Message& message, bool should_fail, + std::vector<const FieldDescriptor*>* output) const; + + // Returns true if the message field is backed by a LazyField. + // + // A message field may be backed by a LazyField without the user annotation + // ([lazy = true]). While the user-annotated LazyField is lazily verified on + // first touch (i.e. failure on access rather than parsing if the LazyField is + // not initialized), the inferred LazyField is eagerly verified to avoid lazy + // parsing error at the cost of lower efficiency. When reflecting a message + // field, use this API instead of checking field->options().lazy(). + bool IsLazyField(const FieldDescriptor* field) const { + return IsLazilyVerifiedLazyField(field) || + IsEagerlyVerifiedLazyField(field); + } + + // Returns true if the field is lazy extension. It is meant to allow python + // reparse lazy field until b/157559327 is fixed. + bool IsLazyExtension(const Message& message, + const FieldDescriptor* field) const; + + bool IsLazilyVerifiedLazyField(const FieldDescriptor* field) const; + bool IsEagerlyVerifiedLazyField(const FieldDescriptor* field) const; + + friend class FastReflectionMessageMutator; + friend bool internal::IsDescendant(Message& root, const Message& message); + + const Descriptor* const descriptor_; + const internal::ReflectionSchema schema_; + const DescriptorPool* const descriptor_pool_; + MessageFactory* const message_factory_; + + // Last non weak field index. This is an optimization when most weak fields + // are at the end of the containing message. If a message proto doesn't + // contain weak fields, then this field equals descriptor_->field_count(). + int last_non_weak_field_index_; + + template <typename T, typename Enable> + friend class RepeatedFieldRef; + template <typename T, typename Enable> + friend class MutableRepeatedFieldRef; + friend class ::PROTOBUF_NAMESPACE_ID::MessageLayoutInspector; + friend class ::PROTOBUF_NAMESPACE_ID::AssignDescriptorsHelper; + friend class DynamicMessageFactory; + friend class GeneratedMessageReflectionTestHelper; + friend class python::MapReflectionFriend; + friend class python::MessageReflectionFriend; + friend class util::MessageDifferencer; +#define GOOGLE_PROTOBUF_HAS_CEL_MAP_REFLECTION_FRIEND + friend class expr::CelMapReflectionFriend; + friend class internal::MapFieldReflectionTest; + friend class internal::MapKeySorter; + friend class internal::WireFormat; + friend class internal::ReflectionOps; + friend class internal::SwapFieldHelper; + // Needed for implementing text format for map. + friend class internal::MapFieldPrinterHelper; + + Reflection(const Descriptor* descriptor, + const internal::ReflectionSchema& schema, + const DescriptorPool* pool, MessageFactory* factory); + + // Special version for specialized implementations of string. We can't + // call MutableRawRepeatedField directly here because we don't have access to + // FieldOptions::* which are defined in descriptor.pb.h. Including that + // file here is not possible because it would cause a circular include cycle. + // We use 1 routine rather than 2 (const vs mutable) because it is private + // and mutable a repeated string field doesn't change the message. + void* MutableRawRepeatedString(Message* message, const FieldDescriptor* field, + bool is_string) const; + + friend class MapReflectionTester; + // Returns true if key is in map. Returns false if key is not in map field. + bool ContainsMapKey(const Message& message, const FieldDescriptor* field, + const MapKey& key) const; + + // If key is in map field: Saves the value pointer to val and returns + // false. If key in not in map field: Insert the key into map, saves + // value pointer to val and returns true. Users are able to modify the + // map value by MapValueRef. + bool InsertOrLookupMapValue(Message* message, const FieldDescriptor* field, + const MapKey& key, MapValueRef* val) const; + + // If key is in map field: Saves the value pointer to val and returns true. + // Returns false if key is not in map field. Users are NOT able to modify + // the value by MapValueConstRef. + bool LookupMapValue(const Message& message, const FieldDescriptor* field, + const MapKey& key, MapValueConstRef* val) const; + bool LookupMapValue(const Message&, const FieldDescriptor*, const MapKey&, + MapValueRef*) const = delete; + + // Delete and returns true if key is in the map field. Returns false + // otherwise. + bool DeleteMapValue(Message* message, const FieldDescriptor* field, + const MapKey& key) const; + + // Returns a MapIterator referring to the first element in the map field. + // If the map field is empty, this function returns the same as + // reflection::MapEnd. Mutation to the field may invalidate the iterator. + MapIterator MapBegin(Message* message, const FieldDescriptor* field) const; + + // Returns a MapIterator referring to the theoretical element that would + // follow the last element in the map field. It does not point to any + // real element. Mutation to the field may invalidate the iterator. + MapIterator MapEnd(Message* message, const FieldDescriptor* field) const; + + // Get the number of <key, value> pair of a map field. The result may be + // different from FieldSize which can have duplicate keys. + int MapSize(const Message& message, const FieldDescriptor* field) const; + + // Help method for MapIterator. + friend class MapIterator; + friend class WireFormatForMapFieldTest; + internal::MapFieldBase* MutableMapData(Message* message, + const FieldDescriptor* field) const; + + const internal::MapFieldBase* GetMapData(const Message& message, + const FieldDescriptor* field) const; + + template <class T> + const T& GetRawNonOneof(const Message& message, + const FieldDescriptor* field) const; + template <class T> + T* MutableRawNonOneof(Message* message, const FieldDescriptor* field) const; + + template <typename Type> + const Type& GetRaw(const Message& message, + const FieldDescriptor* field) const; + template <typename Type> + inline Type* MutableRaw(Message* message, const FieldDescriptor* field) const; + template <typename Type> + const Type& DefaultRaw(const FieldDescriptor* field) const; + + const Message* GetDefaultMessageInstance(const FieldDescriptor* field) const; + + inline const uint32_t* GetHasBits(const Message& message) const; + inline uint32_t* MutableHasBits(Message* message) const; + inline uint32_t GetOneofCase(const Message& message, + const OneofDescriptor* oneof_descriptor) const; + inline uint32_t* MutableOneofCase( + Message* message, const OneofDescriptor* oneof_descriptor) const; + inline bool HasExtensionSet(const Message& /* message */) const { + return schema_.HasExtensionSet(); + } + const internal::ExtensionSet& GetExtensionSet(const Message& message) const; + internal::ExtensionSet* MutableExtensionSet(Message* message) const; + + const internal::InternalMetadata& GetInternalMetadata( + const Message& message) const; + + internal::InternalMetadata* MutableInternalMetadata(Message* message) const; + + inline bool IsInlined(const FieldDescriptor* field) const; + + inline bool HasBit(const Message& message, + const FieldDescriptor* field) const; + inline void SetBit(Message* message, const FieldDescriptor* field) const; + inline void ClearBit(Message* message, const FieldDescriptor* field) const; + inline void SwapBit(Message* message1, Message* message2, + const FieldDescriptor* field) const; + + inline const uint32_t* GetInlinedStringDonatedArray( + const Message& message) const; + inline uint32_t* MutableInlinedStringDonatedArray(Message* message) const; + inline bool IsInlinedStringDonated(const Message& message, + const FieldDescriptor* field) const; + inline void SwapInlinedStringDonated(Message* lhs, Message* rhs, + const FieldDescriptor* field) const; + + // Shallow-swap fields listed in fields vector of two messages. It is the + // caller's responsibility to make sure shallow swap is safe. + void UnsafeShallowSwapFields( + Message* message1, Message* message2, + const std::vector<const FieldDescriptor*>& fields) const; + + // This function only swaps the field. Should swap corresponding has_bit + // before or after using this function. + void SwapField(Message* message1, Message* message2, + const FieldDescriptor* field) const; + + // Unsafe but shallow version of SwapField. + void UnsafeShallowSwapField(Message* message1, Message* message2, + const FieldDescriptor* field) const; + + template <bool unsafe_shallow_swap> + void SwapFieldsImpl(Message* message1, Message* message2, + const std::vector<const FieldDescriptor*>& fields) const; + + template <bool unsafe_shallow_swap> + void SwapOneofField(Message* lhs, Message* rhs, + const OneofDescriptor* oneof_descriptor) const; + + inline bool HasOneofField(const Message& message, + const FieldDescriptor* field) const; + inline void SetOneofCase(Message* message, + const FieldDescriptor* field) const; + inline void ClearOneofField(Message* message, + const FieldDescriptor* field) const; + + template <typename Type> + inline const Type& GetField(const Message& message, + const FieldDescriptor* field) const; + template <typename Type> + inline void SetField(Message* message, const FieldDescriptor* field, + const Type& value) const; + template <typename Type> + inline Type* MutableField(Message* message, + const FieldDescriptor* field) const; + template <typename Type> + inline const Type& GetRepeatedField(const Message& message, + const FieldDescriptor* field, + int index) const; + template <typename Type> + inline const Type& GetRepeatedPtrField(const Message& message, + const FieldDescriptor* field, + int index) const; + template <typename Type> + inline void SetRepeatedField(Message* message, const FieldDescriptor* field, + int index, Type value) const; + template <typename Type> + inline Type* MutableRepeatedField(Message* message, + const FieldDescriptor* field, + int index) const; + template <typename Type> + inline void AddField(Message* message, const FieldDescriptor* field, + const Type& value) const; + template <typename Type> + inline Type* AddField(Message* message, const FieldDescriptor* field) const; + + int GetExtensionNumberOrDie(const Descriptor* type) const; + + // Internal versions of EnumValue API perform no checking. Called after checks + // by public methods. + void SetEnumValueInternal(Message* message, const FieldDescriptor* field, + int value) const; + void SetRepeatedEnumValueInternal(Message* message, + const FieldDescriptor* field, int index, + int value) const; + void AddEnumValueInternal(Message* message, const FieldDescriptor* field, + int value) const; + + friend inline // inline so nobody can call this function. + void + RegisterAllTypesInternal(const Metadata* file_level_metadata, int size); + friend inline const char* ParseLenDelim(int field_number, + const FieldDescriptor* field, + Message* msg, + const Reflection* reflection, + const char* ptr, + internal::ParseContext* ctx); + friend inline const char* ParsePackedField(const FieldDescriptor* field, + Message* msg, + const Reflection* reflection, + const char* ptr, + internal::ParseContext* ctx); + + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Reflection); +}; + +// Abstract interface for a factory for message objects. +class PROTOBUF_EXPORT MessageFactory { + public: + inline MessageFactory() {} + virtual ~MessageFactory(); + + // Given a Descriptor, gets or constructs the default (prototype) Message + // of that type. You can then call that message's New() method to construct + // a mutable message of that type. + // + // Calling this method twice with the same Descriptor returns the same + // object. The returned object remains property of the factory. Also, any + // objects created by calling the prototype's New() method share some data + // with the prototype, so these must be destroyed before the MessageFactory + // is destroyed. + // + // The given descriptor must outlive the returned message, and hence must + // outlive the MessageFactory. + // + // Some implementations do not support all types. GetPrototype() will + // return nullptr if the descriptor passed in is not supported. + // + // This method may or may not be thread-safe depending on the implementation. + // Each implementation should document its own degree thread-safety. + virtual const Message* GetPrototype(const Descriptor* type) = 0; + + // Gets a MessageFactory which supports all generated, compiled-in messages. + // In other words, for any compiled-in type FooMessage, the following is true: + // MessageFactory::generated_factory()->GetPrototype( + // FooMessage::descriptor()) == FooMessage::default_instance() + // This factory supports all types which are found in + // DescriptorPool::generated_pool(). If given a descriptor from any other + // pool, GetPrototype() will return nullptr. (You can also check if a + // descriptor is for a generated message by checking if + // descriptor->file()->pool() == DescriptorPool::generated_pool().) + // + // This factory is 100% thread-safe; calling GetPrototype() does not modify + // any shared data. + // + // This factory is a singleton. The caller must not delete the object. + static MessageFactory* generated_factory(); + + // For internal use only: Registers a .proto file at static initialization + // time, to be placed in generated_factory. The first time GetPrototype() + // is called with a descriptor from this file, |register_messages| will be + // called, with the file name as the parameter. It must call + // InternalRegisterGeneratedMessage() (below) to register each message type + // in the file. This strange mechanism is necessary because descriptors are + // built lazily, so we can't register types by their descriptor until we + // know that the descriptor exists. |filename| must be a permanent string. + static void InternalRegisterGeneratedFile( + const google::protobuf::internal::DescriptorTable* table); + + // For internal use only: Registers a message type. Called only by the + // functions which are registered with InternalRegisterGeneratedFile(), + // above. + static void InternalRegisterGeneratedMessage(const Descriptor* descriptor, + const Message* prototype); + + + private: + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessageFactory); +}; + +#define DECLARE_GET_REPEATED_FIELD(TYPE) \ + template <> \ + PROTOBUF_EXPORT const RepeatedField<TYPE>& \ + Reflection::GetRepeatedFieldInternal<TYPE>( \ + const Message& message, const FieldDescriptor* field) const; \ + \ + template <> \ + PROTOBUF_EXPORT RepeatedField<TYPE>* \ + Reflection::MutableRepeatedFieldInternal<TYPE>( \ + Message * message, const FieldDescriptor* field) const; + +DECLARE_GET_REPEATED_FIELD(int32_t) +DECLARE_GET_REPEATED_FIELD(int64_t) +DECLARE_GET_REPEATED_FIELD(uint32_t) +DECLARE_GET_REPEATED_FIELD(uint64_t) +DECLARE_GET_REPEATED_FIELD(float) +DECLARE_GET_REPEATED_FIELD(double) +DECLARE_GET_REPEATED_FIELD(bool) + +#undef DECLARE_GET_REPEATED_FIELD + +// Tries to downcast this message to a generated message type. Returns nullptr +// if this class is not an instance of T. This works even if RTTI is disabled. +// +// This also has the effect of creating a strong reference to T that will +// prevent the linker from stripping it out at link time. This can be important +// if you are using a DynamicMessageFactory that delegates to the generated +// factory. +template <typename T> +const T* DynamicCastToGenerated(const Message* from) { + // Compile-time assert that T is a generated type that has a + // default_instance() accessor, but avoid actually calling it. + const T& (*get_default_instance)() = &T::default_instance; + (void)get_default_instance; + + // Compile-time assert that T is a subclass of google::protobuf::Message. + const Message* unused = static_cast<T*>(nullptr); + (void)unused; + +#if PROTOBUF_RTTI + return dynamic_cast<const T*>(from); +#else + bool ok = from != nullptr && + T::default_instance().GetReflection() == from->GetReflection(); + return ok ? down_cast<const T*>(from) : nullptr; +#endif +} + +template <typename T> +T* DynamicCastToGenerated(Message* from) { + const Message* message_const = from; + return const_cast<T*>(DynamicCastToGenerated<T>(message_const)); +} + +// Call this function to ensure that this message's reflection is linked into +// the binary: +// +// google::protobuf::LinkMessageReflection<pkg::FooMessage>(); +// +// This will ensure that the following lookup will succeed: +// +// DescriptorPool::generated_pool()->FindMessageTypeByName("pkg.FooMessage"); +// +// As a side-effect, it will also guarantee that anything else from the same +// .proto file will also be available for lookup in the generated pool. +// +// This function does not actually register the message, so it does not need +// to be called before the lookup. However it does need to occur in a function +// that cannot be stripped from the binary (ie. it must be reachable from main). +// +// Best practice is to call this function as close as possible to where the +// reflection is actually needed. This function is very cheap to call, so you +// should not need to worry about its runtime overhead except in the tightest +// of loops (on x86-64 it compiles into two "mov" instructions). +template <typename T> +void LinkMessageReflection() { + internal::StrongReference(T::default_instance); +} + +// ============================================================================= +// Implementation details for {Get,Mutable}RawRepeatedPtrField. We provide +// specializations for <std::string>, <StringPieceField> and <Message> and +// handle everything else with the default template which will match any type +// having a method with signature "static const google::protobuf::Descriptor* +// descriptor()". Such a type presumably is a descendant of google::protobuf::Message. + +template <> +inline const RepeatedPtrField<std::string>& +Reflection::GetRepeatedPtrFieldInternal<std::string>( + const Message& message, const FieldDescriptor* field) const { + return *static_cast<RepeatedPtrField<std::string>*>( + MutableRawRepeatedString(const_cast<Message*>(&message), field, true)); +} + +template <> +inline RepeatedPtrField<std::string>* +Reflection::MutableRepeatedPtrFieldInternal<std::string>( + Message* message, const FieldDescriptor* field) const { + return static_cast<RepeatedPtrField<std::string>*>( + MutableRawRepeatedString(message, field, true)); +} + + +// ----- + +template <> +inline const RepeatedPtrField<Message>& Reflection::GetRepeatedPtrFieldInternal( + const Message& message, const FieldDescriptor* field) const { + return *static_cast<const RepeatedPtrField<Message>*>(GetRawRepeatedField( + message, field, FieldDescriptor::CPPTYPE_MESSAGE, -1, nullptr)); +} + +template <> +inline RepeatedPtrField<Message>* Reflection::MutableRepeatedPtrFieldInternal( + Message* message, const FieldDescriptor* field) const { + return static_cast<RepeatedPtrField<Message>*>(MutableRawRepeatedField( + message, field, FieldDescriptor::CPPTYPE_MESSAGE, -1, nullptr)); +} + +template <typename PB> +inline const RepeatedPtrField<PB>& Reflection::GetRepeatedPtrFieldInternal( + const Message& message, const FieldDescriptor* field) const { + return *static_cast<const RepeatedPtrField<PB>*>( + GetRawRepeatedField(message, field, FieldDescriptor::CPPTYPE_MESSAGE, -1, + PB::default_instance().GetDescriptor())); +} + +template <typename PB> +inline RepeatedPtrField<PB>* Reflection::MutableRepeatedPtrFieldInternal( + Message* message, const FieldDescriptor* field) const { + return static_cast<RepeatedPtrField<PB>*>( + MutableRawRepeatedField(message, field, FieldDescriptor::CPPTYPE_MESSAGE, + -1, PB::default_instance().GetDescriptor())); +} + +template <typename Type> +const Type& Reflection::DefaultRaw(const FieldDescriptor* field) const { + return *reinterpret_cast<const Type*>(schema_.GetFieldDefault(field)); +} + +uint32_t Reflection::GetOneofCase( + const Message& message, const OneofDescriptor* oneof_descriptor) const { + GOOGLE_DCHECK(!oneof_descriptor->is_synthetic()); + return internal::GetConstRefAtOffset<uint32_t>( + message, schema_.GetOneofCaseOffset(oneof_descriptor)); +} + +bool Reflection::HasOneofField(const Message& message, + const FieldDescriptor* field) const { + return (GetOneofCase(message, field->containing_oneof()) == + static_cast<uint32_t>(field->number())); +} + +template <typename Type> +const Type& Reflection::GetRaw(const Message& message, + const FieldDescriptor* field) const { + GOOGLE_DCHECK(!schema_.InRealOneof(field) || HasOneofField(message, field)) + << "Field = " << field->full_name(); + return internal::GetConstRefAtOffset<Type>(message, + schema_.GetFieldOffset(field)); +} +} // namespace protobuf +} // namespace google + +#include <google/protobuf/port_undef.inc> + +#endif // GOOGLE_PROTOBUF_MESSAGE_H__ diff --git a/toolkit/components/protobuf/src/google/protobuf/message_lite.cc b/toolkit/components/protobuf/src/google/protobuf/message_lite.cc new file mode 100644 index 0000000000..a1790b167f --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/message_lite.cc @@ -0,0 +1,603 @@ +// 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. + +// Authors: wink@google.com (Wink Saville), +// kenton@google.com (Kenton Varda) +// Based on original Protocol Buffers design by +// Sanjay Ghemawat, Jeff Dean, and others. + +#include <google/protobuf/message_lite.h> + +#include <climits> +#include <cstdint> +#include <string> +#include <istream> + +#include <google/protobuf/stubs/logging.h> +#include <google/protobuf/stubs/common.h> +#include <google/protobuf/parse_context.h> +#include <google/protobuf/io/coded_stream.h> +#include <google/protobuf/io/zero_copy_stream.h> +#include <google/protobuf/io/zero_copy_stream_impl.h> +#include <google/protobuf/io/zero_copy_stream_impl_lite.h> +#include <google/protobuf/arena.h> +#include <google/protobuf/stubs/strutil.h> +#include <google/protobuf/generated_message_util.h> +#include <google/protobuf/repeated_field.h> +#include <google/protobuf/stubs/stl_util.h> +#include <google/protobuf/stubs/mutex.h> + +// Must be included last. +#include <google/protobuf/port_def.inc> + +namespace google { +namespace protobuf { + +std::string MessageLite::InitializationErrorString() const { + return "(cannot determine missing fields for lite message)"; +} + +std::string MessageLite::DebugString() const { + std::uintptr_t address = reinterpret_cast<std::uintptr_t>(this); + return StrCat("MessageLite at 0x", strings::Hex(address)); +} + +namespace { + +// When serializing, we first compute the byte size, then serialize the message. +// If serialization produces a different number of bytes than expected, we +// call this function, which crashes. The problem could be due to a bug in the +// protobuf implementation but is more likely caused by concurrent modification +// of the message. This function attempts to distinguish between the two and +// provide a useful error message. +void ByteSizeConsistencyError(size_t byte_size_before_serialization, + size_t byte_size_after_serialization, + size_t bytes_produced_by_serialization, + const MessageLite& message) { + GOOGLE_CHECK_EQ(byte_size_before_serialization, byte_size_after_serialization) + << message.GetTypeName() + << " was modified concurrently during serialization."; + GOOGLE_CHECK_EQ(bytes_produced_by_serialization, byte_size_before_serialization) + << "Byte size calculation and serialization were inconsistent. This " + "may indicate a bug in protocol buffers or it may be caused by " + "concurrent modification of " + << message.GetTypeName() << "."; + GOOGLE_LOG(FATAL) << "This shouldn't be called if all the sizes are equal."; +} + +std::string InitializationErrorMessage(const char* action, + const MessageLite& message) { + // Note: We want to avoid depending on strutil in the lite library, otherwise + // we'd use: + // + // return strings::Substitute( + // "Can't $0 message of type \"$1\" because it is missing required " + // "fields: $2", + // action, message.GetTypeName(), + // message.InitializationErrorString()); + + std::string result; + result += "Can't "; + result += action; + result += " message of type \""; + result += message.GetTypeName(); + result += "\" because it is missing required fields: "; + result += message.InitializationErrorString(); + return result; +} + +inline StringPiece as_string_view(const void* data, int size) { + return StringPiece(static_cast<const char*>(data), size); +} + +// Returns true of all required fields are present / have values. +inline bool CheckFieldPresence(const internal::ParseContext& ctx, + const MessageLite& msg, + MessageLite::ParseFlags parse_flags) { + (void)ctx; // Parameter is used by Google-internal code. + if (PROTOBUF_PREDICT_FALSE((parse_flags & MessageLite::kMergePartial) != 0)) { + return true; + } + return msg.IsInitializedWithErrors(); +} + +} // namespace + +void MessageLite::LogInitializationErrorMessage() const { + GOOGLE_LOG(ERROR) << InitializationErrorMessage("parse", *this); +} + +namespace internal { + +template <bool aliasing> +bool MergeFromImpl(StringPiece input, MessageLite* msg, + MessageLite::ParseFlags parse_flags) { + const char* ptr; + internal::ParseContext ctx(io::CodedInputStream::GetDefaultRecursionLimit(), + aliasing, &ptr, input); + ptr = msg->_InternalParse(ptr, &ctx); + // ctx has an explicit limit set (length of string_view). + if (PROTOBUF_PREDICT_TRUE(ptr && ctx.EndedAtLimit())) { + return CheckFieldPresence(ctx, *msg, parse_flags); + } + return false; +} + +template <bool aliasing> +bool MergeFromImpl(io::ZeroCopyInputStream* input, MessageLite* msg, + MessageLite::ParseFlags parse_flags) { + const char* ptr; + internal::ParseContext ctx(io::CodedInputStream::GetDefaultRecursionLimit(), + aliasing, &ptr, input); + ptr = msg->_InternalParse(ptr, &ctx); + // ctx has no explicit limit (hence we end on end of stream) + if (PROTOBUF_PREDICT_TRUE(ptr && ctx.EndedAtEndOfStream())) { + return CheckFieldPresence(ctx, *msg, parse_flags); + } + return false; +} + +template <bool aliasing> +bool MergeFromImpl(BoundedZCIS input, MessageLite* msg, + MessageLite::ParseFlags parse_flags) { + const char* ptr; + internal::ParseContext ctx(io::CodedInputStream::GetDefaultRecursionLimit(), + aliasing, &ptr, input.zcis, input.limit); + ptr = msg->_InternalParse(ptr, &ctx); + if (PROTOBUF_PREDICT_FALSE(!ptr)) return false; + ctx.BackUp(ptr); + if (PROTOBUF_PREDICT_TRUE(ctx.EndedAtLimit())) { + return CheckFieldPresence(ctx, *msg, parse_flags); + } + return false; +} + +template bool MergeFromImpl<false>(StringPiece input, MessageLite* msg, + MessageLite::ParseFlags parse_flags); +template bool MergeFromImpl<true>(StringPiece input, MessageLite* msg, + MessageLite::ParseFlags parse_flags); +template bool MergeFromImpl<false>(io::ZeroCopyInputStream* input, + MessageLite* msg, + MessageLite::ParseFlags parse_flags); +template bool MergeFromImpl<true>(io::ZeroCopyInputStream* input, + MessageLite* msg, + MessageLite::ParseFlags parse_flags); +template bool MergeFromImpl<false>(BoundedZCIS input, MessageLite* msg, + MessageLite::ParseFlags parse_flags); +template bool MergeFromImpl<true>(BoundedZCIS input, MessageLite* msg, + MessageLite::ParseFlags parse_flags); + +} // namespace internal + +class ZeroCopyCodedInputStream : public io::ZeroCopyInputStream { + public: + ZeroCopyCodedInputStream(io::CodedInputStream* cis) : cis_(cis) {} + bool Next(const void** data, int* size) final { + if (!cis_->GetDirectBufferPointer(data, size)) return false; + cis_->Skip(*size); + return true; + } + void BackUp(int count) final { cis_->Advance(-count); } + bool Skip(int count) final { return cis_->Skip(count); } + int64_t ByteCount() const final { return 0; } + + bool aliasing_enabled() { return cis_->aliasing_enabled_; } + + private: + io::CodedInputStream* cis_; +}; + +bool MessageLite::MergeFromImpl(io::CodedInputStream* input, + MessageLite::ParseFlags parse_flags) { + ZeroCopyCodedInputStream zcis(input); + const char* ptr; + internal::ParseContext ctx(input->RecursionBudget(), zcis.aliasing_enabled(), + &ptr, &zcis); + // MergePartialFromCodedStream allows terminating the wireformat by 0 or + // end-group tag. Leaving it up to the caller to verify correct ending by + // calling LastTagWas on input. We need to maintain this behavior. + ctx.TrackCorrectEnding(); + ctx.data().pool = input->GetExtensionPool(); + ctx.data().factory = input->GetExtensionFactory(); + ptr = _InternalParse(ptr, &ctx); + if (PROTOBUF_PREDICT_FALSE(!ptr)) return false; + ctx.BackUp(ptr); + if (!ctx.EndedAtEndOfStream()) { + GOOGLE_DCHECK_NE(ctx.LastTag(), 1); // We can't end on a pushed limit. + if (ctx.IsExceedingLimit(ptr)) return false; + input->SetLastTag(ctx.LastTag()); + } else { + input->SetConsumed(); + } + return CheckFieldPresence(ctx, *this, parse_flags); +} + +bool MessageLite::MergePartialFromCodedStream(io::CodedInputStream* input) { + return MergeFromImpl(input, kMergePartial); +} + +bool MessageLite::MergeFromCodedStream(io::CodedInputStream* input) { + return MergeFromImpl(input, kMerge); +} + +bool MessageLite::ParseFromCodedStream(io::CodedInputStream* input) { + Clear(); + return MergeFromImpl(input, kParse); +} + +bool MessageLite::ParsePartialFromCodedStream(io::CodedInputStream* input) { + Clear(); + return MergeFromImpl(input, kParsePartial); +} + +bool MessageLite::ParseFromZeroCopyStream(io::ZeroCopyInputStream* input) { + return ParseFrom<kParse>(input); +} + +bool MessageLite::ParsePartialFromZeroCopyStream( + io::ZeroCopyInputStream* input) { + return ParseFrom<kParsePartial>(input); +} + +bool MessageLite::ParseFromFileDescriptor(int file_descriptor) { + io::FileInputStream input(file_descriptor); + return ParseFromZeroCopyStream(&input) && input.GetErrno() == 0; +} + +bool MessageLite::ParsePartialFromFileDescriptor(int file_descriptor) { + io::FileInputStream input(file_descriptor); + return ParsePartialFromZeroCopyStream(&input) && input.GetErrno() == 0; +} + +bool MessageLite::ParseFromIstream(std::istream* input) { + io::IstreamInputStream zero_copy_input(input); + return ParseFromZeroCopyStream(&zero_copy_input) && input->eof(); +} + +bool MessageLite::ParsePartialFromIstream(std::istream* input) { + io::IstreamInputStream zero_copy_input(input); + return ParsePartialFromZeroCopyStream(&zero_copy_input) && input->eof(); +} + +bool MessageLite::MergePartialFromBoundedZeroCopyStream( + io::ZeroCopyInputStream* input, int size) { + return ParseFrom<kMergePartial>(internal::BoundedZCIS{input, size}); +} + +bool MessageLite::MergeFromBoundedZeroCopyStream(io::ZeroCopyInputStream* input, + int size) { + return ParseFrom<kMerge>(internal::BoundedZCIS{input, size}); +} + +bool MessageLite::ParseFromBoundedZeroCopyStream(io::ZeroCopyInputStream* input, + int size) { + return ParseFrom<kParse>(internal::BoundedZCIS{input, size}); +} + +bool MessageLite::ParsePartialFromBoundedZeroCopyStream( + io::ZeroCopyInputStream* input, int size) { + return ParseFrom<kParsePartial>(internal::BoundedZCIS{input, size}); +} + +bool MessageLite::ParseFromString(ConstStringParam data) { + return ParseFrom<kParse>(data); +} + +bool MessageLite::ParsePartialFromString(ConstStringParam data) { + return ParseFrom<kParsePartial>(data); +} + +bool MessageLite::ParseFromArray(const void* data, int size) { + return ParseFrom<kParse>(as_string_view(data, size)); +} + +bool MessageLite::ParsePartialFromArray(const void* data, int size) { + return ParseFrom<kParsePartial>(as_string_view(data, size)); +} + +bool MessageLite::MergeFromString(ConstStringParam data) { + return ParseFrom<kMerge>(data); +} + + +// =================================================================== + +inline uint8_t* SerializeToArrayImpl(const MessageLite& msg, uint8_t* target, + int size) { + constexpr bool debug = false; + if (debug) { + // Force serialization to a stream with a block size of 1, which forces + // all writes to the stream to cross buffers triggering all fallback paths + // in the unittests when serializing to string / array. + io::ArrayOutputStream stream(target, size, 1); + uint8_t* ptr; + io::EpsCopyOutputStream out( + &stream, io::CodedOutputStream::IsDefaultSerializationDeterministic(), + &ptr); + ptr = msg._InternalSerialize(ptr, &out); + out.Trim(ptr); + GOOGLE_DCHECK(!out.HadError() && stream.ByteCount() == size); + return target + size; + } else { + io::EpsCopyOutputStream out( + target, size, + io::CodedOutputStream::IsDefaultSerializationDeterministic()); + auto res = msg._InternalSerialize(target, &out); + GOOGLE_DCHECK(target + size == res); + return res; + } +} + +uint8_t* MessageLite::SerializeWithCachedSizesToArray(uint8_t* target) const { + // We only optimize this when using optimize_for = SPEED. In other cases + // we just use the CodedOutputStream path. + return SerializeToArrayImpl(*this, target, GetCachedSize()); +} + +bool MessageLite::SerializeToCodedStream(io::CodedOutputStream* output) const { + GOOGLE_DCHECK(IsInitialized()) << InitializationErrorMessage("serialize", *this); + return SerializePartialToCodedStream(output); +} + +bool MessageLite::SerializePartialToCodedStream( + io::CodedOutputStream* output) const { + const size_t size = ByteSizeLong(); // Force size to be cached. + if (size > INT_MAX) { + GOOGLE_LOG(ERROR) << GetTypeName() + << " exceeded maximum protobuf size of 2GB: " << size; + return false; + } + + int original_byte_count = output->ByteCount(); + SerializeWithCachedSizes(output); + if (output->HadError()) { + return false; + } + int final_byte_count = output->ByteCount(); + + if (final_byte_count - original_byte_count != static_cast<int64_t>(size)) { + ByteSizeConsistencyError(size, ByteSizeLong(), + final_byte_count - original_byte_count, *this); + } + + return true; +} + +bool MessageLite::SerializeToZeroCopyStream( + io::ZeroCopyOutputStream* output) const { + GOOGLE_DCHECK(IsInitialized()) << InitializationErrorMessage("serialize", *this); + return SerializePartialToZeroCopyStream(output); +} + +bool MessageLite::SerializePartialToZeroCopyStream( + io::ZeroCopyOutputStream* output) const { + const size_t size = ByteSizeLong(); // Force size to be cached. + if (size > INT_MAX) { + GOOGLE_LOG(ERROR) << GetTypeName() + << " exceeded maximum protobuf size of 2GB: " << size; + return false; + } + + uint8_t* target; + io::EpsCopyOutputStream stream( + output, io::CodedOutputStream::IsDefaultSerializationDeterministic(), + &target); + target = _InternalSerialize(target, &stream); + stream.Trim(target); + if (stream.HadError()) return false; + return true; +} + +bool MessageLite::SerializeToFileDescriptor(int file_descriptor) const { + io::FileOutputStream output(file_descriptor); + return SerializeToZeroCopyStream(&output) && output.Flush(); +} + +bool MessageLite::SerializePartialToFileDescriptor(int file_descriptor) const { + io::FileOutputStream output(file_descriptor); + return SerializePartialToZeroCopyStream(&output) && output.Flush(); +} + +bool MessageLite::SerializeToOstream(std::ostream* output) const { + { + io::OstreamOutputStream zero_copy_output(output); + if (!SerializeToZeroCopyStream(&zero_copy_output)) return false; + } + return output->good(); +} + +bool MessageLite::SerializePartialToOstream(std::ostream* output) const { + io::OstreamOutputStream zero_copy_output(output); + return SerializePartialToZeroCopyStream(&zero_copy_output); +} + +bool MessageLite::AppendToString(std::string* output) const { + GOOGLE_DCHECK(IsInitialized()) << InitializationErrorMessage("serialize", *this); + return AppendPartialToString(output); +} + +bool MessageLite::AppendPartialToString(std::string* output) const { + size_t old_size = output->size(); + size_t byte_size = ByteSizeLong(); + if (byte_size > INT_MAX) { + GOOGLE_LOG(ERROR) << GetTypeName() + << " exceeded maximum protobuf size of 2GB: " << byte_size; + return false; + } + + STLStringResizeUninitializedAmortized(output, old_size + byte_size); + uint8_t* start = + reinterpret_cast<uint8_t*>(io::mutable_string_data(output) + old_size); + SerializeToArrayImpl(*this, start, byte_size); + return true; +} + +bool MessageLite::SerializeToString(std::string* output) const { + output->clear(); + return AppendToString(output); +} + +bool MessageLite::SerializePartialToString(std::string* output) const { + output->clear(); + return AppendPartialToString(output); +} + +bool MessageLite::SerializeToArray(void* data, int size) const { + GOOGLE_DCHECK(IsInitialized()) << InitializationErrorMessage("serialize", *this); + return SerializePartialToArray(data, size); +} + +bool MessageLite::SerializePartialToArray(void* data, int size) const { + const size_t byte_size = ByteSizeLong(); + if (byte_size > INT_MAX) { + GOOGLE_LOG(ERROR) << GetTypeName() + << " exceeded maximum protobuf size of 2GB: " << byte_size; + return false; + } + if (size < static_cast<int64_t>(byte_size)) return false; + uint8_t* start = reinterpret_cast<uint8_t*>(data); + SerializeToArrayImpl(*this, start, byte_size); + return true; +} + +std::string MessageLite::SerializeAsString() const { + // If the compiler implements the (Named) Return Value Optimization, + // the local variable 'output' will not actually reside on the stack + // of this function, but will be overlaid with the object that the + // caller supplied for the return value to be constructed in. + std::string output; + if (!AppendToString(&output)) output.clear(); + return output; +} + +std::string MessageLite::SerializePartialAsString() const { + std::string output; + if (!AppendPartialToString(&output)) output.clear(); + return output; +} + + +namespace internal { + +MessageLite* NewFromPrototypeHelper(const MessageLite* prototype, + Arena* arena) { + return prototype->New(arena); +} +template <> +void GenericTypeHandler<MessageLite>::Merge(const MessageLite& from, + MessageLite* to) { + to->CheckTypeAndMergeFrom(from); +} +template <> +void GenericTypeHandler<std::string>::Merge(const std::string& from, + std::string* to) { + *to = from; +} + +// Non-inline implementations of InternalMetadata destructor +// This is moved out of the header because the GOOGLE_DCHECK produces a lot of code. +void InternalMetadata::CheckedDestruct() { + if (HasMessageOwnedArenaTag()) { + GOOGLE_DCHECK(!HasUnknownFieldsTag()); + delete reinterpret_cast<Arena*>(ptr_ - kMessageOwnedArenaTagMask); + } +} + +// Non-inline variants of std::string specializations for +// various InternalMetadata routines. +template <> +void InternalMetadata::DoClear<std::string>() { + mutable_unknown_fields<std::string>()->clear(); +} + +template <> +void InternalMetadata::DoMergeFrom<std::string>(const std::string& other) { + mutable_unknown_fields<std::string>()->append(other); +} + +template <> +void InternalMetadata::DoSwap<std::string>(std::string* other) { + mutable_unknown_fields<std::string>()->swap(*other); +} + +} // namespace internal + + +// =================================================================== +// Shutdown support. + +namespace internal { + +struct ShutdownData { + ~ShutdownData() { + std::reverse(functions.begin(), functions.end()); + for (auto pair : functions) pair.first(pair.second); + } + + static ShutdownData* get() { + static auto* data = new ShutdownData; + return data; + } + + std::vector<std::pair<void (*)(const void*), const void*>> functions; + Mutex mutex; +}; + +static void RunZeroArgFunc(const void* arg) { + void (*func)() = reinterpret_cast<void (*)()>(const_cast<void*>(arg)); + func(); +} + +void OnShutdown(void (*func)()) { + OnShutdownRun(RunZeroArgFunc, reinterpret_cast<void*>(func)); +} + +void OnShutdownRun(void (*f)(const void*), const void* arg) { + auto shutdown_data = ShutdownData::get(); + MutexLock lock(&shutdown_data->mutex); + shutdown_data->functions.push_back(std::make_pair(f, arg)); +} + +} // namespace internal + +void ShutdownProtobufLibrary() { + // This function should be called only once, but accepts multiple calls. + static bool is_shutdown = false; + if (!is_shutdown) { + delete internal::ShutdownData::get(); + is_shutdown = true; + } +} + + +} // namespace protobuf +} // namespace google + +#include <google/protobuf/port_undef.inc> diff --git a/toolkit/components/protobuf/src/google/protobuf/message_lite.h b/toolkit/components/protobuf/src/google/protobuf/message_lite.h new file mode 100644 index 0000000000..950ae1a126 --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/message_lite.h @@ -0,0 +1,591 @@ +// 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. + +// Authors: wink@google.com (Wink Saville), +// kenton@google.com (Kenton Varda) +// Based on original Protocol Buffers design by +// Sanjay Ghemawat, Jeff Dean, and others. +// +// Defines MessageLite, the abstract interface implemented by all (lite +// and non-lite) protocol message objects. + +#ifndef GOOGLE_PROTOBUF_MESSAGE_LITE_H__ +#define GOOGLE_PROTOBUF_MESSAGE_LITE_H__ + + +#include <climits> +#include <string> + +#include <google/protobuf/stubs/common.h> +#include <google/protobuf/stubs/logging.h> +#include <google/protobuf/io/coded_stream.h> +#include <google/protobuf/arena.h> +#include <google/protobuf/stubs/once.h> +#include <google/protobuf/port.h> +#include <google/protobuf/stubs/strutil.h> +#include <google/protobuf/explicitly_constructed.h> +#include <google/protobuf/metadata_lite.h> +#include <google/protobuf/stubs/hash.h> // TODO(b/211442718): cleanup + +// clang-format off +#include <google/protobuf/port_def.inc> +// clang-format on + +#ifdef SWIG +#error "You cannot SWIG proto headers" +#endif + +namespace google { +namespace protobuf { + +template <typename T> +class RepeatedPtrField; + +class FastReflectionMessageMutator; +class FastReflectionStringSetter; +class Reflection; + +namespace io { + +class CodedInputStream; +class CodedOutputStream; +class ZeroCopyInputStream; +class ZeroCopyOutputStream; + +} // namespace io +namespace internal { + +class SwapFieldHelper; + +// See parse_context.h for explanation +class ParseContext; + +class ExtensionSet; +class LazyField; +class RepeatedPtrFieldBase; +class TcParser; +class WireFormatLite; +class WeakFieldMap; + +template <typename Type> +class GenericTypeHandler; // defined in repeated_field.h + +// We compute sizes as size_t but cache them as int. This function converts a +// computed size to a cached size. Since we don't proceed with serialization +// if the total size was > INT_MAX, it is not important what this function +// returns for inputs > INT_MAX. However this case should not error or +// GOOGLE_CHECK-fail, because the full size_t resolution is still returned from +// ByteSizeLong() and checked against INT_MAX; we can catch the overflow +// there. +inline int ToCachedSize(size_t size) { return static_cast<int>(size); } + +// We mainly calculate sizes in terms of size_t, but some functions that +// compute sizes return "int". These int sizes are expected to always be +// positive. This function is more efficient than casting an int to size_t +// directly on 64-bit platforms because it avoids making the compiler emit a +// sign extending instruction, which we don't want and don't want to pay for. +inline size_t FromIntSize(int size) { + // Convert to unsigned before widening so sign extension is not necessary. + return static_cast<unsigned int>(size); +} + +// For cases where a legacy function returns an integer size. We GOOGLE_DCHECK() +// that the conversion will fit within an integer; if this is false then we +// are losing information. +inline int ToIntSize(size_t size) { + GOOGLE_DCHECK_LE(size, static_cast<size_t>(INT_MAX)); + return static_cast<int>(size); +} + +// Default empty string object. Don't use this directly. Instead, call +// GetEmptyString() to get the reference. This empty string is aligned with a +// minimum alignment of 8 bytes to match the requirement of ArenaStringPtr. +PROTOBUF_EXPORT extern ExplicitlyConstructedArenaString + fixed_address_empty_string; + + +PROTOBUF_EXPORT constexpr const std::string& GetEmptyStringAlreadyInited() { + return fixed_address_empty_string.get(); +} + +PROTOBUF_EXPORT size_t StringSpaceUsedExcludingSelfLong(const std::string& str); + +} // namespace internal + +// Interface to light weight protocol messages. +// +// This interface is implemented by all protocol message objects. Non-lite +// messages additionally implement the Message interface, which is a +// subclass of MessageLite. Use MessageLite instead when you only need +// the subset of features which it supports -- namely, nothing that uses +// descriptors or reflection. You can instruct the protocol compiler +// to generate classes which implement only MessageLite, not the full +// Message interface, by adding the following line to the .proto file: +// +// option optimize_for = LITE_RUNTIME; +// +// This is particularly useful on resource-constrained systems where +// the full protocol buffers runtime library is too big. +// +// Note that on non-constrained systems (e.g. servers) when you need +// to link in lots of protocol definitions, a better way to reduce +// total code footprint is to use optimize_for = CODE_SIZE. This +// will make the generated code smaller while still supporting all the +// same features (at the expense of speed). optimize_for = LITE_RUNTIME +// is best when you only have a small number of message types linked +// into your binary, in which case the size of the protocol buffers +// runtime itself is the biggest problem. +// +// Users must not derive from this class. Only the protocol compiler and +// the internal library are allowed to create subclasses. +class PROTOBUF_EXPORT MessageLite { + public: + constexpr MessageLite() {} + virtual ~MessageLite() = default; + + // Basic Operations ------------------------------------------------ + + // Get the name of this message type, e.g. "foo.bar.BazProto". + virtual std::string GetTypeName() const = 0; + + // Construct a new instance of the same type. Ownership is passed to the + // caller. + MessageLite* New() const { return New(nullptr); } + + // Construct a new instance on the arena. Ownership is passed to the caller + // if arena is a nullptr. + virtual MessageLite* New(Arena* arena) const = 0; + + // Returns user-owned arena; nullptr if it's message owned. + Arena* GetArena() const { return _internal_metadata_.user_arena(); } + + // Clear all fields of the message and set them to their default values. + // Clear() assumes that any memory allocated to hold parts of the message + // will likely be needed again, so the memory used may not be freed. + // To ensure that all memory used by a Message is freed, you must delete it. + virtual void Clear() = 0; + + // Quickly check if all required fields have values set. + virtual bool IsInitialized() const = 0; + + // This is not implemented for Lite messages -- it just returns "(cannot + // determine missing fields for lite message)". However, it is implemented + // for full messages. See message.h. + virtual std::string InitializationErrorString() const; + + // If |other| is the exact same class as this, calls MergeFrom(). Otherwise, + // results are undefined (probably crash). + virtual void CheckTypeAndMergeFrom(const MessageLite& other) = 0; + + // These methods return a human-readable summary of the message. Note that + // since the MessageLite interface does not support reflection, there is very + // little information that these methods can provide. They are shadowed by + // methods of the same name on the Message interface which provide much more + // information. The methods here are intended primarily to facilitate code + // reuse for logic that needs to interoperate with both full and lite protos. + // + // The format of the returned string is subject to change, so please do not + // assume it will remain stable over time. + std::string DebugString() const; + std::string ShortDebugString() const { return DebugString(); } + // MessageLite::DebugString is already Utf8 Safe. This is to add compatibility + // with Message. + std::string Utf8DebugString() const { return DebugString(); } + + // Parsing --------------------------------------------------------- + // Methods for parsing in protocol buffer format. Most of these are + // just simple wrappers around MergeFromCodedStream(). Clear() will be + // called before merging the input. + + // Fill the message with a protocol buffer parsed from the given input + // stream. Returns false on a read error or if the input is in the wrong + // format. A successful return does not indicate the entire input is + // consumed, ensure you call ConsumedEntireMessage() to check that if + // applicable. + PROTOBUF_ATTRIBUTE_REINITIALIZES bool ParseFromCodedStream( + io::CodedInputStream* input); + // Like ParseFromCodedStream(), but accepts messages that are missing + // required fields. + PROTOBUF_ATTRIBUTE_REINITIALIZES bool ParsePartialFromCodedStream( + io::CodedInputStream* input); + // Read a protocol buffer from the given zero-copy input stream. If + // successful, the entire input will be consumed. + PROTOBUF_ATTRIBUTE_REINITIALIZES bool ParseFromZeroCopyStream( + io::ZeroCopyInputStream* input); + // Like ParseFromZeroCopyStream(), but accepts messages that are missing + // required fields. + PROTOBUF_ATTRIBUTE_REINITIALIZES bool ParsePartialFromZeroCopyStream( + io::ZeroCopyInputStream* input); + // Parse a protocol buffer from a file descriptor. If successful, the entire + // input will be consumed. + PROTOBUF_ATTRIBUTE_REINITIALIZES bool ParseFromFileDescriptor( + int file_descriptor); + // Like ParseFromFileDescriptor(), but accepts messages that are missing + // required fields. + PROTOBUF_ATTRIBUTE_REINITIALIZES bool ParsePartialFromFileDescriptor( + int file_descriptor); + // Parse a protocol buffer from a C++ istream. If successful, the entire + // input will be consumed. + PROTOBUF_ATTRIBUTE_REINITIALIZES bool ParseFromIstream(std::istream* input); + // Like ParseFromIstream(), but accepts messages that are missing + // required fields. + PROTOBUF_ATTRIBUTE_REINITIALIZES bool ParsePartialFromIstream( + std::istream* input); + // Read a protocol buffer from the given zero-copy input stream, expecting + // the message to be exactly "size" bytes long. If successful, exactly + // this many bytes will have been consumed from the input. + bool MergePartialFromBoundedZeroCopyStream(io::ZeroCopyInputStream* input, + int size); + // Like ParseFromBoundedZeroCopyStream(), but accepts messages that are + // missing required fields. + bool MergeFromBoundedZeroCopyStream(io::ZeroCopyInputStream* input, int size); + PROTOBUF_ATTRIBUTE_REINITIALIZES bool ParseFromBoundedZeroCopyStream( + io::ZeroCopyInputStream* input, int size); + // Like ParseFromBoundedZeroCopyStream(), but accepts messages that are + // missing required fields. + PROTOBUF_ATTRIBUTE_REINITIALIZES bool ParsePartialFromBoundedZeroCopyStream( + io::ZeroCopyInputStream* input, int size); + // Parses a protocol buffer contained in a string. Returns true on success. + // This function takes a string in the (non-human-readable) binary wire + // format, matching the encoding output by MessageLite::SerializeToString(). + // If you'd like to convert a human-readable string into a protocol buffer + // object, see google::protobuf::TextFormat::ParseFromString(). + PROTOBUF_ATTRIBUTE_REINITIALIZES bool ParseFromString(ConstStringParam data); + // Like ParseFromString(), but accepts messages that are missing + // required fields. + PROTOBUF_ATTRIBUTE_REINITIALIZES bool ParsePartialFromString( + ConstStringParam data); + // Parse a protocol buffer contained in an array of bytes. + PROTOBUF_ATTRIBUTE_REINITIALIZES bool ParseFromArray(const void* data, + int size); + // Like ParseFromArray(), but accepts messages that are missing + // required fields. + PROTOBUF_ATTRIBUTE_REINITIALIZES bool ParsePartialFromArray(const void* data, + int size); + + + // Reads a protocol buffer from the stream and merges it into this + // Message. Singular fields read from the what is + // already in the Message and repeated fields are appended to those + // already present. + // + // It is the responsibility of the caller to call input->LastTagWas() + // (for groups) or input->ConsumedEntireMessage() (for non-groups) after + // this returns to verify that the message's end was delimited correctly. + // + // ParseFromCodedStream() is implemented as Clear() followed by + // MergeFromCodedStream(). + bool MergeFromCodedStream(io::CodedInputStream* input); + + // Like MergeFromCodedStream(), but succeeds even if required fields are + // missing in the input. + // + // MergeFromCodedStream() is just implemented as MergePartialFromCodedStream() + // followed by IsInitialized(). + bool MergePartialFromCodedStream(io::CodedInputStream* input); + + // Merge a protocol buffer contained in a string. + bool MergeFromString(ConstStringParam data); + + + // Serialization --------------------------------------------------- + // Methods for serializing in protocol buffer format. Most of these + // are just simple wrappers around ByteSize() and SerializeWithCachedSizes(). + + // Write a protocol buffer of this message to the given output. Returns + // false on a write error. If the message is missing required fields, + // this may GOOGLE_CHECK-fail. + bool SerializeToCodedStream(io::CodedOutputStream* output) const; + // Like SerializeToCodedStream(), but allows missing required fields. + bool SerializePartialToCodedStream(io::CodedOutputStream* output) const; + // Write the message to the given zero-copy output stream. All required + // fields must be set. + bool SerializeToZeroCopyStream(io::ZeroCopyOutputStream* output) const; + // Like SerializeToZeroCopyStream(), but allows missing required fields. + bool SerializePartialToZeroCopyStream(io::ZeroCopyOutputStream* output) const; + // Serialize the message and store it in the given string. All required + // fields must be set. + bool SerializeToString(std::string* output) const; + // Like SerializeToString(), but allows missing required fields. + bool SerializePartialToString(std::string* output) const; + // Serialize the message and store it in the given byte array. All required + // fields must be set. + bool SerializeToArray(void* data, int size) const; + // Like SerializeToArray(), but allows missing required fields. + bool SerializePartialToArray(void* data, int size) const; + + // Make a string encoding the message. Is equivalent to calling + // SerializeToString() on a string and using that. Returns the empty + // string if SerializeToString() would have returned an error. + // Note: If you intend to generate many such strings, you may + // reduce heap fragmentation by instead re-using the same string + // object with calls to SerializeToString(). + std::string SerializeAsString() const; + // Like SerializeAsString(), but allows missing required fields. + std::string SerializePartialAsString() const; + + // Serialize the message and write it to the given file descriptor. All + // required fields must be set. + bool SerializeToFileDescriptor(int file_descriptor) const; + // Like SerializeToFileDescriptor(), but allows missing required fields. + bool SerializePartialToFileDescriptor(int file_descriptor) const; + // Serialize the message and write it to the given C++ ostream. All + // required fields must be set. + bool SerializeToOstream(std::ostream* output) const; + // Like SerializeToOstream(), but allows missing required fields. + bool SerializePartialToOstream(std::ostream* output) const; + + // Like SerializeToString(), but appends to the data to the string's + // existing contents. All required fields must be set. + bool AppendToString(std::string* output) const; + // Like AppendToString(), but allows missing required fields. + bool AppendPartialToString(std::string* output) const; + + + // Computes the serialized size of the message. This recursively calls + // ByteSizeLong() on all embedded messages. + // + // ByteSizeLong() is generally linear in the number of fields defined for the + // proto. + virtual size_t ByteSizeLong() const = 0; + + // Legacy ByteSize() API. + PROTOBUF_DEPRECATED_MSG("Please use ByteSizeLong() instead") + int ByteSize() const { return internal::ToIntSize(ByteSizeLong()); } + + // Serializes the message without recomputing the size. The message must not + // have changed since the last call to ByteSize(), and the value returned by + // ByteSize must be non-negative. Otherwise the results are undefined. + void SerializeWithCachedSizes(io::CodedOutputStream* output) const { + output->SetCur(_InternalSerialize(output->Cur(), output->EpsCopy())); + } + + // Functions below here are not part of the public interface. It isn't + // enforced, but they should be treated as private, and will be private + // at some future time. Unfortunately the implementation of the "friend" + // keyword in GCC is broken at the moment, but we expect it will be fixed. + + // Like SerializeWithCachedSizes, but writes directly to *target, returning + // a pointer to the byte immediately after the last byte written. "target" + // must point at a byte array of at least ByteSize() bytes. Whether to use + // deterministic serialization, e.g., maps in sorted order, is determined by + // CodedOutputStream::IsDefaultSerializationDeterministic(). + uint8_t* SerializeWithCachedSizesToArray(uint8_t* target) const; + + // Returns the result of the last call to ByteSize(). An embedded message's + // size is needed both to serialize it (because embedded messages are + // length-delimited) and to compute the outer message's size. Caching + // the size avoids computing it multiple times. + // + // ByteSize() does not automatically use the cached size when available + // because this would require invalidating it every time the message was + // modified, which would be too hard and expensive. (E.g. if a deeply-nested + // sub-message is changed, all of its parents' cached sizes would need to be + // invalidated, which is too much work for an otherwise inlined setter + // method.) + virtual int GetCachedSize() const = 0; + + virtual const char* _InternalParse(const char* /*ptr*/, + internal::ParseContext* /*ctx*/) { + return nullptr; + } + + virtual void OnDemandRegisterArenaDtor(Arena* /*arena*/) {} + + protected: + template <typename T> + static T* CreateMaybeMessage(Arena* arena) { + return Arena::CreateMaybeMessage<T>(arena); + } + + inline explicit MessageLite(Arena* arena, bool is_message_owned = false) + : _internal_metadata_(arena, is_message_owned) {} + + // Returns the arena, if any, that directly owns this message and its internal + // memory (Arena::Own is different in that the arena doesn't directly own the + // internal memory). This method is used in proto's implementation for + // swapping, moving and setting allocated, for deciding whether the ownership + // of this message or its internal memory could be changed. + Arena* GetOwningArena() const { return _internal_metadata_.owning_arena(); } + + // Returns the arena, used for allocating internal objects(e.g., child + // messages, etc), or owning incoming objects (e.g., set allocated). + Arena* GetArenaForAllocation() const { return _internal_metadata_.arena(); } + + // Returns true if this message is enabled for message-owned arena (MOA) + // trials. No lite messages are eligible for MOA. + static bool InMoaTrial() { return false; } + + internal::InternalMetadata _internal_metadata_; + + public: + enum ParseFlags { + kMerge = 0, + kParse = 1, + kMergePartial = 2, + kParsePartial = 3, + kMergeWithAliasing = 4, + kParseWithAliasing = 5, + kMergePartialWithAliasing = 6, + kParsePartialWithAliasing = 7 + }; + + template <ParseFlags flags, typename T> + bool ParseFrom(const T& input); + + // Fast path when conditions match (ie. non-deterministic) + // uint8_t* _InternalSerialize(uint8_t* ptr) const; + virtual uint8_t* _InternalSerialize( + uint8_t* ptr, io::EpsCopyOutputStream* stream) const = 0; + + // Identical to IsInitialized() except that it logs an error message. + bool IsInitializedWithErrors() const { + if (IsInitialized()) return true; + LogInitializationErrorMessage(); + return false; + } + + private: + friend class FastReflectionMessageMutator; + friend class FastReflectionStringSetter; + friend class Message; + friend class Reflection; + friend class internal::ExtensionSet; + friend class internal::LazyField; + friend class internal::SwapFieldHelper; + friend class internal::TcParser; + friend class internal::WeakFieldMap; + friend class internal::WireFormatLite; + + template <typename Type> + friend class Arena::InternalHelper; + template <typename Type> + friend class internal::GenericTypeHandler; + + void LogInitializationErrorMessage() const; + + bool MergeFromImpl(io::CodedInputStream* input, ParseFlags parse_flags); + + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessageLite); +}; + +namespace internal { + +template <bool alias> +bool MergeFromImpl(StringPiece input, MessageLite* msg, + MessageLite::ParseFlags parse_flags); +extern template bool MergeFromImpl<false>(StringPiece input, + MessageLite* msg, + MessageLite::ParseFlags parse_flags); +extern template bool MergeFromImpl<true>(StringPiece input, + MessageLite* msg, + MessageLite::ParseFlags parse_flags); + +template <bool alias> +bool MergeFromImpl(io::ZeroCopyInputStream* input, MessageLite* msg, + MessageLite::ParseFlags parse_flags); +extern template bool MergeFromImpl<false>(io::ZeroCopyInputStream* input, + MessageLite* msg, + MessageLite::ParseFlags parse_flags); +extern template bool MergeFromImpl<true>(io::ZeroCopyInputStream* input, + MessageLite* msg, + MessageLite::ParseFlags parse_flags); + +struct BoundedZCIS { + io::ZeroCopyInputStream* zcis; + int limit; +}; + +template <bool alias> +bool MergeFromImpl(BoundedZCIS input, MessageLite* msg, + MessageLite::ParseFlags parse_flags); +extern template bool MergeFromImpl<false>(BoundedZCIS input, MessageLite* msg, + MessageLite::ParseFlags parse_flags); +extern template bool MergeFromImpl<true>(BoundedZCIS input, MessageLite* msg, + MessageLite::ParseFlags parse_flags); + +template <typename T> +struct SourceWrapper; + +template <bool alias, typename T> +bool MergeFromImpl(const SourceWrapper<T>& input, MessageLite* msg, + MessageLite::ParseFlags parse_flags) { + return input.template MergeInto<alias>(msg, parse_flags); +} + +} // namespace internal + +template <MessageLite::ParseFlags flags, typename T> +bool MessageLite::ParseFrom(const T& input) { + if (flags & kParse) Clear(); + constexpr bool alias = (flags & kMergeWithAliasing) != 0; + return internal::MergeFromImpl<alias>(input, this, flags); +} + +// =================================================================== +// Shutdown support. + + +// Shut down the entire protocol buffers library, deleting all static-duration +// objects allocated by the library or by generated .pb.cc files. +// +// There are two reasons you might want to call this: +// * You use a draconian definition of "memory leak" in which you expect +// every single malloc() to have a corresponding free(), even for objects +// which live until program exit. +// * You are writing a dynamically-loaded library which needs to clean up +// after itself when the library is unloaded. +// +// It is safe to call this multiple times. However, it is not safe to use +// any other part of the protocol buffers library after +// ShutdownProtobufLibrary() has been called. Furthermore this call is not +// thread safe, user needs to synchronize multiple calls. +PROTOBUF_EXPORT void ShutdownProtobufLibrary(); + +namespace internal { + +// Register a function to be called when ShutdownProtocolBuffers() is called. +PROTOBUF_EXPORT void OnShutdown(void (*func)()); +// Run an arbitrary function on an arg +PROTOBUF_EXPORT void OnShutdownRun(void (*f)(const void*), const void* arg); + +template <typename T> +T* OnShutdownDelete(T* p) { + OnShutdownRun([](const void* pp) { delete static_cast<const T*>(pp); }, p); + return p; +} + +} // namespace internal +} // namespace protobuf +} // namespace google + +#include <google/protobuf/port_undef.inc> + +#endif // GOOGLE_PROTOBUF_MESSAGE_LITE_H__ diff --git a/toolkit/components/protobuf/src/google/protobuf/metadata.h b/toolkit/components/protobuf/src/google/protobuf/metadata.h new file mode 100644 index 0000000000..4e89648ee6 --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/metadata.h @@ -0,0 +1,36 @@ +// 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. + +#ifndef GOOGLE_PROTOBUF_METADATA_H__ +#define GOOGLE_PROTOBUF_METADATA_H__ + +// TODO(b/151117630): Remove this file and all instances where it gets imported. + +#endif // GOOGLE_PROTOBUF_METADATA_H__ diff --git a/toolkit/components/protobuf/src/google/protobuf/metadata_lite.h b/toolkit/components/protobuf/src/google/protobuf/metadata_lite.h new file mode 100644 index 0000000000..0c31517f08 --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/metadata_lite.h @@ -0,0 +1,316 @@ +// 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. + +#ifndef GOOGLE_PROTOBUF_METADATA_LITE_H__ +#define GOOGLE_PROTOBUF_METADATA_LITE_H__ + +#include <string> +#include <google/protobuf/stubs/common.h> +#include <google/protobuf/arena.h> +#include <google/protobuf/port.h> + +// Must be included last. +#include <google/protobuf/port_def.inc> + +#ifdef SWIG +#error "You cannot SWIG proto headers" +#endif + +namespace google { +namespace protobuf { +namespace internal { + +// This is the representation for messages that support arena allocation. It +// uses a tagged pointer to either store the owning Arena pointer, if there are +// no unknown fields, or a pointer to a block of memory with both the owning +// Arena pointer and the UnknownFieldSet, if there are unknown fields. Besides, +// it also uses the tag to distinguish whether the owning Arena pointer is also +// used by sub-structure allocation. This optimization allows for +// "zero-overhead" storage of the Arena pointer, relative to the above baseline +// implementation. +// +// The tagged pointer uses the least two significant bits to disambiguate cases. +// It uses bit 0 == 0 to indicate an arena pointer and bit 0 == 1 to indicate a +// UFS+Arena-container pointer. Besides it uses bit 1 == 0 to indicate arena +// allocation and bit 1 == 1 to indicate heap allocation. +class PROTOBUF_EXPORT InternalMetadata { + public: + constexpr InternalMetadata() : ptr_(0) {} + explicit InternalMetadata(Arena* arena, bool is_message_owned = false) { + SetArena(arena, is_message_owned); + } + + void SetArena(Arena* arena, bool is_message_owned) { + ptr_ = is_message_owned + ? reinterpret_cast<intptr_t>(arena) | kMessageOwnedArenaTagMask + : reinterpret_cast<intptr_t>(arena); + GOOGLE_DCHECK(!is_message_owned || arena != nullptr); + } + + // To keep the ABI identical between debug and non-debug builds, + // the destructor is always defined here even though it may delegate + // to a non-inline private method. + // (see https://github.com/protocolbuffers/protobuf/issues/9947) + ~InternalMetadata() { +#if defined(NDEBUG) || defined(_MSC_VER) + if (HasMessageOwnedArenaTag()) { + delete reinterpret_cast<Arena*>(ptr_ - kMessageOwnedArenaTagMask); + } +#else + CheckedDestruct(); +#endif + } + + template <typename T> + void Delete() { + // Note that Delete<> should be called not more than once. + if (have_unknown_fields()) { + DeleteOutOfLineHelper<T>(); + } + } + + // DeleteReturnArena will delete the unknown fields only if they weren't + // allocated on an arena. Then it updates the flags so that if you call + // have_unknown_fields(), it will return false. Finally, it returns the + // current value of arena(). It is designed to be used as part of a + // Message class's destructor call, so that when control eventually gets + // to ~InternalMetadata(), we don't need to check for have_unknown_fields() + // again. + template <typename T> + Arena* DeleteReturnArena() { + if (have_unknown_fields()) { + return DeleteOutOfLineHelper<T>(); + } else { + return PtrValue<Arena>(); + } + } + + PROTOBUF_NDEBUG_INLINE Arena* owning_arena() const { + return HasMessageOwnedArenaTag() ? nullptr : arena(); + } + + PROTOBUF_NDEBUG_INLINE Arena* user_arena() const { + Arena* a = arena(); + return a && !a->IsMessageOwned() ? a : nullptr; + } + + PROTOBUF_NDEBUG_INLINE Arena* arena() const { + if (PROTOBUF_PREDICT_FALSE(have_unknown_fields())) { + return PtrValue<ContainerBase>()->arena; + } else { + return PtrValue<Arena>(); + } + } + + PROTOBUF_NDEBUG_INLINE bool have_unknown_fields() const { + return HasUnknownFieldsTag(); + } + + PROTOBUF_NDEBUG_INLINE void* raw_arena_ptr() const { + return reinterpret_cast<void*>(ptr_); + } + + template <typename T> + PROTOBUF_NDEBUG_INLINE const T& unknown_fields( + const T& (*default_instance)()) const { + if (PROTOBUF_PREDICT_FALSE(have_unknown_fields())) { + return PtrValue<Container<T>>()->unknown_fields; + } else { + return default_instance(); + } + } + + template <typename T> + PROTOBUF_NDEBUG_INLINE T* mutable_unknown_fields() { + if (PROTOBUF_PREDICT_TRUE(have_unknown_fields())) { + return &PtrValue<Container<T>>()->unknown_fields; + } else { + return mutable_unknown_fields_slow<T>(); + } + } + + template <typename T> + PROTOBUF_NDEBUG_INLINE void Swap(InternalMetadata* other) { + // Semantics here are that we swap only the unknown fields, not the arena + // pointer. We cannot simply swap ptr_ with other->ptr_ because we need to + // maintain our own arena ptr. Also, our ptr_ and other's ptr_ may be in + // different states (direct arena pointer vs. container with UFS) so we + // cannot simply swap ptr_ and then restore the arena pointers. We reuse + // UFS's swap implementation instead. + if (have_unknown_fields() || other->have_unknown_fields()) { + DoSwap<T>(other->mutable_unknown_fields<T>()); + } + } + + PROTOBUF_NDEBUG_INLINE void InternalSwap(InternalMetadata* other) { + std::swap(ptr_, other->ptr_); + } + + template <typename T> + PROTOBUF_NDEBUG_INLINE void MergeFrom(const InternalMetadata& other) { + if (other.have_unknown_fields()) { + DoMergeFrom<T>(other.unknown_fields<T>(nullptr)); + } + } + + template <typename T> + PROTOBUF_NDEBUG_INLINE void Clear() { + if (have_unknown_fields()) { + DoClear<T>(); + } + } + + private: + intptr_t ptr_; + + // Tagged pointer implementation. + static constexpr intptr_t kUnknownFieldsTagMask = 1; + static constexpr intptr_t kMessageOwnedArenaTagMask = 2; + static constexpr intptr_t kPtrTagMask = + kUnknownFieldsTagMask | kMessageOwnedArenaTagMask; + static constexpr intptr_t kPtrValueMask = ~kPtrTagMask; + + // Accessors for pointer tag and pointer value. + PROTOBUF_ALWAYS_INLINE bool HasUnknownFieldsTag() const { + return ptr_ & kUnknownFieldsTagMask; + } + PROTOBUF_ALWAYS_INLINE bool HasMessageOwnedArenaTag() const { + return ptr_ & kMessageOwnedArenaTagMask; + } + + template <typename U> + U* PtrValue() const { + return reinterpret_cast<U*>(ptr_ & kPtrValueMask); + } + + // If ptr_'s tag is kTagContainer, it points to an instance of this struct. + struct ContainerBase { + Arena* arena; + }; + + template <typename T> + struct Container : public ContainerBase { + T unknown_fields; + }; + + template <typename T> + PROTOBUF_NOINLINE Arena* DeleteOutOfLineHelper() { + if (auto* a = arena()) { + // Subtle: we want to preserve the message-owned arena flag, while at the + // same time replacing the pointer to Container<T> with a pointer to the + // arena. + intptr_t message_owned_arena_tag = ptr_ & kMessageOwnedArenaTagMask; + ptr_ = reinterpret_cast<intptr_t>(a) | message_owned_arena_tag; + return a; + } else { + delete PtrValue<Container<T>>(); + ptr_ = 0; + return nullptr; + } + } + + template <typename T> + PROTOBUF_NOINLINE T* mutable_unknown_fields_slow() { + Arena* my_arena = arena(); + Container<T>* container = Arena::Create<Container<T>>(my_arena); + intptr_t message_owned_arena_tag = ptr_ & kMessageOwnedArenaTagMask; + // Two-step assignment works around a bug in clang's static analyzer: + // https://bugs.llvm.org/show_bug.cgi?id=34198. + ptr_ = reinterpret_cast<intptr_t>(container); + ptr_ |= kUnknownFieldsTagMask | message_owned_arena_tag; + container->arena = my_arena; + return &(container->unknown_fields); + } + + // Templated functions. + + template <typename T> + PROTOBUF_NOINLINE void DoClear() { + mutable_unknown_fields<T>()->Clear(); + } + + template <typename T> + PROTOBUF_NOINLINE void DoMergeFrom(const T& other) { + mutable_unknown_fields<T>()->MergeFrom(other); + } + + template <typename T> + PROTOBUF_NOINLINE void DoSwap(T* other) { + mutable_unknown_fields<T>()->Swap(other); + } + + // Private helper with debug checks for ~InternalMetadata() + void CheckedDestruct(); +}; + +// String Template specializations. + +template <> +PROTOBUF_EXPORT void InternalMetadata::DoClear<std::string>(); +template <> +PROTOBUF_EXPORT void InternalMetadata::DoMergeFrom<std::string>( + const std::string& other); +template <> +PROTOBUF_EXPORT void InternalMetadata::DoSwap<std::string>(std::string* other); + +// This helper RAII class is needed to efficiently parse unknown fields. We +// should only call mutable_unknown_fields if there are actual unknown fields. +// The obvious thing to just use a stack string and swap it at the end of +// the parse won't work, because the destructor of StringOutputStream needs to +// be called before we can modify the string (it check-fails). Using +// LiteUnknownFieldSetter setter(&_internal_metadata_); +// StringOutputStream stream(setter.buffer()); +// guarantees that the string is only swapped after stream is destroyed. +class PROTOBUF_EXPORT LiteUnknownFieldSetter { + public: + explicit LiteUnknownFieldSetter(InternalMetadata* metadata) + : metadata_(metadata) { + if (metadata->have_unknown_fields()) { + buffer_.swap(*metadata->mutable_unknown_fields<std::string>()); + } + } + ~LiteUnknownFieldSetter() { + if (!buffer_.empty()) + metadata_->mutable_unknown_fields<std::string>()->swap(buffer_); + } + std::string* buffer() { return &buffer_; } + + private: + InternalMetadata* metadata_; + std::string buffer_; +}; + +} // namespace internal +} // namespace protobuf +} // namespace google + +#include <google/protobuf/port_undef.inc> + +#endif // GOOGLE_PROTOBUF_METADATA_LITE_H__ diff --git a/toolkit/components/protobuf/src/google/protobuf/package_info.h b/toolkit/components/protobuf/src/google/protobuf/package_info.h new file mode 100644 index 0000000000..2b61679af5 --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/package_info.h @@ -0,0 +1,66 @@ +// 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. + +// Author: kenton@google.com (Kenton Varda) +// Based on original Protocol Buffers design by +// Sanjay Ghemawat, Jeff Dean, and others. +// +// This file exists solely to document the google::protobuf namespace. +// It is not compiled into anything, but it may be read by an automated +// documentation generator. + +// Core components of the Protocol Buffers runtime library. +// +// The files in this package represent the core of the Protocol Buffer +// system. All of them are part of the libprotobuf library. +// +// A note on thread-safety: +// +// Thread-safety in the Protocol Buffer library follows a simple rule: +// unless explicitly noted otherwise, it is always safe to use an object +// from multiple threads simultaneously as long as the object is declared +// const in all threads (or, it is only used in ways that would be allowed +// if it were declared const). However, if an object is accessed in one +// thread in a way that would not be allowed if it were const, then it is +// not safe to access that object in any other thread simultaneously. +// +// Put simply, read-only access to an object can happen in multiple threads +// simultaneously, but write access can only happen in a single thread at +// a time. +// +// The implementation does contain some "const" methods which actually modify +// the object behind the scenes -- e.g., to cache results -- but in these cases +// mutex locking is used to make the access thread-safe. +namespace google { +namespace protobuf { +// TODO(gerbens) remove this comment, we need it to prevent clang-format +// from combining the brackets. Which would mess with extract script +} // namespace protobuf +} // namespace google diff --git a/toolkit/components/protobuf/src/google/protobuf/parse_context.cc b/toolkit/components/protobuf/src/google/protobuf/parse_context.cc new file mode 100644 index 0000000000..59852fdb7f --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/parse_context.cc @@ -0,0 +1,548 @@ +// 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. + +#include <google/protobuf/parse_context.h> + +#include <google/protobuf/io/coded_stream.h> +#include <google/protobuf/io/zero_copy_stream.h> +#include <google/protobuf/arenastring.h> +#include <google/protobuf/endian.h> +#include <google/protobuf/message_lite.h> +#include <google/protobuf/repeated_field.h> +#include <google/protobuf/stubs/strutil.h> +#include <google/protobuf/wire_format_lite.h> + +// Must be included last. +#include <google/protobuf/port_def.inc> + +namespace google { +namespace protobuf { +namespace internal { + +namespace { + +// Only call if at start of tag. +bool ParseEndsInSlopRegion(const char* begin, int overrun, int depth) { + constexpr int kSlopBytes = EpsCopyInputStream::kSlopBytes; + GOOGLE_DCHECK_GE(overrun, 0); + GOOGLE_DCHECK_LE(overrun, kSlopBytes); + auto ptr = begin + overrun; + auto end = begin + kSlopBytes; + while (ptr < end) { + uint32_t tag; + ptr = ReadTag(ptr, &tag); + if (ptr == nullptr || ptr > end) return false; + // ending on 0 tag is allowed and is the major reason for the necessity of + // this function. + if (tag == 0) return true; + switch (tag & 7) { + case 0: { // Varint + uint64_t val; + ptr = VarintParse(ptr, &val); + if (ptr == nullptr) return false; + break; + } + case 1: { // fixed64 + ptr += 8; + break; + } + case 2: { // len delim + int32_t size = ReadSize(&ptr); + if (ptr == nullptr || size > end - ptr) return false; + ptr += size; + break; + } + case 3: { // start group + depth++; + break; + } + case 4: { // end group + if (--depth < 0) return true; // We exit early + break; + } + case 5: { // fixed32 + ptr += 4; + break; + } + default: + return false; // Unknown wireformat + } + } + return false; +} + +} // namespace + +const char* EpsCopyInputStream::NextBuffer(int overrun, int depth) { + if (next_chunk_ == nullptr) return nullptr; // We've reached end of stream. + if (next_chunk_ != buffer_) { + GOOGLE_DCHECK(size_ > kSlopBytes); + // The chunk is large enough to be used directly + buffer_end_ = next_chunk_ + size_ - kSlopBytes; + auto res = next_chunk_; + next_chunk_ = buffer_; + if (aliasing_ == kOnPatch) aliasing_ = kNoDelta; + return res; + } + // Move the slop bytes of previous buffer to start of the patch buffer. + // Note we must use memmove because the previous buffer could be part of + // buffer_. + std::memmove(buffer_, buffer_end_, kSlopBytes); + if (overall_limit_ > 0 && + (depth < 0 || !ParseEndsInSlopRegion(buffer_, overrun, depth))) { + const void* data; + // ZeroCopyInputStream indicates Next may return 0 size buffers. Hence + // we loop. + while (StreamNext(&data)) { + if (size_ > kSlopBytes) { + // We got a large chunk + std::memcpy(buffer_ + kSlopBytes, data, kSlopBytes); + next_chunk_ = static_cast<const char*>(data); + buffer_end_ = buffer_ + kSlopBytes; + if (aliasing_ >= kNoDelta) aliasing_ = kOnPatch; + return buffer_; + } else if (size_ > 0) { + std::memcpy(buffer_ + kSlopBytes, data, size_); + next_chunk_ = buffer_; + buffer_end_ = buffer_ + size_; + if (aliasing_ >= kNoDelta) aliasing_ = kOnPatch; + return buffer_; + } + GOOGLE_DCHECK(size_ == 0) << size_; + } + overall_limit_ = 0; // Next failed, no more needs for next + } + // End of stream or array + if (aliasing_ == kNoDelta) { + // If there is no more block and aliasing is true, the previous block + // is still valid and we can alias. We have users relying on string_view's + // obtained from protos to outlive the proto, when the parse was from an + // array. This guarantees string_view's are always aliased if parsed from + // an array. + aliasing_ = reinterpret_cast<std::uintptr_t>(buffer_end_) - + reinterpret_cast<std::uintptr_t>(buffer_); + } + next_chunk_ = nullptr; + buffer_end_ = buffer_ + kSlopBytes; + size_ = 0; + return buffer_; +} + +const char* EpsCopyInputStream::Next() { + GOOGLE_DCHECK(limit_ > kSlopBytes); + auto p = NextBuffer(0 /* immaterial */, -1); + if (p == nullptr) { + limit_end_ = buffer_end_; + // Distinguish ending on a pushed limit or ending on end-of-stream. + SetEndOfStream(); + return nullptr; + } + limit_ -= buffer_end_ - p; // Adjust limit_ relative to new anchor + limit_end_ = buffer_end_ + std::min(0, limit_); + return p; +} + +std::pair<const char*, bool> EpsCopyInputStream::DoneFallback(int overrun, + int depth) { + // Did we exceeded the limit (parse error). + if (PROTOBUF_PREDICT_FALSE(overrun > limit_)) return {nullptr, true}; + GOOGLE_DCHECK(overrun != limit_); // Guaranteed by caller. + GOOGLE_DCHECK(overrun < limit_); // Follows from above + // TODO(gerbens) Instead of this dcheck we could just assign, and remove + // updating the limit_end from PopLimit, ie. + // limit_end_ = buffer_end_ + (std::min)(0, limit_); + // if (ptr < limit_end_) return {ptr, false}; + GOOGLE_DCHECK(limit_end_ == buffer_end_ + (std::min)(0, limit_)); + // At this point we know the following assertion holds. + GOOGLE_DCHECK_GT(limit_, 0); + GOOGLE_DCHECK(limit_end_ == buffer_end_); // because limit_ > 0 + const char* p; + do { + // We are past the end of buffer_end_, in the slop region. + GOOGLE_DCHECK_GE(overrun, 0); + p = NextBuffer(overrun, depth); + if (p == nullptr) { + // We are at the end of the stream + if (PROTOBUF_PREDICT_FALSE(overrun != 0)) return {nullptr, true}; + GOOGLE_DCHECK_GT(limit_, 0); + limit_end_ = buffer_end_; + // Distinguish ending on a pushed limit or ending on end-of-stream. + SetEndOfStream(); + return {buffer_end_, true}; + } + limit_ -= buffer_end_ - p; // Adjust limit_ relative to new anchor + p += overrun; + overrun = p - buffer_end_; + } while (overrun >= 0); + limit_end_ = buffer_end_ + std::min(0, limit_); + return {p, false}; +} + +const char* EpsCopyInputStream::SkipFallback(const char* ptr, int size) { + return AppendSize(ptr, size, [](const char* /*p*/, int /*s*/) {}); +} + +const char* EpsCopyInputStream::ReadStringFallback(const char* ptr, int size, + std::string* str) { + str->clear(); + if (PROTOBUF_PREDICT_TRUE(size <= buffer_end_ - ptr + limit_)) { + // Reserve the string up to a static safe size. If strings are bigger than + // this we proceed by growing the string as needed. This protects against + // malicious payloads making protobuf hold on to a lot of memory. + str->reserve(str->size() + std::min<int>(size, kSafeStringSize)); + } + return AppendSize(ptr, size, + [str](const char* p, int s) { str->append(p, s); }); +} + +const char* EpsCopyInputStream::AppendStringFallback(const char* ptr, int size, + std::string* str) { + if (PROTOBUF_PREDICT_TRUE(size <= buffer_end_ - ptr + limit_)) { + // Reserve the string up to a static safe size. If strings are bigger than + // this we proceed by growing the string as needed. This protects against + // malicious payloads making protobuf hold on to a lot of memory. + str->reserve(str->size() + std::min<int>(size, kSafeStringSize)); + } + return AppendSize(ptr, size, + [str](const char* p, int s) { str->append(p, s); }); +} + + +const char* EpsCopyInputStream::InitFrom(io::ZeroCopyInputStream* zcis) { + zcis_ = zcis; + const void* data; + int size; + limit_ = INT_MAX; + if (zcis->Next(&data, &size)) { + overall_limit_ -= size; + if (size > kSlopBytes) { + auto ptr = static_cast<const char*>(data); + limit_ -= size - kSlopBytes; + limit_end_ = buffer_end_ = ptr + size - kSlopBytes; + next_chunk_ = buffer_; + if (aliasing_ == kOnPatch) aliasing_ = kNoDelta; + return ptr; + } else { + limit_end_ = buffer_end_ = buffer_ + kSlopBytes; + next_chunk_ = buffer_; + auto ptr = buffer_ + 2 * kSlopBytes - size; + std::memcpy(ptr, data, size); + return ptr; + } + } + overall_limit_ = 0; + next_chunk_ = nullptr; + size_ = 0; + limit_end_ = buffer_end_ = buffer_; + return buffer_; +} + +const char* ParseContext::ReadSizeAndPushLimitAndDepth(const char* ptr, + int* old_limit) { + int size = ReadSize(&ptr); + if (PROTOBUF_PREDICT_FALSE(!ptr)) { + *old_limit = 0; // Make sure this isn't uninitialized even on error return + return nullptr; + } + *old_limit = PushLimit(ptr, size); + if (--depth_ < 0) return nullptr; + return ptr; +} + +const char* ParseContext::ParseMessage(MessageLite* msg, const char* ptr) { + int old; + ptr = ReadSizeAndPushLimitAndDepth(ptr, &old); + ptr = ptr ? msg->_InternalParse(ptr, this) : nullptr; + depth_++; + if (!PopLimit(old)) return nullptr; + return ptr; +} + +inline void WriteVarint(uint64_t val, std::string* s) { + while (val >= 128) { + uint8_t c = val | 0x80; + s->push_back(c); + val >>= 7; + } + s->push_back(val); +} + +void WriteVarint(uint32_t num, uint64_t val, std::string* s) { + WriteVarint(num << 3, s); + WriteVarint(val, s); +} + +void WriteLengthDelimited(uint32_t num, StringPiece val, std::string* s) { + WriteVarint((num << 3) + 2, s); + WriteVarint(val.size(), s); + s->append(val.data(), val.size()); +} + +std::pair<const char*, uint32_t> VarintParseSlow32(const char* p, + uint32_t res) { + for (std::uint32_t i = 2; i < 5; i++) { + uint32_t byte = static_cast<uint8_t>(p[i]); + res += (byte - 1) << (7 * i); + if (PROTOBUF_PREDICT_TRUE(byte < 128)) { + return {p + i + 1, res}; + } + } + // Accept >5 bytes + for (std::uint32_t i = 5; i < 10; i++) { + uint32_t byte = static_cast<uint8_t>(p[i]); + if (PROTOBUF_PREDICT_TRUE(byte < 128)) { + return {p + i + 1, res}; + } + } + return {nullptr, 0}; +} + +std::pair<const char*, uint64_t> VarintParseSlow64(const char* p, + uint32_t res32) { + uint64_t res = res32; + for (std::uint32_t i = 2; i < 10; i++) { + uint64_t byte = static_cast<uint8_t>(p[i]); + res += (byte - 1) << (7 * i); + if (PROTOBUF_PREDICT_TRUE(byte < 128)) { + return {p + i + 1, res}; + } + } + return {nullptr, 0}; +} + +std::pair<const char*, uint32_t> ReadTagFallback(const char* p, uint32_t res) { + for (std::uint32_t i = 2; i < 5; i++) { + uint32_t byte = static_cast<uint8_t>(p[i]); + res += (byte - 1) << (7 * i); + if (PROTOBUF_PREDICT_TRUE(byte < 128)) { + return {p + i + 1, res}; + } + } + return {nullptr, 0}; +} + +std::pair<const char*, int32_t> ReadSizeFallback(const char* p, uint32_t res) { + for (std::uint32_t i = 1; i < 4; i++) { + uint32_t byte = static_cast<uint8_t>(p[i]); + res += (byte - 1) << (7 * i); + if (PROTOBUF_PREDICT_TRUE(byte < 128)) { + return {p + i + 1, res}; + } + } + std::uint32_t byte = static_cast<uint8_t>(p[4]); + if (PROTOBUF_PREDICT_FALSE(byte >= 8)) return {nullptr, 0}; // size >= 2gb + res += (byte - 1) << 28; + // Protect against sign integer overflow in PushLimit. Limits are relative + // to buffer ends and ptr could potential be kSlopBytes beyond a buffer end. + // To protect against overflow we reject limits absurdly close to INT_MAX. + if (PROTOBUF_PREDICT_FALSE(res > INT_MAX - ParseContext::kSlopBytes)) { + return {nullptr, 0}; + } + return {p + 5, res}; +} + +const char* StringParser(const char* begin, const char* end, void* object, + ParseContext*) { + auto str = static_cast<std::string*>(object); + str->append(begin, end - begin); + return end; +} + +// Defined in wire_format_lite.cc +void PrintUTF8ErrorLog(StringPiece message_name, + StringPiece field_name, const char* operation_str, + bool emit_stacktrace); + +bool VerifyUTF8(StringPiece str, const char* field_name) { + if (!IsStructurallyValidUTF8(str)) { + PrintUTF8ErrorLog("", field_name, "parsing", false); + return false; + } + return true; +} + +const char* InlineGreedyStringParser(std::string* s, const char* ptr, + ParseContext* ctx) { + int size = ReadSize(&ptr); + if (!ptr) return nullptr; + return ctx->ReadString(ptr, size, s); +} + + +template <typename T, bool sign> +const char* VarintParser(void* object, const char* ptr, ParseContext* ctx) { + return ctx->ReadPackedVarint(ptr, [object](uint64_t varint) { + T val; + if (sign) { + if (sizeof(T) == 8) { + val = WireFormatLite::ZigZagDecode64(varint); + } else { + val = WireFormatLite::ZigZagDecode32(varint); + } + } else { + val = varint; + } + static_cast<RepeatedField<T>*>(object)->Add(val); + }); +} + +const char* PackedInt32Parser(void* object, const char* ptr, + ParseContext* ctx) { + return VarintParser<int32_t, false>(object, ptr, ctx); +} +const char* PackedUInt32Parser(void* object, const char* ptr, + ParseContext* ctx) { + return VarintParser<uint32_t, false>(object, ptr, ctx); +} +const char* PackedInt64Parser(void* object, const char* ptr, + ParseContext* ctx) { + return VarintParser<int64_t, false>(object, ptr, ctx); +} +const char* PackedUInt64Parser(void* object, const char* ptr, + ParseContext* ctx) { + return VarintParser<uint64_t, false>(object, ptr, ctx); +} +const char* PackedSInt32Parser(void* object, const char* ptr, + ParseContext* ctx) { + return VarintParser<int32_t, true>(object, ptr, ctx); +} +const char* PackedSInt64Parser(void* object, const char* ptr, + ParseContext* ctx) { + return VarintParser<int64_t, true>(object, ptr, ctx); +} + +const char* PackedEnumParser(void* object, const char* ptr, ParseContext* ctx) { + return VarintParser<int, false>(object, ptr, ctx); +} + +const char* PackedBoolParser(void* object, const char* ptr, ParseContext* ctx) { + return VarintParser<bool, false>(object, ptr, ctx); +} + +template <typename T> +const char* FixedParser(void* object, const char* ptr, ParseContext* ctx) { + int size = ReadSize(&ptr); + return ctx->ReadPackedFixed(ptr, size, + static_cast<RepeatedField<T>*>(object)); +} + +const char* PackedFixed32Parser(void* object, const char* ptr, + ParseContext* ctx) { + return FixedParser<uint32_t>(object, ptr, ctx); +} +const char* PackedSFixed32Parser(void* object, const char* ptr, + ParseContext* ctx) { + return FixedParser<int32_t>(object, ptr, ctx); +} +const char* PackedFixed64Parser(void* object, const char* ptr, + ParseContext* ctx) { + return FixedParser<uint64_t>(object, ptr, ctx); +} +const char* PackedSFixed64Parser(void* object, const char* ptr, + ParseContext* ctx) { + return FixedParser<int64_t>(object, ptr, ctx); +} +const char* PackedFloatParser(void* object, const char* ptr, + ParseContext* ctx) { + return FixedParser<float>(object, ptr, ctx); +} +const char* PackedDoubleParser(void* object, const char* ptr, + ParseContext* ctx) { + return FixedParser<double>(object, ptr, ctx); +} + +class UnknownFieldLiteParserHelper { + public: + explicit UnknownFieldLiteParserHelper(std::string* unknown) + : unknown_(unknown) {} + + void AddVarint(uint32_t num, uint64_t value) { + if (unknown_ == nullptr) return; + WriteVarint(num * 8, unknown_); + WriteVarint(value, unknown_); + } + void AddFixed64(uint32_t num, uint64_t value) { + if (unknown_ == nullptr) return; + WriteVarint(num * 8 + 1, unknown_); + char buffer[8]; + io::CodedOutputStream::WriteLittleEndian64ToArray( + value, reinterpret_cast<uint8_t*>(buffer)); + unknown_->append(buffer, 8); + } + const char* ParseLengthDelimited(uint32_t num, const char* ptr, + ParseContext* ctx) { + int size = ReadSize(&ptr); + GOOGLE_PROTOBUF_PARSER_ASSERT(ptr); + if (unknown_ == nullptr) return ctx->Skip(ptr, size); + WriteVarint(num * 8 + 2, unknown_); + WriteVarint(size, unknown_); + return ctx->AppendString(ptr, size, unknown_); + } + const char* ParseGroup(uint32_t num, const char* ptr, ParseContext* ctx) { + if (unknown_) WriteVarint(num * 8 + 3, unknown_); + ptr = ctx->ParseGroup(this, ptr, num * 8 + 3); + GOOGLE_PROTOBUF_PARSER_ASSERT(ptr); + if (unknown_) WriteVarint(num * 8 + 4, unknown_); + return ptr; + } + void AddFixed32(uint32_t num, uint32_t value) { + if (unknown_ == nullptr) return; + WriteVarint(num * 8 + 5, unknown_); + char buffer[4]; + io::CodedOutputStream::WriteLittleEndian32ToArray( + value, reinterpret_cast<uint8_t*>(buffer)); + unknown_->append(buffer, 4); + } + + const char* _InternalParse(const char* ptr, ParseContext* ctx) { + return WireFormatParser(*this, ptr, ctx); + } + + private: + std::string* unknown_; +}; + +const char* UnknownGroupLiteParse(std::string* unknown, const char* ptr, + ParseContext* ctx) { + UnknownFieldLiteParserHelper field_parser(unknown); + return WireFormatParser(field_parser, ptr, ctx); +} + +const char* UnknownFieldParse(uint32_t tag, std::string* unknown, + const char* ptr, ParseContext* ctx) { + UnknownFieldLiteParserHelper field_parser(unknown); + return FieldParser(tag, field_parser, ptr, ctx); +} + +} // namespace internal +} // namespace protobuf +} // namespace google + +#include <google/protobuf/port_undef.inc> diff --git a/toolkit/components/protobuf/src/google/protobuf/parse_context.h b/toolkit/components/protobuf/src/google/protobuf/parse_context.h new file mode 100644 index 0000000000..7aea50cdc3 --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/parse_context.h @@ -0,0 +1,1025 @@ +// 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. + +#ifndef GOOGLE_PROTOBUF_PARSE_CONTEXT_H__ +#define GOOGLE_PROTOBUF_PARSE_CONTEXT_H__ + +#include <cstdint> +#include <cstring> +#include <string> +#include <type_traits> + +#include <google/protobuf/io/coded_stream.h> +#include <google/protobuf/io/zero_copy_stream.h> +#include <google/protobuf/arena.h> +#include <google/protobuf/port.h> +#include <google/protobuf/stubs/strutil.h> +#include <google/protobuf/arenastring.h> +#include <google/protobuf/endian.h> +#include <google/protobuf/implicit_weak_message.h> +#include <google/protobuf/inlined_string_field.h> +#include <google/protobuf/metadata_lite.h> +#include <google/protobuf/repeated_field.h> +#include <google/protobuf/wire_format_lite.h> + +// Must be included last. +#include <google/protobuf/port_def.inc> + + +namespace google { +namespace protobuf { + +class UnknownFieldSet; +class DescriptorPool; +class MessageFactory; + +namespace internal { + +// Template code below needs to know about the existence of these functions. +PROTOBUF_EXPORT void WriteVarint(uint32_t num, uint64_t val, std::string* s); +PROTOBUF_EXPORT void WriteLengthDelimited(uint32_t num, StringPiece val, + std::string* s); +// Inline because it is just forwarding to s->WriteVarint +inline void WriteVarint(uint32_t num, uint64_t val, UnknownFieldSet* s); +inline void WriteLengthDelimited(uint32_t num, StringPiece val, + UnknownFieldSet* s); + + +// The basic abstraction the parser is designed for is a slight modification +// of the ZeroCopyInputStream (ZCIS) abstraction. A ZCIS presents a serialized +// stream as a series of buffers that concatenate to the full stream. +// Pictorially a ZCIS presents a stream in chunks like so +// [---------------------------------------------------------------] +// [---------------------] chunk 1 +// [----------------------------] chunk 2 +// chunk 3 [--------------] +// +// Where the '-' represent the bytes which are vertically lined up with the +// bytes of the stream. The proto parser requires its input to be presented +// similarly with the extra +// property that each chunk has kSlopBytes past its end that overlaps with the +// first kSlopBytes of the next chunk, or if there is no next chunk at least its +// still valid to read those bytes. Again, pictorially, we now have +// +// [---------------------------------------------------------------] +// [-------------------....] chunk 1 +// [------------------------....] chunk 2 +// chunk 3 [------------------..**] +// chunk 4 [--****] +// Here '-' mean the bytes of the stream or chunk and '.' means bytes past the +// chunk that match up with the start of the next chunk. Above each chunk has +// 4 '.' after the chunk. In the case these 'overflow' bytes represents bytes +// past the stream, indicated by '*' above, their values are unspecified. It is +// still legal to read them (ie. should not segfault). Reading past the +// end should be detected by the user and indicated as an error. +// +// The reason for this, admittedly, unconventional invariant is to ruthlessly +// optimize the protobuf parser. Having an overlap helps in two important ways. +// Firstly it alleviates having to performing bounds checks if a piece of code +// is guaranteed to not read more than kSlopBytes. Secondly, and more +// importantly, the protobuf wireformat is such that reading a key/value pair is +// always less than 16 bytes. This removes the need to change to next buffer in +// the middle of reading primitive values. Hence there is no need to store and +// load the current position. + +class PROTOBUF_EXPORT EpsCopyInputStream { + public: + enum { kSlopBytes = 16, kMaxCordBytesToCopy = 512 }; + + explicit EpsCopyInputStream(bool enable_aliasing) + : aliasing_(enable_aliasing ? kOnPatch : kNoAliasing) {} + + void BackUp(const char* ptr) { + GOOGLE_DCHECK(ptr <= buffer_end_ + kSlopBytes); + int count; + if (next_chunk_ == buffer_) { + count = static_cast<int>(buffer_end_ + kSlopBytes - ptr); + } else { + count = size_ + static_cast<int>(buffer_end_ - ptr); + } + if (count > 0) StreamBackUp(count); + } + + // If return value is negative it's an error + PROTOBUF_NODISCARD int PushLimit(const char* ptr, int limit) { + GOOGLE_DCHECK(limit >= 0 && limit <= INT_MAX - kSlopBytes); + // This add is safe due to the invariant above, because + // ptr - buffer_end_ <= kSlopBytes. + limit += static_cast<int>(ptr - buffer_end_); + limit_end_ = buffer_end_ + (std::min)(0, limit); + auto old_limit = limit_; + limit_ = limit; + return old_limit - limit; + } + + PROTOBUF_NODISCARD bool PopLimit(int delta) { + if (PROTOBUF_PREDICT_FALSE(!EndedAtLimit())) return false; + limit_ = limit_ + delta; + // TODO(gerbens) We could remove this line and hoist the code to + // DoneFallback. Study the perf/bin-size effects. + limit_end_ = buffer_end_ + (std::min)(0, limit_); + return true; + } + + PROTOBUF_NODISCARD const char* Skip(const char* ptr, int size) { + if (size <= buffer_end_ + kSlopBytes - ptr) { + return ptr + size; + } + return SkipFallback(ptr, size); + } + PROTOBUF_NODISCARD const char* ReadString(const char* ptr, int size, + std::string* s) { + if (size <= buffer_end_ + kSlopBytes - ptr) { + s->assign(ptr, size); + return ptr + size; + } + return ReadStringFallback(ptr, size, s); + } + PROTOBUF_NODISCARD const char* AppendString(const char* ptr, int size, + std::string* s) { + if (size <= buffer_end_ + kSlopBytes - ptr) { + s->append(ptr, size); + return ptr + size; + } + return AppendStringFallback(ptr, size, s); + } + // Implemented in arenastring.cc + PROTOBUF_NODISCARD const char* ReadArenaString(const char* ptr, + ArenaStringPtr* s, + Arena* arena); + + template <typename Tag, typename T> + PROTOBUF_NODISCARD const char* ReadRepeatedFixed(const char* ptr, + Tag expected_tag, + RepeatedField<T>* out); + + template <typename T> + PROTOBUF_NODISCARD const char* ReadPackedFixed(const char* ptr, int size, + RepeatedField<T>* out); + template <typename Add> + PROTOBUF_NODISCARD const char* ReadPackedVarint(const char* ptr, Add add); + + uint32_t LastTag() const { return last_tag_minus_1_ + 1; } + bool ConsumeEndGroup(uint32_t start_tag) { + bool res = last_tag_minus_1_ == start_tag; + last_tag_minus_1_ = 0; + return res; + } + bool EndedAtLimit() const { return last_tag_minus_1_ == 0; } + bool EndedAtEndOfStream() const { return last_tag_minus_1_ == 1; } + void SetLastTag(uint32_t tag) { last_tag_minus_1_ = tag - 1; } + void SetEndOfStream() { last_tag_minus_1_ = 1; } + bool IsExceedingLimit(const char* ptr) { + return ptr > limit_end_ && + (next_chunk_ == nullptr || ptr - buffer_end_ > limit_); + } + bool AliasingEnabled() const { return aliasing_ != kNoAliasing; } + int BytesUntilLimit(const char* ptr) const { + return limit_ + static_cast<int>(buffer_end_ - ptr); + } + // Returns true if more data is available, if false is returned one has to + // call Done for further checks. + bool DataAvailable(const char* ptr) { return ptr < limit_end_; } + + protected: + // Returns true is limit (either an explicit limit or end of stream) is + // reached. It aligns *ptr across buffer seams. + // If limit is exceeded it returns true and ptr is set to null. + bool DoneWithCheck(const char** ptr, int d) { + GOOGLE_DCHECK(*ptr); + if (PROTOBUF_PREDICT_TRUE(*ptr < limit_end_)) return false; + int overrun = static_cast<int>(*ptr - buffer_end_); + GOOGLE_DCHECK_LE(overrun, kSlopBytes); // Guaranteed by parse loop. + if (overrun == + limit_) { // No need to flip buffers if we ended on a limit. + // If we actually overrun the buffer and next_chunk_ is null. It means + // the stream ended and we passed the stream end. + if (overrun > 0 && next_chunk_ == nullptr) *ptr = nullptr; + return true; + } + auto res = DoneFallback(overrun, d); + *ptr = res.first; + return res.second; + } + + const char* InitFrom(StringPiece flat) { + overall_limit_ = 0; + if (flat.size() > kSlopBytes) { + limit_ = kSlopBytes; + limit_end_ = buffer_end_ = flat.data() + flat.size() - kSlopBytes; + next_chunk_ = buffer_; + if (aliasing_ == kOnPatch) aliasing_ = kNoDelta; + return flat.data(); + } else { + std::memcpy(buffer_, flat.data(), flat.size()); + limit_ = 0; + limit_end_ = buffer_end_ = buffer_ + flat.size(); + next_chunk_ = nullptr; + if (aliasing_ == kOnPatch) { + aliasing_ = reinterpret_cast<std::uintptr_t>(flat.data()) - + reinterpret_cast<std::uintptr_t>(buffer_); + } + return buffer_; + } + } + + const char* InitFrom(io::ZeroCopyInputStream* zcis); + + const char* InitFrom(io::ZeroCopyInputStream* zcis, int limit) { + if (limit == -1) return InitFrom(zcis); + overall_limit_ = limit; + auto res = InitFrom(zcis); + limit_ = limit - static_cast<int>(buffer_end_ - res); + limit_end_ = buffer_end_ + (std::min)(0, limit_); + return res; + } + + private: + const char* limit_end_; // buffer_end_ + min(limit_, 0) + const char* buffer_end_; + const char* next_chunk_; + int size_; + int limit_; // relative to buffer_end_; + io::ZeroCopyInputStream* zcis_ = nullptr; + char buffer_[2 * kSlopBytes] = {}; + enum { kNoAliasing = 0, kOnPatch = 1, kNoDelta = 2 }; + std::uintptr_t aliasing_ = kNoAliasing; + // This variable is used to communicate how the parse ended, in order to + // completely verify the parsed data. A wire-format parse can end because of + // one of the following conditions: + // 1) A parse can end on a pushed limit. + // 2) A parse can end on End Of Stream (EOS). + // 3) A parse can end on 0 tag (only valid for toplevel message). + // 4) A parse can end on an end-group tag. + // This variable should always be set to 0, which indicates case 1. If the + // parse terminated due to EOS (case 2), it's set to 1. In case the parse + // ended due to a terminating tag (case 3 and 4) it's set to (tag - 1). + // This var doesn't really belong in EpsCopyInputStream and should be part of + // the ParseContext, but case 2 is most easily and optimally implemented in + // DoneFallback. + uint32_t last_tag_minus_1_ = 0; + int overall_limit_ = INT_MAX; // Overall limit independent of pushed limits. + // Pretty random large number that seems like a safe allocation on most + // systems. TODO(gerbens) do we need to set this as build flag? + enum { kSafeStringSize = 50000000 }; + + // Advances to next buffer chunk returns a pointer to the same logical place + // in the stream as set by overrun. Overrun indicates the position in the slop + // region the parse was left (0 <= overrun <= kSlopBytes). Returns true if at + // limit, at which point the returned pointer maybe null if there was an + // error. The invariant of this function is that it's guaranteed that + // kSlopBytes bytes can be accessed from the returned ptr. This function might + // advance more buffers than one in the underlying ZeroCopyInputStream. + std::pair<const char*, bool> DoneFallback(int overrun, int depth); + // Advances to the next buffer, at most one call to Next() on the underlying + // ZeroCopyInputStream is made. This function DOES NOT match the returned + // pointer to where in the slop region the parse ends, hence no overrun + // parameter. This is useful for string operations where you always copy + // to the end of the buffer (including the slop region). + const char* Next(); + // overrun is the location in the slop region the stream currently is + // (0 <= overrun <= kSlopBytes). To prevent flipping to the next buffer of + // the ZeroCopyInputStream in the case the parse will end in the last + // kSlopBytes of the current buffer. depth is the current depth of nested + // groups (or negative if the use case does not need careful tracking). + inline const char* NextBuffer(int overrun, int depth); + const char* SkipFallback(const char* ptr, int size); + const char* AppendStringFallback(const char* ptr, int size, std::string* str); + const char* ReadStringFallback(const char* ptr, int size, std::string* str); + bool StreamNext(const void** data) { + bool res = zcis_->Next(data, &size_); + if (res) overall_limit_ -= size_; + return res; + } + void StreamBackUp(int count) { + zcis_->BackUp(count); + overall_limit_ += count; + } + + template <typename A> + const char* AppendSize(const char* ptr, int size, const A& append) { + int chunk_size = buffer_end_ + kSlopBytes - ptr; + do { + GOOGLE_DCHECK(size > chunk_size); + if (next_chunk_ == nullptr) return nullptr; + append(ptr, chunk_size); + ptr += chunk_size; + size -= chunk_size; + // TODO(gerbens) Next calls NextBuffer which generates buffers with + // overlap and thus incurs cost of copying the slop regions. This is not + // necessary for reading strings. We should just call Next buffers. + if (limit_ <= kSlopBytes) return nullptr; + ptr = Next(); + if (ptr == nullptr) return nullptr; // passed the limit + ptr += kSlopBytes; + chunk_size = buffer_end_ + kSlopBytes - ptr; + } while (size > chunk_size); + append(ptr, size); + return ptr + size; + } + + // AppendUntilEnd appends data until a limit (either a PushLimit or end of + // stream. Normal payloads are from length delimited fields which have an + // explicit size. Reading until limit only comes when the string takes + // the place of a protobuf, ie RawMessage/StringRawMessage, lazy fields and + // implicit weak messages. We keep these methods private and friend them. + template <typename A> + const char* AppendUntilEnd(const char* ptr, const A& append) { + if (ptr - buffer_end_ > limit_) return nullptr; + while (limit_ > kSlopBytes) { + size_t chunk_size = buffer_end_ + kSlopBytes - ptr; + append(ptr, chunk_size); + ptr = Next(); + if (ptr == nullptr) return limit_end_; + ptr += kSlopBytes; + } + auto end = buffer_end_ + limit_; + GOOGLE_DCHECK(end >= ptr); + append(ptr, end - ptr); + return end; + } + + PROTOBUF_NODISCARD const char* AppendString(const char* ptr, + std::string* str) { + return AppendUntilEnd( + ptr, [str](const char* p, ptrdiff_t s) { str->append(p, s); }); + } + friend class ImplicitWeakMessage; +}; + +using LazyEagerVerifyFnType = const char* (*)(const char* ptr, + ParseContext* ctx); +using LazyEagerVerifyFnRef = std::remove_pointer<LazyEagerVerifyFnType>::type&; + +// ParseContext holds all data that is global to the entire parse. Most +// importantly it contains the input stream, but also recursion depth and also +// stores the end group tag, in case a parser ended on a endgroup, to verify +// matching start/end group tags. +class PROTOBUF_EXPORT ParseContext : public EpsCopyInputStream { + public: + struct Data { + const DescriptorPool* pool = nullptr; + MessageFactory* factory = nullptr; + Arena* arena = nullptr; + }; + + template <typename... T> + ParseContext(int depth, bool aliasing, const char** start, T&&... args) + : EpsCopyInputStream(aliasing), depth_(depth) { + *start = InitFrom(std::forward<T>(args)...); + } + + void TrackCorrectEnding() { group_depth_ = 0; } + + bool Done(const char** ptr) { return DoneWithCheck(ptr, group_depth_); } + + int depth() const { return depth_; } + + Data& data() { return data_; } + const Data& data() const { return data_; } + + const char* ParseMessage(MessageLite* msg, const char* ptr); + + // Spawns a child parsing context that inherits key properties. New context + // inherits the following: + // --depth_, data_, check_required_fields_, lazy_parse_mode_ + // The spawned context always disables aliasing (different input). + template <typename... T> + ParseContext Spawn(const char** start, T&&... args) { + ParseContext spawned(depth_, false, start, std::forward<T>(args)...); + // Transfer key context states. + spawned.data_ = data_; + return spawned; + } + + // This overload supports those few cases where ParseMessage is called + // on a class that is not actually a proto message. + // TODO(jorg): Eliminate this use case. + template <typename T, + typename std::enable_if<!std::is_base_of<MessageLite, T>::value, + bool>::type = true> + PROTOBUF_NODISCARD const char* ParseMessage(T* msg, const char* ptr); + + template <typename T> + PROTOBUF_NODISCARD PROTOBUF_NDEBUG_INLINE const char* ParseGroup( + T* msg, const char* ptr, uint32_t tag) { + if (--depth_ < 0) return nullptr; + group_depth_++; + ptr = msg->_InternalParse(ptr, this); + group_depth_--; + depth_++; + if (PROTOBUF_PREDICT_FALSE(!ConsumeEndGroup(tag))) return nullptr; + return ptr; + } + + private: + // Out-of-line routine to save space in ParseContext::ParseMessage<T> + // int old; + // ptr = ReadSizeAndPushLimitAndDepth(ptr, &old) + // is equivalent to: + // int size = ReadSize(&ptr); + // if (!ptr) return nullptr; + // int old = PushLimit(ptr, size); + // if (--depth_ < 0) return nullptr; + PROTOBUF_NODISCARD const char* ReadSizeAndPushLimitAndDepth(const char* ptr, + int* old_limit); + + // The context keeps an internal stack to keep track of the recursive + // part of the parse state. + // Current depth of the active parser, depth counts down. + // This is used to limit recursion depth (to prevent overflow on malicious + // data), but is also used to index in stack_ to store the current state. + int depth_; + // Unfortunately necessary for the fringe case of ending on 0 or end-group tag + // in the last kSlopBytes of a ZeroCopyInputStream chunk. + int group_depth_ = INT_MIN; + Data data_; +}; + +template <uint32_t tag> +bool ExpectTag(const char* ptr) { + if (tag < 128) { + return *ptr == static_cast<char>(tag); + } else { + static_assert(tag < 128 * 128, "We only expect tags for 1 or 2 bytes"); + char buf[2] = {static_cast<char>(tag | 0x80), static_cast<char>(tag >> 7)}; + return std::memcmp(ptr, buf, 2) == 0; + } +} + +template <int> +struct EndianHelper; + +template <> +struct EndianHelper<1> { + static uint8_t Load(const void* p) { return *static_cast<const uint8_t*>(p); } +}; + +template <> +struct EndianHelper<2> { + static uint16_t Load(const void* p) { + uint16_t tmp; + std::memcpy(&tmp, p, 2); + return little_endian::ToHost(tmp); + } +}; + +template <> +struct EndianHelper<4> { + static uint32_t Load(const void* p) { + uint32_t tmp; + std::memcpy(&tmp, p, 4); + return little_endian::ToHost(tmp); + } +}; + +template <> +struct EndianHelper<8> { + static uint64_t Load(const void* p) { + uint64_t tmp; + std::memcpy(&tmp, p, 8); + return little_endian::ToHost(tmp); + } +}; + +template <typename T> +T UnalignedLoad(const char* p) { + auto tmp = EndianHelper<sizeof(T)>::Load(p); + T res; + memcpy(&res, &tmp, sizeof(T)); + return res; +} + +PROTOBUF_EXPORT +std::pair<const char*, uint32_t> VarintParseSlow32(const char* p, uint32_t res); +PROTOBUF_EXPORT +std::pair<const char*, uint64_t> VarintParseSlow64(const char* p, uint32_t res); + +inline const char* VarintParseSlow(const char* p, uint32_t res, uint32_t* out) { + auto tmp = VarintParseSlow32(p, res); + *out = tmp.second; + return tmp.first; +} + +inline const char* VarintParseSlow(const char* p, uint32_t res, uint64_t* out) { + auto tmp = VarintParseSlow64(p, res); + *out = tmp.second; + return tmp.first; +} + +template <typename T> +PROTOBUF_NODISCARD const char* VarintParse(const char* p, T* out) { + auto ptr = reinterpret_cast<const uint8_t*>(p); + uint32_t res = ptr[0]; + if (!(res & 0x80)) { + *out = res; + return p + 1; + } + uint32_t byte = ptr[1]; + res += (byte - 1) << 7; + if (!(byte & 0x80)) { + *out = res; + return p + 2; + } + return VarintParseSlow(p, res, out); +} + +// Used for tags, could read up to 5 bytes which must be available. +// Caller must ensure its safe to call. + +PROTOBUF_EXPORT +std::pair<const char*, uint32_t> ReadTagFallback(const char* p, uint32_t res); + +// Same as ParseVarint but only accept 5 bytes at most. +inline const char* ReadTag(const char* p, uint32_t* out, + uint32_t /*max_tag*/ = 0) { + uint32_t res = static_cast<uint8_t>(p[0]); + if (res < 128) { + *out = res; + return p + 1; + } + uint32_t second = static_cast<uint8_t>(p[1]); + res += (second - 1) << 7; + if (second < 128) { + *out = res; + return p + 2; + } + auto tmp = ReadTagFallback(p, res); + *out = tmp.second; + return tmp.first; +} + +// As above, but optimized to consume very few registers while still being fast, +// ReadTagInlined is useful for callers that don't mind the extra code but would +// like to avoid an extern function call causing spills into the stack. +// +// Two support routines for ReadTagInlined come first... +template <class T> +PROTOBUF_NODISCARD PROTOBUF_ALWAYS_INLINE constexpr T RotateLeft( + T x, int s) noexcept { + return static_cast<T>(x << (s & (std::numeric_limits<T>::digits - 1))) | + static_cast<T>(x >> ((-s) & (std::numeric_limits<T>::digits - 1))); +} + +PROTOBUF_NODISCARD inline PROTOBUF_ALWAYS_INLINE uint64_t +RotRight7AndReplaceLowByte(uint64_t res, const char& byte) { +#if defined(__x86_64__) && defined(__GNUC__) + // This will only use one register for `res`. + // `byte` comes as a reference to allow the compiler to generate code like: + // + // rorq $7, %rcx + // movb 1(%rax), %cl + // + // which avoids loading the incoming bytes into a separate register first. + asm("ror $7,%0\n\t" + "movb %1,%b0" + : "+r"(res) + : "m"(byte)); +#else + res = RotateLeft(res, -7); + res = res & ~0xFF; + res |= 0xFF & byte; +#endif + return res; +}; + +inline PROTOBUF_ALWAYS_INLINE +const char* ReadTagInlined(const char* ptr, uint32_t* out) { + uint64_t res = 0xFF & ptr[0]; + if (PROTOBUF_PREDICT_FALSE(res >= 128)) { + res = RotRight7AndReplaceLowByte(res, ptr[1]); + if (PROTOBUF_PREDICT_FALSE(res & 0x80)) { + res = RotRight7AndReplaceLowByte(res, ptr[2]); + if (PROTOBUF_PREDICT_FALSE(res & 0x80)) { + res = RotRight7AndReplaceLowByte(res, ptr[3]); + if (PROTOBUF_PREDICT_FALSE(res & 0x80)) { + // Note: this wouldn't work if res were 32-bit, + // because then replacing the low byte would overwrite + // the bottom 4 bits of the result. + res = RotRight7AndReplaceLowByte(res, ptr[4]); + if (PROTOBUF_PREDICT_FALSE(res & 0x80)) { + // The proto format does not permit longer than 5-byte encodings for + // tags. + *out = 0; + return nullptr; + } + *out = static_cast<uint32_t>(RotateLeft(res, 28)); +#if defined(__GNUC__) + // Note: this asm statement prevents the compiler from + // trying to share the "return ptr + constant" among all + // branches. + asm("" : "+r"(ptr)); +#endif + return ptr + 5; + } + *out = static_cast<uint32_t>(RotateLeft(res, 21)); + return ptr + 4; + } + *out = static_cast<uint32_t>(RotateLeft(res, 14)); + return ptr + 3; + } + *out = static_cast<uint32_t>(RotateLeft(res, 7)); + return ptr + 2; + } + *out = static_cast<uint32_t>(res); + return ptr + 1; +} + +// Decode 2 consecutive bytes of a varint and returns the value, shifted left +// by 1. It simultaneous updates *ptr to *ptr + 1 or *ptr + 2 depending if the +// first byte's continuation bit is set. +// If bit 15 of return value is set (equivalent to the continuation bits of both +// bytes being set) the varint continues, otherwise the parse is done. On x86 +// movsx eax, dil +// and edi, eax +// add eax, edi +// adc [rsi], 1 +inline uint32_t DecodeTwoBytes(const char** ptr) { + uint32_t value = UnalignedLoad<uint16_t>(*ptr); + // Sign extend the low byte continuation bit + uint32_t x = static_cast<int8_t>(value); + value &= x; // Mask out the high byte iff no continuation + // This add is an amazing operation, it cancels the low byte continuation bit + // from y transferring it to the carry. Simultaneously it also shifts the 7 + // LSB left by one tightly against high byte varint bits. Hence value now + // contains the unpacked value shifted left by 1. + value += x; + // Use the carry to update the ptr appropriately. + *ptr += value < x ? 2 : 1; + return value; +} + +// More efficient varint parsing for big varints +inline const char* ParseBigVarint(const char* p, uint64_t* out) { + auto pnew = p; + auto tmp = DecodeTwoBytes(&pnew); + uint64_t res = tmp >> 1; + if (PROTOBUF_PREDICT_TRUE(static_cast<std::int16_t>(tmp) >= 0)) { + *out = res; + return pnew; + } + for (std::uint32_t i = 1; i < 5; i++) { + pnew = p + 2 * i; + tmp = DecodeTwoBytes(&pnew); + res += (static_cast<std::uint64_t>(tmp) - 2) << (14 * i - 1); + if (PROTOBUF_PREDICT_TRUE(static_cast<std::int16_t>(tmp) >= 0)) { + *out = res; + return pnew; + } + } + return nullptr; +} + +PROTOBUF_EXPORT +std::pair<const char*, int32_t> ReadSizeFallback(const char* p, uint32_t first); +// Used for tags, could read up to 5 bytes which must be available. Additionally +// it makes sure the unsigned value fits a int32_t, otherwise returns nullptr. +// Caller must ensure its safe to call. +inline uint32_t ReadSize(const char** pp) { + auto p = *pp; + uint32_t res = static_cast<uint8_t>(p[0]); + if (res < 128) { + *pp = p + 1; + return res; + } + auto x = ReadSizeFallback(p, res); + *pp = x.first; + return x.second; +} + +// Some convenience functions to simplify the generated parse loop code. +// Returning the value and updating the buffer pointer allows for nicer +// function composition. We rely on the compiler to inline this. +// Also in debug compiles having local scoped variables tend to generated +// stack frames that scale as O(num fields). +inline uint64_t ReadVarint64(const char** p) { + uint64_t tmp; + *p = VarintParse(*p, &tmp); + return tmp; +} + +inline uint32_t ReadVarint32(const char** p) { + uint32_t tmp; + *p = VarintParse(*p, &tmp); + return tmp; +} + +inline int64_t ReadVarintZigZag64(const char** p) { + uint64_t tmp; + *p = VarintParse(*p, &tmp); + return WireFormatLite::ZigZagDecode64(tmp); +} + +inline int32_t ReadVarintZigZag32(const char** p) { + uint64_t tmp; + *p = VarintParse(*p, &tmp); + return WireFormatLite::ZigZagDecode32(static_cast<uint32_t>(tmp)); +} + +template <typename T, typename std::enable_if< + !std::is_base_of<MessageLite, T>::value, bool>::type> +PROTOBUF_NODISCARD const char* ParseContext::ParseMessage(T* msg, + const char* ptr) { + int old; + ptr = ReadSizeAndPushLimitAndDepth(ptr, &old); + ptr = ptr ? msg->_InternalParse(ptr, this) : nullptr; + depth_++; + if (!PopLimit(old)) return nullptr; + return ptr; +} + +template <typename Tag, typename T> +const char* EpsCopyInputStream::ReadRepeatedFixed(const char* ptr, + Tag expected_tag, + RepeatedField<T>* out) { + do { + out->Add(UnalignedLoad<T>(ptr)); + ptr += sizeof(T); + if (PROTOBUF_PREDICT_FALSE(ptr >= limit_end_)) return ptr; + } while (UnalignedLoad<Tag>(ptr) == expected_tag && (ptr += sizeof(Tag))); + return ptr; +} + +// Add any of the following lines to debug which parse function is failing. + +#define GOOGLE_PROTOBUF_ASSERT_RETURN(predicate, ret) \ + if (!(predicate)) { \ + /* ::raise(SIGINT); */ \ + /* GOOGLE_LOG(ERROR) << "Parse failure"; */ \ + return ret; \ + } + +#define GOOGLE_PROTOBUF_PARSER_ASSERT(predicate) \ + GOOGLE_PROTOBUF_ASSERT_RETURN(predicate, nullptr) + +template <typename T> +const char* EpsCopyInputStream::ReadPackedFixed(const char* ptr, int size, + RepeatedField<T>* out) { + GOOGLE_PROTOBUF_PARSER_ASSERT(ptr); + int nbytes = buffer_end_ + kSlopBytes - ptr; + while (size > nbytes) { + int num = nbytes / sizeof(T); + int old_entries = out->size(); + out->Reserve(old_entries + num); + int block_size = num * sizeof(T); + auto dst = out->AddNAlreadyReserved(num); +#ifdef PROTOBUF_LITTLE_ENDIAN + std::memcpy(dst, ptr, block_size); +#else + for (int i = 0; i < num; i++) + dst[i] = UnalignedLoad<T>(ptr + i * sizeof(T)); +#endif + size -= block_size; + if (limit_ <= kSlopBytes) return nullptr; + ptr = Next(); + if (ptr == nullptr) return nullptr; + ptr += kSlopBytes - (nbytes - block_size); + nbytes = buffer_end_ + kSlopBytes - ptr; + } + int num = size / sizeof(T); + int old_entries = out->size(); + out->Reserve(old_entries + num); + int block_size = num * sizeof(T); + auto dst = out->AddNAlreadyReserved(num); +#ifdef PROTOBUF_LITTLE_ENDIAN + std::memcpy(dst, ptr, block_size); +#else + for (int i = 0; i < num; i++) dst[i] = UnalignedLoad<T>(ptr + i * sizeof(T)); +#endif + ptr += block_size; + if (size != block_size) return nullptr; + return ptr; +} + +template <typename Add> +const char* ReadPackedVarintArray(const char* ptr, const char* end, Add add) { + while (ptr < end) { + uint64_t varint; + ptr = VarintParse(ptr, &varint); + if (ptr == nullptr) return nullptr; + add(varint); + } + return ptr; +} + +template <typename Add> +const char* EpsCopyInputStream::ReadPackedVarint(const char* ptr, Add add) { + int size = ReadSize(&ptr); + GOOGLE_PROTOBUF_PARSER_ASSERT(ptr); + int chunk_size = buffer_end_ - ptr; + while (size > chunk_size) { + ptr = ReadPackedVarintArray(ptr, buffer_end_, add); + if (ptr == nullptr) return nullptr; + int overrun = ptr - buffer_end_; + GOOGLE_DCHECK(overrun >= 0 && overrun <= kSlopBytes); + if (size - chunk_size <= kSlopBytes) { + // The current buffer contains all the information needed, we don't need + // to flip buffers. However we must parse from a buffer with enough space + // so we are not prone to a buffer overflow. + char buf[kSlopBytes + 10] = {}; + std::memcpy(buf, buffer_end_, kSlopBytes); + GOOGLE_CHECK_LE(size - chunk_size, kSlopBytes); + auto end = buf + (size - chunk_size); + auto res = ReadPackedVarintArray(buf + overrun, end, add); + if (res == nullptr || res != end) return nullptr; + return buffer_end_ + (res - buf); + } + size -= overrun + chunk_size; + GOOGLE_DCHECK_GT(size, 0); + // We must flip buffers + if (limit_ <= kSlopBytes) return nullptr; + ptr = Next(); + if (ptr == nullptr) return nullptr; + ptr += overrun; + chunk_size = buffer_end_ - ptr; + } + auto end = ptr + size; + ptr = ReadPackedVarintArray(ptr, end, add); + return end == ptr ? ptr : nullptr; +} + +// Helper for verification of utf8 +PROTOBUF_EXPORT +bool VerifyUTF8(StringPiece s, const char* field_name); + +inline bool VerifyUTF8(const std::string* s, const char* field_name) { + return VerifyUTF8(*s, field_name); +} + +// All the string parsers with or without UTF checking and for all CTypes. +PROTOBUF_NODISCARD PROTOBUF_EXPORT const char* InlineGreedyStringParser( + std::string* s, const char* ptr, ParseContext* ctx); + + +template <typename T> +PROTOBUF_NODISCARD const char* FieldParser(uint64_t tag, T& field_parser, + const char* ptr, ParseContext* ctx) { + uint32_t number = tag >> 3; + GOOGLE_PROTOBUF_PARSER_ASSERT(number != 0); + using WireType = internal::WireFormatLite::WireType; + switch (tag & 7) { + case WireType::WIRETYPE_VARINT: { + uint64_t value; + ptr = VarintParse(ptr, &value); + GOOGLE_PROTOBUF_PARSER_ASSERT(ptr); + field_parser.AddVarint(number, value); + break; + } + case WireType::WIRETYPE_FIXED64: { + uint64_t value = UnalignedLoad<uint64_t>(ptr); + ptr += 8; + field_parser.AddFixed64(number, value); + break; + } + case WireType::WIRETYPE_LENGTH_DELIMITED: { + ptr = field_parser.ParseLengthDelimited(number, ptr, ctx); + GOOGLE_PROTOBUF_PARSER_ASSERT(ptr); + break; + } + case WireType::WIRETYPE_START_GROUP: { + ptr = field_parser.ParseGroup(number, ptr, ctx); + GOOGLE_PROTOBUF_PARSER_ASSERT(ptr); + break; + } + case WireType::WIRETYPE_END_GROUP: { + GOOGLE_LOG(FATAL) << "Can't happen"; + break; + } + case WireType::WIRETYPE_FIXED32: { + uint32_t value = UnalignedLoad<uint32_t>(ptr); + ptr += 4; + field_parser.AddFixed32(number, value); + break; + } + default: + return nullptr; + } + return ptr; +} + +template <typename T> +PROTOBUF_NODISCARD const char* WireFormatParser(T& field_parser, + const char* ptr, + ParseContext* ctx) { + while (!ctx->Done(&ptr)) { + uint32_t tag; + ptr = ReadTag(ptr, &tag); + GOOGLE_PROTOBUF_PARSER_ASSERT(ptr != nullptr); + if (tag == 0 || (tag & 7) == 4) { + ctx->SetLastTag(tag); + return ptr; + } + ptr = FieldParser(tag, field_parser, ptr, ctx); + GOOGLE_PROTOBUF_PARSER_ASSERT(ptr != nullptr); + } + return ptr; +} + +// The packed parsers parse repeated numeric primitives directly into the +// corresponding field + +// These are packed varints +PROTOBUF_NODISCARD PROTOBUF_EXPORT const char* PackedInt32Parser( + void* object, const char* ptr, ParseContext* ctx); +PROTOBUF_NODISCARD PROTOBUF_EXPORT const char* PackedUInt32Parser( + void* object, const char* ptr, ParseContext* ctx); +PROTOBUF_NODISCARD PROTOBUF_EXPORT const char* PackedInt64Parser( + void* object, const char* ptr, ParseContext* ctx); +PROTOBUF_NODISCARD PROTOBUF_EXPORT const char* PackedUInt64Parser( + void* object, const char* ptr, ParseContext* ctx); +PROTOBUF_NODISCARD PROTOBUF_EXPORT const char* PackedSInt32Parser( + void* object, const char* ptr, ParseContext* ctx); +PROTOBUF_NODISCARD PROTOBUF_EXPORT const char* PackedSInt64Parser( + void* object, const char* ptr, ParseContext* ctx); +PROTOBUF_NODISCARD PROTOBUF_EXPORT const char* PackedEnumParser( + void* object, const char* ptr, ParseContext* ctx); + +template <typename T> +PROTOBUF_NODISCARD const char* PackedEnumParser(void* object, const char* ptr, + ParseContext* ctx, + bool (*is_valid)(int), + InternalMetadata* metadata, + int field_num) { + return ctx->ReadPackedVarint( + ptr, [object, is_valid, metadata, field_num](uint64_t val) { + if (is_valid(val)) { + static_cast<RepeatedField<int>*>(object)->Add(val); + } else { + WriteVarint(field_num, val, metadata->mutable_unknown_fields<T>()); + } + }); +} + +template <typename T> +PROTOBUF_NODISCARD const char* PackedEnumParserArg( + void* object, const char* ptr, ParseContext* ctx, + bool (*is_valid)(const void*, int), const void* data, + InternalMetadata* metadata, int field_num) { + return ctx->ReadPackedVarint( + ptr, [object, is_valid, data, metadata, field_num](uint64_t val) { + if (is_valid(data, val)) { + static_cast<RepeatedField<int>*>(object)->Add(val); + } else { + WriteVarint(field_num, val, metadata->mutable_unknown_fields<T>()); + } + }); +} + +PROTOBUF_NODISCARD PROTOBUF_EXPORT const char* PackedBoolParser( + void* object, const char* ptr, ParseContext* ctx); +PROTOBUF_NODISCARD PROTOBUF_EXPORT const char* PackedFixed32Parser( + void* object, const char* ptr, ParseContext* ctx); +PROTOBUF_NODISCARD PROTOBUF_EXPORT const char* PackedSFixed32Parser( + void* object, const char* ptr, ParseContext* ctx); +PROTOBUF_NODISCARD PROTOBUF_EXPORT const char* PackedFixed64Parser( + void* object, const char* ptr, ParseContext* ctx); +PROTOBUF_NODISCARD PROTOBUF_EXPORT const char* PackedSFixed64Parser( + void* object, const char* ptr, ParseContext* ctx); +PROTOBUF_NODISCARD PROTOBUF_EXPORT const char* PackedFloatParser( + void* object, const char* ptr, ParseContext* ctx); +PROTOBUF_NODISCARD PROTOBUF_EXPORT const char* PackedDoubleParser( + void* object, const char* ptr, ParseContext* ctx); + +// This is the only recursive parser. +PROTOBUF_NODISCARD PROTOBUF_EXPORT const char* UnknownGroupLiteParse( + std::string* unknown, const char* ptr, ParseContext* ctx); +// This is a helper to for the UnknownGroupLiteParse but is actually also +// useful in the generated code. It uses overload on std::string* vs +// UnknownFieldSet* to make the generated code isomorphic between full and lite. +PROTOBUF_NODISCARD PROTOBUF_EXPORT const char* UnknownFieldParse( + uint32_t tag, std::string* unknown, const char* ptr, ParseContext* ctx); + +} // namespace internal +} // namespace protobuf +} // namespace google + +#include <google/protobuf/port_undef.inc> + +#endif // GOOGLE_PROTOBUF_PARSE_CONTEXT_H__ diff --git a/toolkit/components/protobuf/src/google/protobuf/port.h b/toolkit/components/protobuf/src/google/protobuf/port.h new file mode 100644 index 0000000000..a5c060b6f6 --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/port.h @@ -0,0 +1,80 @@ +// 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. + +// A common header that is included across all protobuf headers. We do our best +// to avoid #defining any macros here; instead we generally put macros in +// port_def.inc and port_undef.inc so they are not visible from outside of +// protobuf. + +#ifndef GOOGLE_PROTOBUF_PORT_H__ +#define GOOGLE_PROTOBUF_PORT_H__ + +#include <cstddef> +#include <new> + + +namespace google { +namespace protobuf { +namespace internal { +inline void SizedDelete(void* p, size_t size) { +#if defined(__cpp_sized_deallocation) + ::operator delete(p, size); +#else + ::operator delete(p); +#endif +} +inline void SizedArrayDelete(void* p, size_t size) { +#if defined(__cpp_sized_deallocation) + ::operator delete[](p, size); +#else + ::operator delete[](p); +#endif +} + +// Tag type used to invoke the constinit constructor overload of classes +// such as ArenaStringPtr and MapFieldBase. Such constructors are internal +// implementation details of the library. +struct ConstantInitialized { + explicit ConstantInitialized() = default; +}; + +// Tag type used to invoke the arena constructor overload of classes such +// as ExtensionSet and MapFieldLite in aggregate initialization. These +// classes typically don't have move/copy constructors, which rules out +// explicit initialization in pre-C++17. +struct ArenaInitialized { + explicit ArenaInitialized() = default; +}; + +} // namespace internal +} // namespace protobuf +} // namespace google + +#endif // GOOGLE_PROTOBUF_PORT_H__ diff --git a/toolkit/components/protobuf/src/google/protobuf/port_def.inc b/toolkit/components/protobuf/src/google/protobuf/port_def.inc new file mode 100644 index 0000000000..8943a4454f --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/port_def.inc @@ -0,0 +1,928 @@ +// 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. + +// This file defines common macros that are used in protobuf. +// +// To hide these definitions from the outside world (and to prevent collisions +// if more than one version of protobuf is #included in the same project) you +// must follow this pattern when #including port_def.inc in a header file: +// +// #include "other_header.h" +// #include "message.h" +// // etc. +// +// #include "port_def.inc" // MUST be last header included +// +// // Definitions for this header. +// +// #include "port_undef.inc" +// +// This is a textual header with no include guard, because we want to +// detect/prohibit anytime it is #included twice without a corresponding +// #undef. + +// The definitions in this file are intended to be portable across Clang, +// GCC, and MSVC. Function-like macros are usable without an #ifdef guard. +// Syntax macros (for example, attributes) are always defined, although +// they may be empty. +// +// Some definitions rely on the NDEBUG macro and/or (in MSVC) _DEBUG: +// - https://en.cppreference.com/w/c/error/assert +// - https://docs.microsoft.com/en-us/cpp/preprocessor/predefined-macros#microsoft-specific-predefined-macros +// +// References for predefined macros: +// - Standard: https://en.cppreference.com/w/cpp/preprocessor/replace +// - Clang: https://clang.llvm.org/docs/LanguageExtensions.html +// (see also GCC predefined macros) +// - GCC: https://gcc.gnu.org/onlinedocs/cpp/Predefined-Macros.html +// - MSVC: https://docs.microsoft.com/en-us/cpp/preprocessor/predefined-macros +// - Interactive (Clang/GCC only): https://www.compiler-explorer.com/z/hc6jKd3sj +// +// References for attributes (and extension attributes): +// - Standard: https://en.cppreference.com/w/cpp/language/attributes +// - Clang: https://clang.llvm.org/docs/AttributeReference.html +// - GCC: https://gcc.gnu.org/onlinedocs/gcc/Attribute-Syntax.html +// (see Clang attribute docs as well) +// +// References for standard C++ language conformance (and minimum versions): +// - Clang: https://clang.llvm.org/cxx_status.html +// - GCC: https://gcc.gnu.org/projects/cxx-status.html +// - MSVC: https://docs.microsoft.com/en-us/cpp/overview/visual-cpp-language-conformance +// +// Historical release notes (which can help to determine minimum versions): +// - Clang: https://releases.llvm.org/ +// - GCC: https://gcc.gnu.org/releases.html +// - MSVC: https://docs.microsoft.com/en-us/visualstudio/releases/2019/release-notes-history +// https://docs.microsoft.com/en-us/visualstudio/releasenotes/vs2017-relnotes-history + +// Portable fallbacks for C++20 feature test macros: +// https://en.cppreference.com/w/cpp/feature_test +#ifndef __has_cpp_attribute +#define __has_cpp_attribute(x) 0 +#define PROTOBUF_has_cpp_attribute_DEFINED_ +#endif + +// Portable fallback for Clang's __has_feature macro: +// https://clang.llvm.org/docs/LanguageExtensions.html#has-feature-and-has-extension +#ifndef __has_feature +#define __has_feature(x) 0 +#define PROTOBUF_has_feature_DEFINED_ +#endif + +// Portable fallback for Clang's __has_warning macro: +#ifndef __has_warning +#define __has_warning(x) 0 +#define PROTOBUF_has_warning_DEFINED_ +#endif + +// Portable fallbacks for the __has_attribute macro (GCC and Clang): +// https://clang.llvm.org/docs/LanguageExtensions.html#has-attribute +// https://gcc.gnu.org/onlinedocs/cpp/_005f_005fhas_005fattribute.html +#ifndef __has_attribute +#define __has_attribute(x) 0 +#define PROTOBUF_has_attribute_DEFINED_ +#endif + +// Portable fallback for __has_builtin (GCC and Clang): +// https://clang.llvm.org/docs/LanguageExtensions.html#has-builtin +// https://gcc.gnu.org/onlinedocs/cpp/_005f_005fhas_005fbuiltin.html +#ifndef __has_builtin +#define __has_builtin(x) 0 +#define PROTOBUF_has_builtin_DEFINED_ +#endif + +// Portable PROTOBUF_BUILTIN_BSWAPxx definitions +// Code must check for availability, e.g.: `defined(PROTOBUF_BUILTIN_BSWAP32)` +#ifdef PROTOBUF_BUILTIN_BSWAP16 +#error PROTOBUF_BUILTIN_BSWAP16 was previously defined +#endif +#ifdef PROTOBUF_BUILTIN_BSWAP32 +#error PROTOBUF_BUILTIN_BSWAP32 was previously defined +#endif +#ifdef PROTOBUF_BUILTIN_BSWAP64 +#error PROTOBUF_BUILTIN_BSWAP64 was previously defined +#endif +#if defined(__GNUC__) || __has_builtin(__builtin_bswap16) +#define PROTOBUF_BUILTIN_BSWAP16(x) __builtin_bswap16(x) +#endif +#if defined(__GNUC__) || __has_builtin(__builtin_bswap32) +#define PROTOBUF_BUILTIN_BSWAP32(x) __builtin_bswap32(x) +#endif +#if defined(__GNUC__) || __has_builtin(__builtin_bswap64) +#define PROTOBUF_BUILTIN_BSWAP64(x) __builtin_bswap64(x) +#endif + +// Portable check for GCC minimum version: +// https://gcc.gnu.org/onlinedocs/cpp/Common-Predefined-Macros.html +#if defined(__GNUC__) && defined(__GNUC_MINOR__) \ + && defined(__GNUC_PATCHLEVEL__) +# define PROTOBUF_GNUC_MIN(x, y) \ + (__GNUC__ > (x) || __GNUC__ == (x) && __GNUC_MINOR__ >= (y)) +#else +# define PROTOBUF_GNUC_MIN(x, y) 0 +#endif + +// Portable check for MSVC minimum version: +// https://docs.microsoft.com/en-us/cpp/preprocessor/predefined-macros +#if defined(_MSC_VER) +#define PROTOBUF_MSC_VER_MIN(x) (_MSC_VER >= x) +#else +#define PROTOBUF_MSC_VER_MIN(x) 0 +#endif + +// Portable check for minimum C++ language version: +// https://en.cppreference.com/w/cpp/preprocessor/replace +// https://docs.microsoft.com/en-us/cpp/preprocessor/predefined-macros +#if !defined(_MSVC_LANG) +#define PROTOBUF_CPLUSPLUS_MIN(x) (__cplusplus >= x) +#else +#define PROTOBUF_CPLUSPLUS_MIN(x) (_MSVC_LANG >= x) +#endif + +// Future versions of protobuf will include breaking changes to some APIs. +// This macro can be set to enable these API changes ahead of time, so that +// user code can be updated before upgrading versions of protobuf. +// PROTOBUF_FUTURE_FINAL is used on classes that are historically not marked as +// final, but that may be marked final in future (breaking) releases. +// #define PROTOBUF_FUTURE_BREAKING_CHANGES 1 +// #define PROTOBUF_FUTURE_FINAL final +#define PROTOBUF_FUTURE_FINAL + +#ifdef PROTOBUF_VERSION +#error PROTOBUF_VERSION was previously defined +#endif +#define PROTOBUF_VERSION 3021006 + +#ifdef PROTOBUF_MIN_HEADER_VERSION_FOR_PROTOC +#error PROTOBUF_MIN_HEADER_VERSION_FOR_PROTOC was previously defined +#endif +#define PROTOBUF_MIN_HEADER_VERSION_FOR_PROTOC 3021000 + +#ifdef PROTOBUF_MIN_PROTOC_VERSION +#error PROTOBUF_MIN_PROTOC_VERSION was previously defined +#endif +#define PROTOBUF_MIN_PROTOC_VERSION 3021000 + +#ifdef PROTOBUF_VERSION_SUFFIX +#error PROTOBUF_VERSION_SUFFIX was previously defined +#endif +#define PROTOBUF_VERSION_SUFFIX "" + +#if defined(PROTOBUF_NAMESPACE) || defined(PROTOBUF_NAMESPACE_ID) +#error PROTOBUF_NAMESPACE or PROTOBUF_NAMESPACE_ID was previously defined +#endif +#define PROTOBUF_NAMESPACE "google::protobuf" +#define PROTOBUF_NAMESPACE_ID google::protobuf +#define PROTOBUF_NAMESPACE_OPEN \ + namespace google { \ + namespace protobuf { +#define PROTOBUF_NAMESPACE_CLOSE \ + } /* namespace protobuf */ \ + } /* namespace google */ + +#ifdef PROTOBUF_ALWAYS_INLINE +#error PROTOBUF_ALWAYS_INLINE was previously defined +#endif +// For functions we want to force inline. +#if defined(PROTOBUF_NO_INLINE) +# define PROTOBUF_ALWAYS_INLINE +#elif PROTOBUF_GNUC_MIN(3, 1) +# define PROTOBUF_ALWAYS_INLINE __attribute__((always_inline)) +#elif defined(_MSC_VER) +# define PROTOBUF_ALWAYS_INLINE __forceinline +#else +# define PROTOBUF_ALWAYS_INLINE +#endif + +#ifdef PROTOBUF_NDEBUG_INLINE +#error PROTOBUF_NDEBUG_INLINE was previously defined +#endif +// Avoid excessive inlining in non-optimized builds. Without other optimizations +// the inlining is not going to provide benefits anyway and the huge resulting +// functions, especially in the proto-generated serialization functions, produce +// stack frames so large that many tests run into stack overflows (b/32192897). +#if defined(NDEBUG) || (defined(_MSC_VER) && !defined(_DEBUG)) +# define PROTOBUF_NDEBUG_INLINE PROTOBUF_ALWAYS_INLINE +#else +# define PROTOBUF_NDEBUG_INLINE +#endif + +// Note that PROTOBUF_NOINLINE is an attribute applied to functions, to prevent +// them from being inlined by the compiler. This is different from +// PROTOBUF_NO_INLINE, which is a user-supplied macro that disables forced +// inlining by PROTOBUF_(ALWAYS|NDEBUG)_INLINE. +#ifdef PROTOBUF_NOINLINE +#error PROTOBUF_NOINLINE was previously defined +#endif +#if PROTOBUF_GNUC_MIN(3, 1) +# define PROTOBUF_NOINLINE __attribute__((noinline)) +#elif defined(_MSC_VER) +// Seems to have been around since at least Visual Studio 2005 +# define PROTOBUF_NOINLINE __declspec(noinline) +#endif + +#ifdef PROTOBUF_MUSTTAIL +#error PROTOBUF_MUSTTAIL was previously defined +#endif +#ifdef PROTOBUF_TAILCALL +#error PROTOBUF_TAILCALL was previously defined +#endif +#if __has_cpp_attribute(clang::musttail) && !defined(__arm__) && \ + !defined(_ARCH_PPC) && !defined(__wasm__) && \ + !(defined(_MSC_VER) && defined(_M_IX86)) && \ + !(defined(__NDK_MAJOR__) && __NDK_MAJOR <= 24) +# ifndef PROTO2_OPENSOURCE +// Compilation fails on ARM32: b/195943306 +// Compilation fails on powerpc64le: b/187985113 +// Compilation fails on X86 Windows: +// https://github.com/llvm/llvm-project/issues/53271 +# endif +#define PROTOBUF_MUSTTAIL [[clang::musttail]] +#define PROTOBUF_TAILCALL true +#else +#define PROTOBUF_MUSTTAIL +#define PROTOBUF_TAILCALL false +#endif + +#ifdef PROTOBUF_EXCLUSIVE_LOCKS_REQUIRED +#error PROTOBUF_EXCLUSIVE_LOCKS_REQUIRED was previously defined +#endif +#if __has_attribute(exclusive_locks_required) +#define PROTOBUF_EXCLUSIVE_LOCKS_REQUIRED(...) \ + __attribute__((exclusive_locks_required(__VA_ARGS__))) +#else +#define PROTOBUF_EXCLUSIVE_LOCKS_REQUIRED(...) +#endif + +#ifdef PROTOBUF_NO_THREAD_SAFETY_ANALYSIS +#error PROTOBUF_NO_THREAD_SAFETY_ANALYSIS was previously defined +#endif +#if __has_attribute(no_thread_safety_analysis) +#define PROTOBUF_NO_THREAD_SAFETY_ANALYSIS \ + __attribute__((no_thread_safety_analysis)) +#else +#define PROTOBUF_NO_THREAD_SAFETY_ANALYSIS +#endif + +#ifdef PROTOBUF_GUARDED_BY +#error PROTOBUF_GUARDED_BY was previously defined +#endif +#if __has_attribute(guarded_by) +#define PROTOBUF_GUARDED_BY(x) __attribute__((guarded_by(x))) +#else +#define PROTOBUF_GUARDED_BY(x) +#endif + +#ifdef PROTOBUF_LOCKS_EXCLUDED +#error PROTOBUF_LOCKS_EXCLUDED was previously defined +#endif +#if __has_attribute(locks_excluded) +#define PROTOBUF_LOCKS_EXCLUDED(...) \ + __attribute__((locks_excluded(__VA_ARGS__))) +#else +#define PROTOBUF_LOCKS_EXCLUDED(...) +#endif + +#ifdef PROTOBUF_COLD +#error PROTOBUF_COLD was previously defined +#endif +#if __has_attribute(cold) || PROTOBUF_GNUC_MIN(4, 3) +# define PROTOBUF_COLD __attribute__((cold)) +#else +# define PROTOBUF_COLD +#endif + +#ifdef PROTOBUF_SECTION_VARIABLE +#error PROTOBUF_SECTION_VARIABLE was previously defined +#endif +#if (__has_attribute(section) || defined(__GNUC__)) && defined(__ELF__) +// Place a variable in the given ELF section. +# define PROTOBUF_SECTION_VARIABLE(x) __attribute__((section(#x))) +#else +# define PROTOBUF_SECTION_VARIABLE(x) +#endif + +#if defined(PROTOBUF_DEPRECATED) +#error PROTOBUF_DEPRECATED was previously defined +#endif +#if defined(PROTOBUF_DEPRECATED_MSG) +#error PROTOBUF_DEPRECATED_MSG was previously defined +#endif +#if __has_attribute(deprecated) || PROTOBUF_GNUC_MIN(3, 0) +# define PROTOBUF_DEPRECATED __attribute__((deprecated)) +# define PROTOBUF_DEPRECATED_MSG(msg) __attribute__((deprecated(msg))) +#elif defined(_MSC_VER) +# define PROTOBUF_DEPRECATED __declspec(deprecated) +# define PROTOBUF_DEPRECATED_MSG(msg) __declspec(deprecated(msg)) +#else +# define PROTOBUF_DEPRECATED +# define PROTOBUF_DEPRECATED_MSG(msg) +#endif + +#if defined(PROTOBUF_DEPRECATED_ENUM) +#error PROTOBUF_DEPRECATED_ENUM was previously defined +#endif +#if defined(__clang__) || PROTOBUF_GNUC_MIN(6, 0) +// https://gcc.gnu.org/gcc-6/changes.html +# define PROTOBUF_DEPRECATED_ENUM __attribute__((deprecated)) +#else +# define PROTOBUF_DEPRECATED_ENUM +#endif + +#ifdef PROTOBUF_FUNC_ALIGN +#error PROTOBUF_FUNC_ALIGN was previously defined +#endif +#if __has_attribute(aligned) || PROTOBUF_GNUC_MIN(4, 3) +#define PROTOBUF_FUNC_ALIGN(bytes) __attribute__((aligned(bytes))) +#else +#define PROTOBUF_FUNC_ALIGN(bytes) +#endif + +#ifdef PROTOBUF_RETURNS_NONNULL +#error PROTOBUF_RETURNS_NONNULL was previously defined +#endif +#if __has_attribute(returns_nonnull) || PROTOBUF_GNUC_MIN(4, 9) +#define PROTOBUF_RETURNS_NONNULL __attribute__((returns_nonnull)) +#else +#define PROTOBUF_RETURNS_NONNULL +#endif + +#ifdef PROTOBUF_ATTRIBUTE_REINITIALIZES +#error PROTOBUF_ATTRIBUTE_REINITIALIZES was previously defined +#endif +#if __has_cpp_attribute(clang::reinitializes) +#define PROTOBUF_ATTRIBUTE_REINITIALIZES [[clang::reinitializes]] +#else +#define PROTOBUF_ATTRIBUTE_REINITIALIZES +#endif + +// The minimum library version which works with the current version of the +// headers. +#define GOOGLE_PROTOBUF_MIN_LIBRARY_VERSION 3021000 + +#ifdef PROTOBUF_RTTI +#error PROTOBUF_RTTI was previously defined +#endif +#if defined(GOOGLE_PROTOBUF_NO_RTTI) && GOOGLE_PROTOBUF_NO_RTTI +// A user-provided definition GOOGLE_PROTOBUF_NO_RTTI=1 disables RTTI. +#define PROTOBUF_RTTI 0 +#elif defined(__cpp_rtti) +// https://en.cppreference.com/w/cpp/feature_test +#define PROTOBUF_RTTI 1 +#elif __has_feature(cxx_rtti) +// https://clang.llvm.org/docs/LanguageExtensions.html#c-rtti +#define PROTOBUF_RTTI 1 +#elif defined(__GXX_RTTI) +// https://gcc.gnu.org/onlinedocs/cpp/Common-Predefined-Macros.html +#define PROTOBUF_RTTI 1 +#elif defined(_CPPRTTI) +// https://docs.microsoft.com/en-us/cpp/build/reference/gr-enable-run-time-type-information +#define PROTOBUF_RTTI 1 +#else +#define PROTOBUF_RTTI 0 +#endif + +// Returns the offset of the given field within the given aggregate type. +// This is equivalent to the ANSI C offsetof() macro. However, according +// to the C++ standard, offsetof() only works on POD types, and GCC +// enforces this requirement with a warning. In practice, this rule is +// unnecessarily strict; there is probably no compiler or platform on +// which the offsets of the direct fields of a class are non-constant. +// Fields inherited from superclasses *can* have non-constant offsets, +// but that's not what this macro will be used for. +#ifdef PROTOBUF_FIELD_OFFSET +#error PROTOBUF_FIELD_OFFSET was previously defined +#endif +#if defined(__clang__) +// For Clang we use __builtin_offsetof() and suppress the warning, +// to avoid Control Flow Integrity and UBSan vptr sanitizers from +// crashing while trying to validate the invalid reinterpret_casts. +#define PROTOBUF_FIELD_OFFSET(TYPE, FIELD) \ + _Pragma("clang diagnostic push") \ + _Pragma("clang diagnostic ignored \"-Winvalid-offsetof\"") \ + __builtin_offsetof(TYPE, FIELD) \ + _Pragma("clang diagnostic pop") +#elif PROTOBUF_GNUC_MIN(4, 8) +#define PROTOBUF_FIELD_OFFSET(TYPE, FIELD) __builtin_offsetof(TYPE, FIELD) +#else // defined(__clang__) +// Note that we calculate relative to the pointer value 16 here since if we +// just use zero, GCC complains about dereferencing a NULL pointer. We +// choose 16 rather than some other number just in case the compiler would +// be confused by an unaligned pointer. +#define PROTOBUF_FIELD_OFFSET(TYPE, FIELD) \ + static_cast< ::uint32_t>(reinterpret_cast<const char*>( \ + &reinterpret_cast<const TYPE*>(16)->FIELD) - \ + reinterpret_cast<const char*>(16)) +#endif + +#ifdef PROTOBUF_EXPORT +#error PROTOBUF_EXPORT was previously defined +#endif + +#if defined(PROTOBUF_USE_DLLS) && defined(_MSC_VER) +# if defined(LIBPROTOBUF_EXPORTS) +# define PROTOBUF_EXPORT __declspec(dllexport) +# define PROTOBUF_EXPORT_TEMPLATE_DECLARE +# define PROTOBUF_EXPORT_TEMPLATE_DEFINE __declspec(dllexport) +# else +# define PROTOBUF_EXPORT __declspec(dllimport) +# define PROTOBUF_EXPORT_TEMPLATE_DECLARE +# define PROTOBUF_EXPORT_TEMPLATE_DEFINE __declspec(dllimport) +# endif // defined(LIBPROTOBUF_EXPORTS) +#elif defined(PROTOBUF_USE_DLLS) && defined(LIBPROTOBUF_EXPORTS) +# define PROTOBUF_EXPORT __attribute__((visibility("default"))) +# define PROTOBUF_EXPORT_TEMPLATE_DECLARE __attribute__((visibility("default"))) +# define PROTOBUF_EXPORT_TEMPLATE_DEFINE +#else +# define PROTOBUF_EXPORT +# define PROTOBUF_EXPORT_TEMPLATE_DECLARE +# define PROTOBUF_EXPORT_TEMPLATE_DEFINE +#endif + +#ifdef PROTOC_EXPORT +#error PROTOC_EXPORT was previously defined +#endif + +#if defined(PROTOBUF_USE_DLLS) && defined(_MSC_VER) +# if defined(LIBPROTOC_EXPORTS) +# define PROTOC_EXPORT __declspec(dllexport) +# else +# define PROTOC_EXPORT __declspec(dllimport) +# endif // defined(LIBPROTOC_EXPORTS) +#elif defined(PROTOBUF_USE_DLLS) && defined(LIBPROTOC_EXPORTS) +# define PROTOC_EXPORT __attribute__((visibility("default"))) +#else +# define PROTOC_EXPORT +#endif + +#if defined(PROTOBUF_PREDICT_TRUE) || defined(PROTOBUF_PREDICT_FALSE) +#error PROTOBUF_PREDICT_(TRUE|FALSE) was previously defined +#endif +#if PROTOBUF_GNUC_MIN(3, 0) +# define PROTOBUF_PREDICT_TRUE(x) (__builtin_expect(false || (x), true)) +# define PROTOBUF_PREDICT_FALSE(x) (__builtin_expect(false || (x), false)) +#else +# define PROTOBUF_PREDICT_TRUE(x) (x) +# define PROTOBUF_PREDICT_FALSE(x) (x) +#endif + +#ifdef PROTOBUF_NODISCARD +#error PROTOBUF_NODISCARD was previously defined +#endif +#if __has_cpp_attribute(nodiscard) && PROTOBUF_CPLUSPLUS_MIN(201703L) +#define PROTOBUF_NODISCARD [[nodiscard]] +#elif __has_attribute(warn_unused_result) || PROTOBUF_GNUC_MIN(4, 8) +#define PROTOBUF_NODISCARD __attribute__((warn_unused_result)) +#else +#define PROTOBUF_NODISCARD +#endif + +// Enable all stable experiments if this flag is set. This allows us to group +// all of these experiments under a single build flag, which can be enabled in +// the protobuf.stable-experiments TAP project. +#ifdef PROTOBUF_ENABLE_STABLE_EXPERIMENTS +#define PROTOBUF_FORCE_MESSAGE_OWNED_ARENA +#endif // !PROTOBUF_ENABLE_STABLE_EXPERIMENTS + +#ifdef PROTOBUF_FORCE_COPY_IN_RELEASE +#error PROTOBUF_FORCE_COPY_IN_RELEASE was previously defined +#endif + +#ifdef PROTOBUF_FORCE_COPY_IN_SWAP +#error PROTOBUF_FORCE_COPY_IN_SWAP was previously defined +#endif + +#ifdef PROTOBUF_FORCE_COPY_IN_MOVE +#error PROTOBUF_FORCE_COPY_IN_MOVE was previously defined +#endif + +#ifdef PROTOBUF_FORCE_RESET_IN_CLEAR +#error PROTOBUF_FORCE_RESET_IN_CLEAR was previously defined +#endif + +// Force copy the default string to a string field so that non-optimized builds +// have harder-to-rely-on address stability. +#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING +#error PROTOBUF_FORCE_COPY_DEFAULT_STRING was previously defined +#endif + +#ifdef PROTOBUF_FALLTHROUGH_INTENDED +#error PROTOBUF_FALLTHROUGH_INTENDED was previously defined +#endif +#if __has_cpp_attribute(fallthrough) +#define PROTOBUF_FALLTHROUGH_INTENDED [[fallthrough]] +#elif __has_feature(cxx_attributes) && __has_warning("-Wimplicit-fallthrough") +#define PROTOBUF_FALLTHROUGH_INTENDED [[clang::fallthrough]] +#elif PROTOBUF_GNUC_MIN(7, 0) +#define PROTOBUF_FALLTHROUGH_INTENDED [[gnu::fallthrough]] +#else +#define PROTOBUF_FALLTHROUGH_INTENDED +#endif + +// PROTOBUF_ASSUME(pred) tells the compiler that it can assume pred is true. To +// be safe, we also validate the assumption with a GOOGLE_DCHECK in unoptimized +// builds. The macro does not do anything useful if the compiler does not +// support __builtin_assume. +#ifdef PROTOBUF_ASSUME +#error PROTOBUF_ASSUME was previously defined +#endif +#if __has_builtin(__builtin_assume) +#define PROTOBUF_ASSUME(pred) \ + GOOGLE_DCHECK(pred); \ + __builtin_assume(pred) +#else +#define PROTOBUF_ASSUME(pred) GOOGLE_DCHECK(pred) +#endif + +// Specify memory alignment for structs, classes, etc. +// Use like: +// class PROTOBUF_ALIGNAS(16) MyClass { ... } +// PROTOBUF_ALIGNAS(16) int array[4]; +// +// In most places you can use the C++11 keyword "alignas", which is preferred. +// +// But compilers have trouble mixing __attribute__((...)) syntax with +// alignas(...) syntax. +// +// Doesn't work in clang or gcc: +// struct alignas(16) __attribute__((packed)) S { char c; }; +// Works in clang but not gcc: +// struct __attribute__((packed)) alignas(16) S2 { char c; }; +// Works in clang and gcc: +// struct alignas(16) S3 { char c; } __attribute__((packed)); +// +// There are also some attributes that must be specified *before* a class +// definition: visibility (used for exporting functions/classes) is one of +// these attributes. This means that it is not possible to use alignas() with a +// class that is marked as exported. +#ifdef PROTOBUF_ALIGNAS +#error PROTOBUF_ALIGNAS was previously defined +#endif +#if defined(_MSC_VER) +#define PROTOBUF_ALIGNAS(byte_alignment) __declspec(align(byte_alignment)) +#elif PROTOBUF_GNUC_MIN(3, 0) +#define PROTOBUF_ALIGNAS(byte_alignment) \ + __attribute__((aligned(byte_alignment))) +#else +#define PROTOBUF_ALIGNAS(byte_alignment) alignas(byte_alignment) +#endif + +#ifdef PROTOBUF_FINAL +#error PROTOBUF_FINAL was previously defined +#endif +#define PROTOBUF_FINAL final + +#ifdef PROTOBUF_THREAD_LOCAL +#error PROTOBUF_THREAD_LOCAL was previously defined +#endif +#if defined(_MSC_VER) +#define PROTOBUF_THREAD_LOCAL __declspec(thread) +#else +#define PROTOBUF_THREAD_LOCAL __thread +#endif + +// TODO(b/228173843): cleanup PROTOBUF_LITTLE_ENDIAN in various 3p forks. +#if (defined(__BYTE_ORDER__) && defined(__ORDER_LITTLE_ENDIAN__) && \ + __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) +#define PROTOBUF_LITTLE_ENDIAN 1 +#ifdef PROTOBUF_BIG_ENDIAN +#error Conflicting PROTOBUF_BIG_ENDIAN was previously defined +#endif +#elif defined(__BYTE_ORDER__) && defined(__ORDER_BIG_ENDIAN__) && \ + __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ +#define PROTOBUF_BIG_ENDIAN 1 +#elif defined(_WIN32) || defined(__x86_64__) || defined(__aarch64__) +#define PROTOBUF_LITTLE_ENDIAN 1 +#else +#error "endian detection failed for current compiler" +#endif + +// For enabling message owned arena, one major blocker is semantic change from +// moving to copying when there is ownership transfer (e.g., move ctor, swap, +// set allocated, release). This change not only causes performance regression +// but also breaks users code (e.g., dangling reference). For top-level +// messages, since it owns the arena, we can mitigate the issue by transferring +// ownership of arena. However, we cannot do that for nested messages. In order +// to tell how many usages of nested messages affected by message owned arena, +// we need to simulate the arena ownership. +// This experiment is purely for the purpose of gathering data. All code guarded +// by this flag is supposed to be removed after this experiment. +#define PROTOBUF_MESSAGE_OWNED_ARENA_EXPERIMENT +#ifdef PROTOBUF_CONSTINIT +#error PROTOBUF_CONSTINIT was previously defined +#endif +#if defined(__cpp_constinit) && !defined(_MSC_VER) +#define PROTOBUF_CONSTINIT constinit +#define PROTOBUF_CONSTEXPR constexpr +// Some older Clang versions incorrectly raise an error about +// constant-initializing weak default instance pointers. Versions 12.0 and +// higher seem to work, except that XCode 12.5.1 shows the error even though it +// uses Clang 12.0.5. +// Clang-cl on Windows raises error also. +#elif !defined(_MSC_VER) && __has_cpp_attribute(clang::require_constant_initialization) && \ + ((defined(__APPLE__) && __clang_major__ >= 13) || \ + (!defined(__APPLE__) && __clang_major__ >= 12)) +#define PROTOBUF_CONSTINIT [[clang::require_constant_initialization]] +#define PROTOBUF_CONSTEXPR constexpr +#elif PROTOBUF_GNUC_MIN(12, 2) +#define PROTOBUF_CONSTINIT __constinit +#define PROTOBUF_CONSTEXPR constexpr +// MSVC 17 currently seems to raise an error about constant-initialized pointers. +#elif defined(_MSC_VER) && _MSC_VER >= 1930 +#define PROTOBUF_CONSTINIT +#define PROTOBUF_CONSTEXPR constexpr +#else +#define PROTOBUF_CONSTINIT +#define PROTOBUF_CONSTEXPR +#endif + +// Some globals with an empty non-trivial destructor are annotated with +// no_destroy for performance reasons. It reduces the cost of these globals in +// non-opt mode and under sanitizers. +#ifdef PROTOBUF_ATTRIBUTE_NO_DESTROY +#error PROTOBUF_ATTRIBUTE_NO_DESTROY was previously defined +#endif +#if __has_cpp_attribute(clang::no_destroy) +#define PROTOBUF_ATTRIBUTE_NO_DESTROY [[clang::no_destroy]] +#else +#define PROTOBUF_ATTRIBUTE_NO_DESTROY +#endif + +// Force clang to always emit complete debug info for a type. +// Clang uses constructor homing to determine when to emit debug info for a +// type. If the constructor of a type is never used, which can happen in some +// cases where member variables are constructed in place for optimization +// purposes (see b/208803175 for an example), the type will have incomplete +// debug info unless this attribute is used. +#ifdef PROTOBUF_ATTRIBUTE_STANDALONE_DEBUG +#error PROTOBUF_ATTRIBUTE_STANDALONE_DEBUG was previously defined +#endif +#if __has_cpp_attribute(clang::standalone_debug) +#define PROTOBUF_ATTRIBUTE_STANDALONE_DEBUG [[clang::standalone_debug]] +#else +#define PROTOBUF_ATTRIBUTE_STANDALONE_DEBUG +#endif + +// Protobuf extensions and reflection require registration of the protos linked +// in the binary. Not until everything is registered does the runtime have a +// complete view on all protos. When code is using reflection or extensions +// in between registration calls this can lead to surprising behavior. By +// having the registration run first we mitigate this scenario. +// Highest priority is 101. We use 102 for registration, to allow code that +// really wants to higher priority to still beat us. Some initialization happens +// at higher priority, though, since it is needed before registration. +#ifdef PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 +#error PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 was previously defined +#endif +#ifdef PROTOBUF_ATTRIBUTE_INIT_PRIORITY2 +#error PROTOBUF_ATTRIBUTE_INIT_PRIORITY2 was previously defined +#endif +#if PROTOBUF_GNUC_MIN(3, 0) && (!defined(__APPLE__) || defined(__clang__)) && \ + !((defined(sun) || defined(__sun)) && \ + (defined(__SVR4) || defined(__svr4__))) +#define PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 __attribute__((init_priority((101)))) +#define PROTOBUF_ATTRIBUTE_INIT_PRIORITY2 __attribute__((init_priority((102)))) +#else +#define PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 +#define PROTOBUF_ATTRIBUTE_INIT_PRIORITY2 +#endif + +#ifdef PROTOBUF_PRAGMA_INIT_SEG +#error PROTOBUF_PRAGMA_INIT_SEG was previously defined +#endif +#ifdef _MSC_VER +#define PROTOBUF_PRAGMA_INIT_SEG __pragma(init_seg(lib)) +#else +#define PROTOBUF_PRAGMA_INIT_SEG +#endif + +#ifdef PROTOBUF_ATTRIBUTE_WEAK +#error PROTOBUF_ATTRIBUTE_WEAK was previously defined +#endif +#if __has_attribute(weak) && \ + !defined(__APPLE__) && \ + (!defined(_WIN32) || __clang_major__ < 9) && \ + !defined(__MINGW32__) +#define PROTOBUF_ATTRIBUTE_WEAK __attribute__((weak)) +#define PROTOBUF_HAVE_ATTRIBUTE_WEAK 1 +#else +#define PROTOBUF_ATTRIBUTE_WEAK +#define PROTOBUF_HAVE_ATTRIBUTE_WEAK 0 +#endif + +// Macros to detect sanitizers. +#ifdef PROTOBUF_ASAN +#error PROTOBUF_ASAN was previously defined +#endif +#ifdef PROTOBUF_MSAN +#error PROTOBUF_MSAN was previously defined +#endif +#ifdef PROTOBUF_TSAN +#error PROTOBUF_TSAN was previously defined +#endif +#if defined(__clang__) +# if __has_feature(address_sanitizer) +# define PROTOBUF_ASAN 1 +# endif +# if __has_feature(thread_sanitizer) +# define PROTOBUF_TSAN 1 +# endif +# if __has_feature(memory_sanitizer) +# define PROTOBUF_MSAN 1 +# endif +#elif PROTOBUF_GNUC_MIN(3, 0) +// Double-guard is needed for -Wundef: +# ifdef __SANITIZE_ADDRESS__ +# if __SANITIZE_ADDRESS__ +# define PROTOBUF_ASAN 1 +# endif +# endif +# ifdef __SANITIZE_THREAD__ +# if __SANITIZE_THREAD__ +# define PROTOBUF_TSAN 1 +# endif +# endif +#endif + +// Tail call table-driven parsing can be enabled by defining +// PROTOBUF_EXPERIMENTAL_USE_TAIL_CALL_TABLE_PARSER at compilation time. Note +// that this macro is for small-scale testing only, and is not supported. +#ifdef PROTOBUF_TAIL_CALL_TABLE_PARSER_ENABLED +#error PROTOBUF_TAIL_CALL_TABLE_PARSER_ENABLED was previously declared +#endif +#if defined(PROTOBUF_EXPERIMENTAL_USE_TAIL_CALL_TABLE_PARSER) +#define PROTOBUF_TAIL_CALL_TABLE_PARSER_ENABLED 1 +#endif + +#define PROTOBUF_TC_PARAM_DECL \ + ::google::protobuf::MessageLite *msg, const char *ptr, \ + ::google::protobuf::internal::ParseContext *ctx, \ + const ::google::protobuf::internal::TcParseTableBase *table, \ + uint64_t hasbits, ::google::protobuf::internal::TcFieldData data + +#ifdef PROTOBUF_UNUSED +#error PROTOBUF_UNUSED was previously defined +#endif +#if __has_cpp_attribute(maybe_unused) || \ + (PROTOBUF_MSC_VER_MIN(1911) && PROTOBUF_CPLUSPLUS_MIN(201703L)) +#define PROTOBUF_UNUSED [[maybe_unused]] +#elif __has_attribute(unused) || PROTOBUF_GNUC_MIN(3, 0) +#define PROTOBUF_UNUSED __attribute__((__unused__)) +#else +#define PROTOBUF_UNUSED +#endif + +// ThreadSafeArenaz is turned off completely in opensource builds. + +// Windows declares several inconvenient macro names. We #undef them and then +// restore them in port_undef.inc. +#ifdef _MSC_VER +#pragma push_macro("CREATE_NEW") +#undef CREATE_NEW +#pragma push_macro("DELETE") +#undef DELETE +#pragma push_macro("DOUBLE_CLICK") +#undef DOUBLE_CLICK +#pragma push_macro("ERROR") +#undef ERROR +#pragma push_macro("ERROR_BUSY") +#undef ERROR_BUSY +#pragma push_macro("ERROR_INSTALL_FAILED") +#undef ERROR_INSTALL_FAILED +#pragma push_macro("ERROR_NOT_FOUND") +#undef ERROR_NOT_FOUND +#pragma push_macro("GetClassName") +#undef GetClassName +#pragma push_macro("GetMessage") +#undef GetMessage +#pragma push_macro("GetObject") +#undef GetObject +#pragma push_macro("IGNORE") +#undef IGNORE +#pragma push_macro("IN") +#undef IN +#pragma push_macro("INPUT_KEYBOARD") +#undef INPUT_KEYBOARD +#pragma push_macro("NO_ERROR") +#undef NO_ERROR +#pragma push_macro("OUT") +#undef OUT +#pragma push_macro("OPTIONAL") +#undef OPTIONAL +#pragma push_macro("min") +#undef min +#pragma push_macro("max") +#undef max +#pragma push_macro("NEAR") +#undef NEAR +#pragma push_macro("NO_DATA") +#undef NO_DATA +#pragma push_macro("REASON_UNKNOWN") +#undef REASON_UNKNOWN +#pragma push_macro("SERVICE_DISABLED") +#undef SERVICE_DISABLED +#pragma push_macro("SEVERITY_ERROR") +#undef SEVERITY_ERROR +#pragma push_macro("STATUS_PENDING") +#undef STATUS_PENDING +#pragma push_macro("STRICT") +#undef STRICT +#pragma push_macro("timezone") +#undef timezone +#endif // _MSC_VER + +#ifdef __APPLE__ +// Inconvenient macro names from usr/include/math.h in some macOS SDKs. +#pragma push_macro("DOMAIN") +#undef DOMAIN +// Inconvenient macro names from /usr/include/mach/boolean.h in some macOS SDKs. +#pragma push_macro("TRUE") +#undef TRUE +#pragma push_macro("FALSE") +#undef FALSE +// Inconvenient macro names from usr/include/sys/syslimits.h in some macOS SDKs. +#pragma push_macro("UID_MAX") +#undef UID_MAX +#endif // __APPLE__ + +#if defined(__clang__) || PROTOBUF_GNUC_MIN(3, 0) || defined(_MSC_VER) +// Don't let Objective-C Macros interfere with proto identifiers with the same +// name. +#pragma push_macro("DEBUG") +#undef DEBUG +#endif // defined(__clang__) || PROTOBUF_GNUC_MIN(3, 0) || defined(_MSC_VER) + +#if PROTOBUF_GNUC_MIN(3, 0) +// GCC does not allow disabling diagnostics within an expression: +// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=60875, so we disable this one +// globally even though it's only used for PROTOBUF_FIELD_OFFSET. +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Winvalid-offsetof" +#endif + +// Silence some MSVC warnings in all our code. +#ifdef _MSC_VER +#pragma warning(push) +// For non-trivial unions +#pragma warning(disable : 4582) +#pragma warning(disable : 4583) +// For init_seg(lib) +#pragma warning(disable : 4073) +// To silence the fact that we will pop this push from another file +#pragma warning(disable : 5031) +// Conditional expression is constant +#pragma warning(disable: 4127) +// decimal digit terminates octal escape sequence +#pragma warning(disable: 4125) +#endif + +// We don't want code outside port_def doing complex testing, so +// remove our portable condition test macros to nudge folks away from +// using it themselves. +#ifdef PROTOBUF_has_cpp_attribute_DEFINED_ +# undef __has_cpp_attribute +# undef PROTOBUF_has_cpp_attribute_DEFINED_ +#endif +#ifdef PROTOBUF_has_feature_DEFINED_ +# undef __has_feature +# undef PROTOBUF_has_feature_DEFINED_ +#endif +#ifdef PROTOBUF_has_warning_DEFINED_ +# undef __has_warning +# undef PROTOBUF_has_warning_DEFINED_ +#endif +#ifdef PROTOBUF_has_attribute_DEFINED_ +# undef __has_attribute +# undef PROTOBUF_has_attribute_DEFINED_ +#endif +#ifdef PROTOBUF_has_builtin_DEFINED_ +# undef __has_builtin +# undef PROTOBUF_has_builtin_DEFINED_ +#endif diff --git a/toolkit/components/protobuf/src/google/protobuf/port_undef.inc b/toolkit/components/protobuf/src/google/protobuf/port_undef.inc new file mode 100644 index 0000000000..e880fa5c59 --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/port_undef.inc @@ -0,0 +1,160 @@ +// 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. + +// #undefs all macros defined in port_def.inc. See comments in port_def.inc +// for more info. + +#ifndef PROTOBUF_NAMESPACE +#error "port_undef.inc must be included after port_def.inc" +#endif + +#undef PROTOBUF_BUILTIN_BSWAP16 +#undef PROTOBUF_BUILTIN_BSWAP32 +#undef PROTOBUF_BUILTIN_BSWAP64 +#undef PROTOBUF_GNUC_MIN +#undef PROTOBUF_MSC_VER_MIN +#undef PROTOBUF_CPLUSPLUS_MIN +#undef PROTOBUF_NAMESPACE +#undef PROTOBUF_NAMESPACE_ID +#undef PROTOBUF_ALWAYS_INLINE +#undef PROTOBUF_NDEBUG_INLINE +#undef PROTOBUF_MUSTTAIL +#undef PROTOBUF_TAILCALL +#undef PROTOBUF_COLD +#undef PROTOBUF_NOINLINE +#undef PROTOBUF_SECTION_VARIABLE +#undef PROTOBUF_DEPRECATED +#undef PROTOBUF_DEPRECATED_ENUM +#undef PROTOBUF_DEPRECATED_MSG +#undef PROTOBUF_FUNC_ALIGN +#undef PROTOBUF_RETURNS_NONNULL +#undef PROTOBUF_ATTRIBUTE_REINITIALIZES +#undef PROTOBUF_RTTI +#undef PROTOBUF_VERSION +#undef PROTOBUF_VERSION_SUFFIX +#undef PROTOBUF_FIELD_OFFSET +#undef PROTOBUF_MIN_HEADER_VERSION_FOR_PROTOC +#undef PROTOBUF_MIN_PROTOC_VERSION +#undef PROTOBUF_PREDICT_TRUE +#undef PROTOBUF_PREDICT_FALSE +#undef PROTOBUF_FALLTHROUGH_INTENDED +#undef PROTOBUF_EXPORT +#undef PROTOC_EXPORT +#undef PROTOBUF_NODISCARD +#undef PROTOBUF_FORCE_COPY_IN_RELEASE +#undef PROTOBUF_FORCE_COPY_IN_SWAP +#undef PROTOBUF_FORCE_COPY_IN_MOVE +#undef PROTOBUF_FORCE_RESET_IN_CLEAR +#undef PROTOBUF_FORCE_COPY_DEFAULT_STRING +#undef PROTOBUF_NAMESPACE_OPEN +#undef PROTOBUF_NAMESPACE_CLOSE +#undef PROTOBUF_UNUSED +#undef PROTOBUF_ASSUME +#undef PROTOBUF_EXPORT_TEMPLATE_DECLARE +#undef PROTOBUF_EXPORT_TEMPLATE_DEFINE +#undef PROTOBUF_ALIGNAS +#undef PROTOBUF_FINAL +#undef PROTOBUF_FUTURE_FINAL +#undef PROTOBUF_THREAD_LOCAL +#undef PROTOBUF_LITTLE_ENDIAN +#undef PROTOBUF_BIG_ENDIAN +#undef PROTOBUF_MESSAGE_OWNED_ARENA_EXPERIMENT +#undef PROTOBUF_CONSTINIT +#undef PROTOBUF_CONSTEXPR +#undef PROTOBUF_ATTRIBUTE_WEAK +#undef PROTOBUF_HAVE_ATTRIBUTE_WEAK +#undef PROTOBUF_ATTRIBUTE_NO_DESTROY +#undef PROTOBUF_ATTRIBUTE_STANDALONE_DEBUG +#undef PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 +#undef PROTOBUF_ATTRIBUTE_INIT_PRIORITY2 +#undef PROTOBUF_PRAGMA_INIT_SEG +#undef PROTOBUF_ASAN +#undef PROTOBUF_MSAN +#undef PROTOBUF_TSAN +#undef PROTOBUF_TAIL_CALL_TABLE_PARSER_ENABLED +#undef PROTOBUF_TC_PARAM_DECL +#undef PROTOBUF_EXCLUSIVE_LOCKS_REQUIRED +#undef PROTOBUF_LOCKS_EXCLUDED +#undef PROTOBUF_NO_THREAD_SAFETY_ANALYSIS +#undef PROTOBUF_GUARDED_BY + +#ifdef PROTOBUF_FUTURE_BREAKING_CHANGES +#undef PROTOBUF_FUTURE_BREAKING_CHANGES +#endif + +// Restore macro that may have been #undef'd in port_def.inc. +#ifdef _MSC_VER +#pragma pop_macro("CREATE_NEW") +#pragma pop_macro("DELETE") +#pragma pop_macro("DOUBLE_CLICK") +#pragma pop_macro("ERROR") +#pragma pop_macro("ERROR_BUSY") +#pragma pop_macro("ERROR_INSTALL_FAILED") +#pragma pop_macro("ERROR_NOT_FOUND") +#pragma pop_macro("GetClassName") +#pragma pop_macro("GetMessage") +#pragma pop_macro("GetObject") +#pragma pop_macro("IGNORE") +#pragma pop_macro("IN") +#pragma pop_macro("INPUT_KEYBOARD") +#pragma pop_macro("OUT") +#pragma pop_macro("OPTIONAL") +#pragma pop_macro("min") +#pragma pop_macro("max") +#pragma pop_macro("NEAR") +#pragma pop_macro("NO_DATA") +#pragma pop_macro("NO_ERROR") +#pragma pop_macro("REASON_UNKNOWN") +#pragma pop_macro("SERVICE_DISABLED") +#pragma pop_macro("SEVERITY_ERROR") +#pragma pop_macro("STRICT") +#pragma pop_macro("STATUS_PENDING") +#pragma pop_macro("timezone") +#endif + +#ifdef __APPLE__ +#pragma pop_macro("DOMAIN") +#pragma pop_macro("TRUE") +#pragma pop_macro("FALSE") +#pragma pop_macro("UID_MAX") +#endif // __APPLE__ + +#if defined(__clang__) || defined(__GNUC__) || defined(_MSC_VER) +#pragma pop_macro("DEBUG") +#endif // defined(__clang__) || defined(__GNUC__) || defined(_MSC_VER) + +#if defined(__GNUC__) +#pragma GCC diagnostic pop +#endif + +// Pop the warning(push) from port_def.inc +#ifdef _MSC_VER +#pragma warning(pop) +#endif diff --git a/toolkit/components/protobuf/src/google/protobuf/reflection.h b/toolkit/components/protobuf/src/google/protobuf/reflection.h new file mode 100644 index 0000000000..7b75a43f22 --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/reflection.h @@ -0,0 +1,570 @@ +// 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. + +// This header defines the RepeatedFieldRef class template used to access +// repeated fields with protobuf reflection API. +#ifndef GOOGLE_PROTOBUF_REFLECTION_H__ +#define GOOGLE_PROTOBUF_REFLECTION_H__ + + +#include <memory> + +#include <google/protobuf/message.h> +#include <google/protobuf/generated_enum_util.h> + +#ifdef SWIG +#error "You cannot SWIG proto headers" +#endif + +// Must be included last. +#include <google/protobuf/port_def.inc> + +namespace google { +namespace protobuf { +namespace internal { +template <typename T, typename Enable = void> +struct RefTypeTraits; +} // namespace internal + +template <typename T> +RepeatedFieldRef<T> Reflection::GetRepeatedFieldRef( + const Message& message, const FieldDescriptor* field) const { + return RepeatedFieldRef<T>(message, field); +} + +template <typename T> +MutableRepeatedFieldRef<T> Reflection::GetMutableRepeatedFieldRef( + Message* message, const FieldDescriptor* field) const { + return MutableRepeatedFieldRef<T>(message, field); +} + +// RepeatedFieldRef definition for non-message types. +template <typename T> +class RepeatedFieldRef< + T, typename std::enable_if<!std::is_base_of<Message, T>::value>::type> { + typedef typename internal::RefTypeTraits<T>::iterator IteratorType; + typedef typename internal::RefTypeTraits<T>::AccessorType AccessorType; + + public: + bool empty() const { return accessor_->IsEmpty(data_); } + int size() const { return accessor_->Size(data_); } + T Get(int index) const { return accessor_->template Get<T>(data_, index); } + + typedef IteratorType iterator; + typedef IteratorType const_iterator; + typedef T value_type; + typedef T& reference; + typedef const T& const_reference; + typedef int size_type; + typedef ptrdiff_t difference_type; + + iterator begin() const { return iterator(data_, accessor_, true); } + iterator end() const { return iterator(data_, accessor_, false); } + + private: + friend class Reflection; + RepeatedFieldRef(const Message& message, const FieldDescriptor* field) { + const Reflection* reflection = message.GetReflection(); + data_ = reflection->RepeatedFieldData(const_cast<Message*>(&message), field, + internal::RefTypeTraits<T>::cpp_type, + nullptr); + accessor_ = reflection->RepeatedFieldAccessor(field); + } + + const void* data_; + const AccessorType* accessor_; +}; + +// MutableRepeatedFieldRef definition for non-message types. +template <typename T> +class MutableRepeatedFieldRef< + T, typename std::enable_if<!std::is_base_of<Message, T>::value>::type> { + typedef typename internal::RefTypeTraits<T>::AccessorType AccessorType; + + public: + bool empty() const { return accessor_->IsEmpty(data_); } + int size() const { return accessor_->Size(data_); } + T Get(int index) const { return accessor_->template Get<T>(data_, index); } + + void Set(int index, const T& value) const { + accessor_->template Set<T>(data_, index, value); + } + void Add(const T& value) const { accessor_->template Add<T>(data_, value); } + void RemoveLast() const { accessor_->RemoveLast(data_); } + void SwapElements(int index1, int index2) const { + accessor_->SwapElements(data_, index1, index2); + } + void Clear() const { accessor_->Clear(data_); } + + void Swap(const MutableRepeatedFieldRef& other) const { + accessor_->Swap(data_, other.accessor_, other.data_); + } + + template <typename Container> + void MergeFrom(const Container& container) const { + typedef typename Container::const_iterator Iterator; + for (Iterator it = container.begin(); it != container.end(); ++it) { + Add(*it); + } + } + template <typename Container> + void CopyFrom(const Container& container) const { + Clear(); + MergeFrom(container); + } + + private: + friend class Reflection; + MutableRepeatedFieldRef(Message* message, const FieldDescriptor* field) { + const Reflection* reflection = message->GetReflection(); + data_ = reflection->RepeatedFieldData( + message, field, internal::RefTypeTraits<T>::cpp_type, nullptr); + accessor_ = reflection->RepeatedFieldAccessor(field); + } + + void* data_; + const AccessorType* accessor_; +}; + +// RepeatedFieldRef definition for message types. +template <typename T> +class RepeatedFieldRef< + T, typename std::enable_if<std::is_base_of<Message, T>::value>::type> { + typedef typename internal::RefTypeTraits<T>::iterator IteratorType; + typedef typename internal::RefTypeTraits<T>::AccessorType AccessorType; + + public: + bool empty() const { return accessor_->IsEmpty(data_); } + int size() const { return accessor_->Size(data_); } + // This method returns a reference to the underlying message object if it + // exists. If a message object doesn't exist (e.g., data stored in serialized + // form), scratch_space will be filled with the data and a reference to it + // will be returned. + // + // Example: + // RepeatedFieldRef<Message> h = ... + // unique_ptr<Message> scratch_space(h.NewMessage()); + // const Message& item = h.Get(index, scratch_space.get()); + const T& Get(int index, T* scratch_space) const { + return *static_cast<const T*>(accessor_->Get(data_, index, scratch_space)); + } + // Create a new message of the same type as the messages stored in this + // repeated field. Caller takes ownership of the returned object. + T* NewMessage() const { return static_cast<T*>(default_instance_->New()); } + + typedef IteratorType iterator; + typedef IteratorType const_iterator; + typedef T value_type; + typedef T& reference; + typedef const T& const_reference; + typedef int size_type; + typedef ptrdiff_t difference_type; + + iterator begin() const { + return iterator(data_, accessor_, true, NewMessage()); + } + iterator end() const { + // The end iterator must not be dereferenced, no need for scratch space. + return iterator(data_, accessor_, false, nullptr); + } + + private: + friend class Reflection; + RepeatedFieldRef(const Message& message, const FieldDescriptor* field) { + const Reflection* reflection = message.GetReflection(); + data_ = reflection->RepeatedFieldData( + const_cast<Message*>(&message), field, + internal::RefTypeTraits<T>::cpp_type, + internal::RefTypeTraits<T>::GetMessageFieldDescriptor()); + accessor_ = reflection->RepeatedFieldAccessor(field); + default_instance_ = + reflection->GetMessageFactory()->GetPrototype(field->message_type()); + } + + const void* data_; + const AccessorType* accessor_; + const Message* default_instance_; +}; + +// MutableRepeatedFieldRef definition for message types. +template <typename T> +class MutableRepeatedFieldRef< + T, typename std::enable_if<std::is_base_of<Message, T>::value>::type> { + typedef typename internal::RefTypeTraits<T>::AccessorType AccessorType; + + public: + bool empty() const { return accessor_->IsEmpty(data_); } + int size() const { return accessor_->Size(data_); } + // See comments for RepeatedFieldRef<Message>::Get() + const T& Get(int index, T* scratch_space) const { + return *static_cast<const T*>(accessor_->Get(data_, index, scratch_space)); + } + // Create a new message of the same type as the messages stored in this + // repeated field. Caller takes ownership of the returned object. + T* NewMessage() const { return static_cast<T*>(default_instance_->New()); } + + void Set(int index, const T& value) const { + accessor_->Set(data_, index, &value); + } + void Add(const T& value) const { accessor_->Add(data_, &value); } + void RemoveLast() const { accessor_->RemoveLast(data_); } + void SwapElements(int index1, int index2) const { + accessor_->SwapElements(data_, index1, index2); + } + void Clear() const { accessor_->Clear(data_); } + + void Swap(const MutableRepeatedFieldRef& other) const { + accessor_->Swap(data_, other.accessor_, other.data_); + } + + template <typename Container> + void MergeFrom(const Container& container) const { + typedef typename Container::const_iterator Iterator; + for (Iterator it = container.begin(); it != container.end(); ++it) { + Add(*it); + } + } + template <typename Container> + void CopyFrom(const Container& container) const { + Clear(); + MergeFrom(container); + } + + private: + friend class Reflection; + MutableRepeatedFieldRef(Message* message, const FieldDescriptor* field) { + const Reflection* reflection = message->GetReflection(); + data_ = reflection->RepeatedFieldData( + message, field, internal::RefTypeTraits<T>::cpp_type, + internal::RefTypeTraits<T>::GetMessageFieldDescriptor()); + accessor_ = reflection->RepeatedFieldAccessor(field); + default_instance_ = + reflection->GetMessageFactory()->GetPrototype(field->message_type()); + } + + void* data_; + const AccessorType* accessor_; + const Message* default_instance_; +}; + +namespace internal { +// Interfaces used to implement reflection RepeatedFieldRef API. +// Reflection::GetRepeatedAccessor() should return a pointer to an singleton +// object that implements the below interface. +// +// This interface passes/returns values using void pointers. The actual type +// of the value depends on the field's cpp_type. Following is a mapping from +// cpp_type to the type that should be used in this interface: +// +// field->cpp_type() T Actual type of void* +// CPPTYPE_INT32 int32_t int32_t +// CPPTYPE_UINT32 uint32_t uint32_t +// CPPTYPE_INT64 int64_t int64_t +// CPPTYPE_UINT64 uint64_t uint64_t +// CPPTYPE_DOUBLE double double +// CPPTYPE_FLOAT float float +// CPPTYPE_BOOL bool bool +// CPPTYPE_ENUM generated enum type int32_t +// CPPTYPE_STRING string std::string +// CPPTYPE_MESSAGE generated message type google::protobuf::Message +// or google::protobuf::Message +// +// Note that for enums we use int32_t in the interface. +// +// You can map from T to the actual type using RefTypeTraits: +// typedef RefTypeTraits<T>::AccessorValueType ActualType; +class PROTOBUF_EXPORT RepeatedFieldAccessor { + public: + // Typedefs for clarity. + typedef void Field; + typedef void Value; + typedef void Iterator; + + virtual bool IsEmpty(const Field* data) const = 0; + virtual int Size(const Field* data) const = 0; + // Depends on the underlying representation of the repeated field, this + // method can return a pointer to the underlying object if such an object + // exists, or fill the data into scratch_space and return scratch_space. + // Callers of this method must ensure scratch_space is a valid pointer + // to a mutable object of the correct type. + virtual const Value* Get(const Field* data, int index, + Value* scratch_space) const = 0; + + virtual void Clear(Field* data) const = 0; + virtual void Set(Field* data, int index, const Value* value) const = 0; + virtual void Add(Field* data, const Value* value) const = 0; + virtual void RemoveLast(Field* data) const = 0; + virtual void SwapElements(Field* data, int index1, int index2) const = 0; + virtual void Swap(Field* data, const RepeatedFieldAccessor* other_mutator, + Field* other_data) const = 0; + + // Create an iterator that points at the beginning of the repeated field. + virtual Iterator* BeginIterator(const Field* data) const = 0; + // Create an iterator that points at the end of the repeated field. + virtual Iterator* EndIterator(const Field* data) const = 0; + // Make a copy of an iterator and return the new copy. + virtual Iterator* CopyIterator(const Field* data, + const Iterator* iterator) const = 0; + // Move an iterator to point to the next element. + virtual Iterator* AdvanceIterator(const Field* data, + Iterator* iterator) const = 0; + // Compare whether two iterators point to the same element. + virtual bool EqualsIterator(const Field* data, const Iterator* a, + const Iterator* b) const = 0; + // Delete an iterator created by BeginIterator(), EndIterator() and + // CopyIterator(). + virtual void DeleteIterator(const Field* data, Iterator* iterator) const = 0; + // Like Get() but for iterators. + virtual const Value* GetIteratorValue(const Field* data, + const Iterator* iterator, + Value* scratch_space) const = 0; + + // Templated methods that make using this interface easier for non-message + // types. + template <typename T> + T Get(const Field* data, int index) const { + typedef typename RefTypeTraits<T>::AccessorValueType ActualType; + ActualType scratch_space; + return static_cast<T>(*reinterpret_cast<const ActualType*>( + Get(data, index, static_cast<Value*>(&scratch_space)))); + } + + template <typename T, typename ValueType> + void Set(Field* data, int index, const ValueType& value) const { + typedef typename RefTypeTraits<T>::AccessorValueType ActualType; + // In this RepeatedFieldAccessor interface we pass/return data using + // raw pointers. Type of the data these raw pointers point to should + // be ActualType. Here we have a ValueType object and want a ActualType + // pointer. We can't cast a ValueType pointer to an ActualType pointer + // directly because their type might be different (for enums ValueType + // may be a generated enum type while ActualType is int32_t). To be safe + // we make a copy to get a temporary ActualType object and use it. + ActualType tmp = static_cast<ActualType>(value); + Set(data, index, static_cast<const Value*>(&tmp)); + } + + template <typename T, typename ValueType> + void Add(Field* data, const ValueType& value) const { + typedef typename RefTypeTraits<T>::AccessorValueType ActualType; + // In this RepeatedFieldAccessor interface we pass/return data using + // raw pointers. Type of the data these raw pointers point to should + // be ActualType. Here we have a ValueType object and want a ActualType + // pointer. We can't cast a ValueType pointer to an ActualType pointer + // directly because their type might be different (for enums ValueType + // may be a generated enum type while ActualType is int32_t). To be safe + // we make a copy to get a temporary ActualType object and use it. + ActualType tmp = static_cast<ActualType>(value); + Add(data, static_cast<const Value*>(&tmp)); + } + + protected: + // We want the destructor to be completely trivial as to allow it to be + // a function local static. Hence we make it non-virtual and protected, + // this class only live as part of a global singleton and should not be + // deleted. + ~RepeatedFieldAccessor() = default; +}; + +// Implement (Mutable)RepeatedFieldRef::iterator +template <typename T> +class RepeatedFieldRefIterator { + typedef typename RefTypeTraits<T>::AccessorValueType AccessorValueType; + typedef typename RefTypeTraits<T>::IteratorValueType IteratorValueType; + typedef typename RefTypeTraits<T>::IteratorPointerType IteratorPointerType; + + public: + using iterator_category = std::forward_iterator_tag; + using value_type = T; + using pointer = T*; + using reference = T&; + using difference_type = std::ptrdiff_t; + + // Constructor for non-message fields. + RepeatedFieldRefIterator(const void* data, + const RepeatedFieldAccessor* accessor, bool begin) + : data_(data), + accessor_(accessor), + iterator_(begin ? accessor->BeginIterator(data) + : accessor->EndIterator(data)), + // The end iterator must not be dereferenced, no need for scratch space. + scratch_space_(begin ? new AccessorValueType : nullptr) {} + // Constructor for message fields. + RepeatedFieldRefIterator(const void* data, + const RepeatedFieldAccessor* accessor, bool begin, + AccessorValueType* scratch_space) + : data_(data), + accessor_(accessor), + iterator_(begin ? accessor->BeginIterator(data) + : accessor->EndIterator(data)), + scratch_space_(scratch_space) {} + ~RepeatedFieldRefIterator() { accessor_->DeleteIterator(data_, iterator_); } + RepeatedFieldRefIterator operator++(int) { + RepeatedFieldRefIterator tmp(*this); + iterator_ = accessor_->AdvanceIterator(data_, iterator_); + return tmp; + } + RepeatedFieldRefIterator& operator++() { + iterator_ = accessor_->AdvanceIterator(data_, iterator_); + return *this; + } + IteratorValueType operator*() const { + return static_cast<IteratorValueType>( + *static_cast<const AccessorValueType*>(accessor_->GetIteratorValue( + data_, iterator_, scratch_space_.get()))); + } + IteratorPointerType operator->() const { + return static_cast<IteratorPointerType>( + accessor_->GetIteratorValue(data_, iterator_, scratch_space_.get())); + } + bool operator!=(const RepeatedFieldRefIterator& other) const { + assert(data_ == other.data_); + assert(accessor_ == other.accessor_); + return !accessor_->EqualsIterator(data_, iterator_, other.iterator_); + } + bool operator==(const RepeatedFieldRefIterator& other) const { + return !this->operator!=(other); + } + + RepeatedFieldRefIterator(const RepeatedFieldRefIterator& other) + : data_(other.data_), + accessor_(other.accessor_), + iterator_(accessor_->CopyIterator(data_, other.iterator_)) {} + RepeatedFieldRefIterator& operator=(const RepeatedFieldRefIterator& other) { + if (this != &other) { + accessor_->DeleteIterator(data_, iterator_); + data_ = other.data_; + accessor_ = other.accessor_; + iterator_ = accessor_->CopyIterator(data_, other.iterator_); + } + return *this; + } + + protected: + const void* data_; + const RepeatedFieldAccessor* accessor_; + void* iterator_; + std::unique_ptr<AccessorValueType> scratch_space_; +}; + +// TypeTraits that maps the type parameter T of RepeatedFieldRef or +// MutableRepeatedFieldRef to corresponding iterator type, +// RepeatedFieldAccessor type, etc. +template <typename T> +struct PrimitiveTraits { + static constexpr bool is_primitive = false; +}; +#define DEFINE_PRIMITIVE(TYPE, type) \ + template <> \ + struct PrimitiveTraits<type> { \ + static const bool is_primitive = true; \ + static const FieldDescriptor::CppType cpp_type = \ + FieldDescriptor::CPPTYPE_##TYPE; \ + }; +DEFINE_PRIMITIVE(INT32, int32_t) +DEFINE_PRIMITIVE(UINT32, uint32_t) +DEFINE_PRIMITIVE(INT64, int64_t) +DEFINE_PRIMITIVE(UINT64, uint64_t) +DEFINE_PRIMITIVE(FLOAT, float) +DEFINE_PRIMITIVE(DOUBLE, double) +DEFINE_PRIMITIVE(BOOL, bool) +#undef DEFINE_PRIMITIVE + +template <typename T> +struct RefTypeTraits< + T, typename std::enable_if<PrimitiveTraits<T>::is_primitive>::type> { + typedef RepeatedFieldRefIterator<T> iterator; + typedef RepeatedFieldAccessor AccessorType; + typedef T AccessorValueType; + typedef T IteratorValueType; + typedef T* IteratorPointerType; + static constexpr FieldDescriptor::CppType cpp_type = + PrimitiveTraits<T>::cpp_type; + static const Descriptor* GetMessageFieldDescriptor() { return nullptr; } +}; + +template <typename T> +struct RefTypeTraits< + T, typename std::enable_if<is_proto_enum<T>::value>::type> { + typedef RepeatedFieldRefIterator<T> iterator; + typedef RepeatedFieldAccessor AccessorType; + // We use int32_t for repeated enums in RepeatedFieldAccessor. + typedef int32_t AccessorValueType; + typedef T IteratorValueType; + typedef int32_t* IteratorPointerType; + static constexpr FieldDescriptor::CppType cpp_type = + FieldDescriptor::CPPTYPE_ENUM; + static const Descriptor* GetMessageFieldDescriptor() { return nullptr; } +}; + +template <typename T> +struct RefTypeTraits< + T, typename std::enable_if<std::is_same<std::string, T>::value>::type> { + typedef RepeatedFieldRefIterator<T> iterator; + typedef RepeatedFieldAccessor AccessorType; + typedef std::string AccessorValueType; + typedef const std::string IteratorValueType; + typedef const std::string* IteratorPointerType; + static constexpr FieldDescriptor::CppType cpp_type = + FieldDescriptor::CPPTYPE_STRING; + static const Descriptor* GetMessageFieldDescriptor() { return nullptr; } +}; + +template <typename T> +struct MessageDescriptorGetter { + static const Descriptor* get() { + return T::default_instance().GetDescriptor(); + } +}; +template <> +struct MessageDescriptorGetter<Message> { + static const Descriptor* get() { return nullptr; } +}; + +template <typename T> +struct RefTypeTraits< + T, typename std::enable_if<std::is_base_of<Message, T>::value>::type> { + typedef RepeatedFieldRefIterator<T> iterator; + typedef RepeatedFieldAccessor AccessorType; + typedef Message AccessorValueType; + typedef const T& IteratorValueType; + typedef const T* IteratorPointerType; + static constexpr FieldDescriptor::CppType cpp_type = + FieldDescriptor::CPPTYPE_MESSAGE; + static const Descriptor* GetMessageFieldDescriptor() { + return MessageDescriptorGetter<T>::get(); + } +}; +} // namespace internal +} // namespace protobuf +} // namespace google + +#include <google/protobuf/port_undef.inc> + +#endif // GOOGLE_PROTOBUF_REFLECTION_H__ diff --git a/toolkit/components/protobuf/src/google/protobuf/reflection_internal.h b/toolkit/components/protobuf/src/google/protobuf/reflection_internal.h new file mode 100644 index 0000000000..f749c3eb11 --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/reflection_internal.h @@ -0,0 +1,364 @@ +// 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. + +#ifndef GOOGLE_PROTOBUF_REFLECTION_INTERNAL_H__ +#define GOOGLE_PROTOBUF_REFLECTION_INTERNAL_H__ + +#include <google/protobuf/map_field.h> +#include <google/protobuf/reflection.h> +#include <google/protobuf/repeated_field.h> + +namespace google { +namespace protobuf { +namespace internal { +// A base class for RepeatedFieldAccessor implementations that can support +// random-access efficiently. All iterator methods delegates the work to +// corresponding random-access methods. +class RandomAccessRepeatedFieldAccessor : public RepeatedFieldAccessor { + public: + Iterator* BeginIterator(const Field* /*data*/) const override { + return PositionToIterator(0); + } + Iterator* EndIterator(const Field* data) const override { + return PositionToIterator(this->Size(data)); + } + Iterator* CopyIterator(const Field* /*data*/, + const Iterator* iterator) const override { + return const_cast<Iterator*>(iterator); + } + Iterator* AdvanceIterator(const Field* /*data*/, + Iterator* iterator) const override { + return PositionToIterator(IteratorToPosition(iterator) + 1); + } + bool EqualsIterator(const Field* /*data*/, const Iterator* a, + const Iterator* b) const override { + return a == b; + } + void DeleteIterator(const Field* /*data*/, + Iterator* /*iterator*/) const override {} + const Value* GetIteratorValue(const Field* data, const Iterator* iterator, + Value* scratch_space) const override { + return Get(data, static_cast<int>(IteratorToPosition(iterator)), + scratch_space); + } + + protected: + ~RandomAccessRepeatedFieldAccessor() = default; + + private: + static intptr_t IteratorToPosition(const Iterator* iterator) { + return reinterpret_cast<intptr_t>(iterator); + } + static Iterator* PositionToIterator(intptr_t position) { + return reinterpret_cast<Iterator*>(position); + } +}; + +// Base class for RepeatedFieldAccessor implementations that manipulates +// RepeatedField<T>. +template <typename T> +class RepeatedFieldWrapper : public RandomAccessRepeatedFieldAccessor { + public: + RepeatedFieldWrapper() {} + bool IsEmpty(const Field* data) const override { + return GetRepeatedField(data)->empty(); + } + int Size(const Field* data) const override { + return GetRepeatedField(data)->size(); + } + const Value* Get(const Field* data, int index, + Value* scratch_space) const override { + return ConvertFromT(GetRepeatedField(data)->Get(index), scratch_space); + } + void Clear(Field* data) const override { + MutableRepeatedField(data)->Clear(); + } + void Set(Field* data, int index, const Value* value) const override { + MutableRepeatedField(data)->Set(index, ConvertToT(value)); + } + void Add(Field* data, const Value* value) const override { + MutableRepeatedField(data)->Add(ConvertToT(value)); + } + void RemoveLast(Field* data) const override { + MutableRepeatedField(data)->RemoveLast(); + } + void SwapElements(Field* data, int index1, int index2) const override { + MutableRepeatedField(data)->SwapElements(index1, index2); + } + + protected: + ~RepeatedFieldWrapper() = default; + typedef RepeatedField<T> RepeatedFieldType; + static const RepeatedFieldType* GetRepeatedField(const Field* data) { + return reinterpret_cast<const RepeatedFieldType*>(data); + } + static RepeatedFieldType* MutableRepeatedField(Field* data) { + return reinterpret_cast<RepeatedFieldType*>(data); + } + + // Convert an object received by this accessor to an object to be stored in + // the underlying RepeatedField. + virtual T ConvertToT(const Value* value) const = 0; + + // Convert an object stored in RepeatedPtrField to an object that will be + // returned by this accessor. If the two objects have the same type (true for + // string fields with ctype=STRING), a pointer to the source object can be + // returned directly. Otherwise, data should be copied from value to + // scratch_space and scratch_space should be returned. + virtual const Value* ConvertFromT(const T& value, + Value* scratch_space) const = 0; +}; + +// Base class for RepeatedFieldAccessor implementations that manipulates +// RepeatedPtrField<T>. +template <typename T> +class RepeatedPtrFieldWrapper : public RandomAccessRepeatedFieldAccessor { + public: + bool IsEmpty(const Field* data) const override { + return GetRepeatedField(data)->empty(); + } + int Size(const Field* data) const override { + return GetRepeatedField(data)->size(); + } + const Value* Get(const Field* data, int index, + Value* scratch_space) const override { + return ConvertFromT(GetRepeatedField(data)->Get(index), scratch_space); + } + void Clear(Field* data) const override { + MutableRepeatedField(data)->Clear(); + } + void Set(Field* data, int index, const Value* value) const override { + ConvertToT(value, MutableRepeatedField(data)->Mutable(index)); + } + void Add(Field* data, const Value* value) const override { + T* allocated = New(value); + ConvertToT(value, allocated); + MutableRepeatedField(data)->AddAllocated(allocated); + } + void RemoveLast(Field* data) const override { + MutableRepeatedField(data)->RemoveLast(); + } + void SwapElements(Field* data, int index1, int index2) const override { + MutableRepeatedField(data)->SwapElements(index1, index2); + } + + protected: + ~RepeatedPtrFieldWrapper() = default; + typedef RepeatedPtrField<T> RepeatedFieldType; + static const RepeatedFieldType* GetRepeatedField(const Field* data) { + return reinterpret_cast<const RepeatedFieldType*>(data); + } + static RepeatedFieldType* MutableRepeatedField(Field* data) { + return reinterpret_cast<RepeatedFieldType*>(data); + } + + // Create a new T instance. For repeated message fields, T can be specified + // as google::protobuf::Message so we can't use "new T()" directly. In that case, value + // should be a message of the same type (it's ensured by the caller) and a + // new message object will be created using it. + virtual T* New(const Value* value) const = 0; + + // Convert an object received by this accessor to an object that will be + // stored in the underlying RepeatedPtrField. + virtual void ConvertToT(const Value* value, T* result) const = 0; + + // Convert an object stored in RepeatedPtrField to an object that will be + // returned by this accessor. If the two objects have the same type (true for + // string fields with ctype=STRING), a pointer to the source object can be + // returned directly. Otherwise, data should be copied from value to + // scratch_space and scratch_space should be returned. + virtual const Value* ConvertFromT(const T& value, + Value* scratch_space) const = 0; +}; + +// An implementation of RandomAccessRepeatedFieldAccessor that manipulates +// MapFieldBase. +class MapFieldAccessor final : public RandomAccessRepeatedFieldAccessor { + public: + MapFieldAccessor() {} + virtual ~MapFieldAccessor() {} + bool IsEmpty(const Field* data) const override { + return GetRepeatedField(data)->empty(); + } + int Size(const Field* data) const override { + return GetRepeatedField(data)->size(); + } + const Value* Get(const Field* data, int index, + Value* scratch_space) const override { + return ConvertFromEntry(GetRepeatedField(data)->Get(index), scratch_space); + } + void Clear(Field* data) const override { + MutableRepeatedField(data)->Clear(); + } + void Set(Field* data, int index, const Value* value) const override { + ConvertToEntry(value, MutableRepeatedField(data)->Mutable(index)); + } + void Add(Field* data, const Value* value) const override { + Message* allocated = New(value); + ConvertToEntry(value, allocated); + MutableRepeatedField(data)->AddAllocated(allocated); + } + void RemoveLast(Field* data) const override { + MutableRepeatedField(data)->RemoveLast(); + } + void SwapElements(Field* data, int index1, int index2) const override { + MutableRepeatedField(data)->SwapElements(index1, index2); + } + void Swap(Field* data, const internal::RepeatedFieldAccessor* other_mutator, + Field* other_data) const override { + GOOGLE_CHECK(this == other_mutator); + MutableRepeatedField(data)->Swap(MutableRepeatedField(other_data)); + } + + protected: + typedef RepeatedPtrField<Message> RepeatedFieldType; + static const RepeatedFieldType* GetRepeatedField(const Field* data) { + return reinterpret_cast<const RepeatedFieldType*>( + (&reinterpret_cast<const MapFieldBase*>(data)->GetRepeatedField())); + } + static RepeatedFieldType* MutableRepeatedField(Field* data) { + return reinterpret_cast<RepeatedFieldType*>( + reinterpret_cast<MapFieldBase*>(data)->MutableRepeatedField()); + } + virtual Message* New(const Value* value) const { + return static_cast<const Message*>(value)->New(); + } + // Convert an object received by this accessor to an MapEntry message to be + // stored in the underlying MapFieldBase. + virtual void ConvertToEntry(const Value* value, Message* result) const { + result->CopyFrom(*static_cast<const Message*>(value)); + } + // Convert a MapEntry message stored in the underlying MapFieldBase to an + // object that will be returned by this accessor. + virtual const Value* ConvertFromEntry(const Message& value, + Value* /*scratch_space*/) const { + return static_cast<const Value*>(&value); + } +}; + +// Default implementations of RepeatedFieldAccessor for primitive types. +template <typename T> +class RepeatedFieldPrimitiveAccessor final : public RepeatedFieldWrapper<T> { + typedef void Field; + typedef void Value; + using RepeatedFieldWrapper<T>::MutableRepeatedField; + + public: + RepeatedFieldPrimitiveAccessor() {} + void Swap(Field* data, const internal::RepeatedFieldAccessor* other_mutator, + Field* other_data) const override { + // Currently RepeatedFieldPrimitiveAccessor is the only implementation of + // RepeatedFieldAccessor for primitive types. As we are using singletons + // for these accessors, here "other_mutator" must be "this". + GOOGLE_CHECK(this == other_mutator); + MutableRepeatedField(data)->Swap(MutableRepeatedField(other_data)); + } + + protected: + T ConvertToT(const Value* value) const override { + return *static_cast<const T*>(value); + } + const Value* ConvertFromT(const T& value, + Value* /*scratch_space*/) const override { + return static_cast<const Value*>(&value); + } +}; + +// Default implementation of RepeatedFieldAccessor for string fields with +// ctype=STRING. +class RepeatedPtrFieldStringAccessor final + : public RepeatedPtrFieldWrapper<std::string> { + typedef void Field; + typedef void Value; + using RepeatedFieldAccessor::Add; + + public: + RepeatedPtrFieldStringAccessor() {} + void Swap(Field* data, const internal::RepeatedFieldAccessor* other_mutator, + Field* other_data) const override { + if (this == other_mutator) { + MutableRepeatedField(data)->Swap(MutableRepeatedField(other_data)); + } else { + RepeatedPtrField<std::string> tmp; + tmp.Swap(MutableRepeatedField(data)); + int other_size = other_mutator->Size(other_data); + for (int i = 0; i < other_size; ++i) { + Add<std::string>(data, other_mutator->Get<std::string>(other_data, i)); + } + int size = Size(data); + other_mutator->Clear(other_data); + for (int i = 0; i < size; ++i) { + other_mutator->Add<std::string>(other_data, tmp.Get(i)); + } + } + } + + protected: + std::string* New(const Value*) const override { return new std::string(); } + void ConvertToT(const Value* value, std::string* result) const override { + *result = *static_cast<const std::string*>(value); + } + const Value* ConvertFromT(const std::string& value, + Value* /*scratch_space*/) const override { + return static_cast<const Value*>(&value); + } +}; + + +class RepeatedPtrFieldMessageAccessor final + : public RepeatedPtrFieldWrapper<Message> { + typedef void Field; + typedef void Value; + + public: + RepeatedPtrFieldMessageAccessor() {} + void Swap(Field* data, const internal::RepeatedFieldAccessor* other_mutator, + Field* other_data) const override { + GOOGLE_CHECK(this == other_mutator); + MutableRepeatedField(data)->Swap(MutableRepeatedField(other_data)); + } + + protected: + Message* New(const Value* value) const override { + return static_cast<const Message*>(value)->New(); + } + void ConvertToT(const Value* value, Message* result) const override { + result->CopyFrom(*static_cast<const Message*>(value)); + } + const Value* ConvertFromT(const Message& value, + Value* /*scratch_space*/) const override { + return static_cast<const Value*>(&value); + } +}; +} // namespace internal +} // namespace protobuf +} // namespace google + +#endif // GOOGLE_PROTOBUF_REFLECTION_INTERNAL_H__ diff --git a/toolkit/components/protobuf/src/google/protobuf/reflection_ops.cc b/toolkit/components/protobuf/src/google/protobuf/reflection_ops.cc new file mode 100644 index 0000000000..3a1972e274 --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/reflection_ops.cc @@ -0,0 +1,459 @@ +// 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. + +// Author: kenton@google.com (Kenton Varda) +// Based on original Protocol Buffers design by +// Sanjay Ghemawat, Jeff Dean, and others. +#include <google/protobuf/reflection_ops.h> + +#include <string> +#include <vector> + +#include <google/protobuf/stubs/logging.h> +#include <google/protobuf/stubs/common.h> +#include <google/protobuf/descriptor.h> +#include <google/protobuf/descriptor.pb.h> +#include <google/protobuf/map_field.h> +#include <google/protobuf/map_field_inl.h> +#include <google/protobuf/unknown_field_set.h> + +// Must be included last. +#include <google/protobuf/port_def.inc> + +namespace google { +namespace protobuf { +namespace internal { + +static const Reflection* GetReflectionOrDie(const Message& m) { + const Reflection* r = m.GetReflection(); + if (r == nullptr) { + const Descriptor* d = m.GetDescriptor(); + const std::string& mtype = d ? d->name() : "unknown"; + // RawMessage is one known type for which GetReflection() returns nullptr. + GOOGLE_LOG(FATAL) << "Message does not support reflection (type " << mtype << ")."; + } + return r; +} + +void ReflectionOps::Copy(const Message& from, Message* to) { + if (&from == to) return; + Clear(to); + Merge(from, to); +} + +void ReflectionOps::Merge(const Message& from, Message* to) { + GOOGLE_CHECK_NE(&from, to); + + const Descriptor* descriptor = from.GetDescriptor(); + GOOGLE_CHECK_EQ(to->GetDescriptor(), descriptor) + << "Tried to merge messages of different types " + << "(merge " << descriptor->full_name() << " to " + << to->GetDescriptor()->full_name() << ")"; + + const Reflection* from_reflection = GetReflectionOrDie(from); + const Reflection* to_reflection = GetReflectionOrDie(*to); + bool is_from_generated = (from_reflection->GetMessageFactory() == + google::protobuf::MessageFactory::generated_factory()); + bool is_to_generated = (to_reflection->GetMessageFactory() == + google::protobuf::MessageFactory::generated_factory()); + + std::vector<const FieldDescriptor*> fields; + from_reflection->ListFieldsOmitStripped(from, &fields); + for (const FieldDescriptor* field : fields) { + if (field->is_repeated()) { + // Use map reflection if both are in map status and have the + // same map type to avoid sync with repeated field. + // Note: As from and to messages have the same descriptor, the + // map field types are the same if they are both generated + // messages or both dynamic messages. + if (is_from_generated == is_to_generated && field->is_map()) { + const MapFieldBase* from_field = + from_reflection->GetMapData(from, field); + MapFieldBase* to_field = to_reflection->MutableMapData(to, field); + if (to_field->IsMapValid() && from_field->IsMapValid()) { + to_field->MergeFrom(*from_field); + continue; + } + } + int count = from_reflection->FieldSize(from, field); + for (int j = 0; j < count; j++) { + switch (field->cpp_type()) { +#define HANDLE_TYPE(CPPTYPE, METHOD) \ + case FieldDescriptor::CPPTYPE_##CPPTYPE: \ + to_reflection->Add##METHOD( \ + to, field, from_reflection->GetRepeated##METHOD(from, field, j)); \ + break; + + HANDLE_TYPE(INT32, Int32); + HANDLE_TYPE(INT64, Int64); + HANDLE_TYPE(UINT32, UInt32); + HANDLE_TYPE(UINT64, UInt64); + HANDLE_TYPE(FLOAT, Float); + HANDLE_TYPE(DOUBLE, Double); + HANDLE_TYPE(BOOL, Bool); + HANDLE_TYPE(STRING, String); + HANDLE_TYPE(ENUM, Enum); +#undef HANDLE_TYPE + + case FieldDescriptor::CPPTYPE_MESSAGE: + const Message& from_child = + from_reflection->GetRepeatedMessage(from, field, j); + if (from_reflection == to_reflection) { + to_reflection + ->AddMessage(to, field, + from_child.GetReflection()->GetMessageFactory()) + ->MergeFrom(from_child); + } else { + to_reflection->AddMessage(to, field)->MergeFrom(from_child); + } + break; + } + } + } else { + switch (field->cpp_type()) { +#define HANDLE_TYPE(CPPTYPE, METHOD) \ + case FieldDescriptor::CPPTYPE_##CPPTYPE: \ + to_reflection->Set##METHOD(to, field, \ + from_reflection->Get##METHOD(from, field)); \ + break; + + HANDLE_TYPE(INT32, Int32); + HANDLE_TYPE(INT64, Int64); + HANDLE_TYPE(UINT32, UInt32); + HANDLE_TYPE(UINT64, UInt64); + HANDLE_TYPE(FLOAT, Float); + HANDLE_TYPE(DOUBLE, Double); + HANDLE_TYPE(BOOL, Bool); + HANDLE_TYPE(STRING, String); + HANDLE_TYPE(ENUM, Enum); +#undef HANDLE_TYPE + + case FieldDescriptor::CPPTYPE_MESSAGE: + const Message& from_child = from_reflection->GetMessage(from, field); + if (from_reflection == to_reflection) { + to_reflection + ->MutableMessage( + to, field, from_child.GetReflection()->GetMessageFactory()) + ->MergeFrom(from_child); + } else { + to_reflection->MutableMessage(to, field)->MergeFrom(from_child); + } + break; + } + } + } + + if (!from_reflection->GetUnknownFields(from).empty()) { + to_reflection->MutableUnknownFields(to)->MergeFrom( + from_reflection->GetUnknownFields(from)); + } +} + +void ReflectionOps::Clear(Message* message) { + const Reflection* reflection = GetReflectionOrDie(*message); + + std::vector<const FieldDescriptor*> fields; + reflection->ListFieldsOmitStripped(*message, &fields); + for (const FieldDescriptor* field : fields) { + reflection->ClearField(message, field); + } + + if (reflection->GetInternalMetadata(*message).have_unknown_fields()) { + reflection->MutableUnknownFields(message)->Clear(); + } +} + +bool ReflectionOps::IsInitialized(const Message& message, bool check_fields, + bool check_descendants) { + const Descriptor* descriptor = message.GetDescriptor(); + const Reflection* reflection = GetReflectionOrDie(message); + if (const int field_count = descriptor->field_count()) { + const FieldDescriptor* begin = descriptor->field(0); + const FieldDescriptor* end = begin + field_count; + GOOGLE_DCHECK_EQ(descriptor->field(field_count - 1), end - 1); + + if (check_fields) { + // Check required fields of this message. + for (const FieldDescriptor* field = begin; field != end; ++field) { + if (field->is_required() && !reflection->HasField(message, field)) { + return false; + } + } + } + + if (check_descendants) { + for (const FieldDescriptor* field = begin; field != end; ++field) { + if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { + const Descriptor* message_type = field->message_type(); + if (PROTOBUF_PREDICT_FALSE(message_type->options().map_entry())) { + if (message_type->field(1)->cpp_type() == + FieldDescriptor::CPPTYPE_MESSAGE) { + const MapFieldBase* map_field = + reflection->GetMapData(message, field); + if (map_field->IsMapValid()) { + MapIterator it(const_cast<Message*>(&message), field); + MapIterator end_map(const_cast<Message*>(&message), field); + for (map_field->MapBegin(&it), map_field->MapEnd(&end_map); + it != end_map; ++it) { + if (!it.GetValueRef().GetMessageValue().IsInitialized()) { + return false; + } + } + } + } + } else if (field->is_repeated()) { + const int size = reflection->FieldSize(message, field); + for (int j = 0; j < size; j++) { + if (!reflection->GetRepeatedMessage(message, field, j) + .IsInitialized()) { + return false; + } + } + } else if (reflection->HasField(message, field)) { + if (!reflection->GetMessage(message, field).IsInitialized()) { + return false; + } + } + } + } + } + } + if (check_descendants && reflection->HasExtensionSet(message) && + !reflection->GetExtensionSet(message).IsInitialized()) { + return false; + } + return true; +} + +bool ReflectionOps::IsInitialized(const Message& message) { + const Descriptor* descriptor = message.GetDescriptor(); + const Reflection* reflection = GetReflectionOrDie(message); + + // Check required fields of this message. + { + const int field_count = descriptor->field_count(); + for (int i = 0; i < field_count; i++) { + if (descriptor->field(i)->is_required()) { + if (!reflection->HasField(message, descriptor->field(i))) { + return false; + } + } + } + } + + // Check that sub-messages are initialized. + std::vector<const FieldDescriptor*> fields; + // Should be safe to skip stripped fields because required fields are not + // stripped. + reflection->ListFieldsOmitStripped(message, &fields); + for (const FieldDescriptor* field : fields) { + if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { + + if (field->is_map()) { + const FieldDescriptor* value_field = field->message_type()->field(1); + if (value_field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { + const MapFieldBase* map_field = + reflection->GetMapData(message, field); + if (map_field->IsMapValid()) { + MapIterator iter(const_cast<Message*>(&message), field); + MapIterator end(const_cast<Message*>(&message), field); + for (map_field->MapBegin(&iter), map_field->MapEnd(&end); + iter != end; ++iter) { + if (!iter.GetValueRef().GetMessageValue().IsInitialized()) { + return false; + } + } + continue; + } + } else { + continue; + } + } + + if (field->is_repeated()) { + int size = reflection->FieldSize(message, field); + + for (int j = 0; j < size; j++) { + if (!reflection->GetRepeatedMessage(message, field, j) + .IsInitialized()) { + return false; + } + } + } else { + if (!reflection->GetMessage(message, field).IsInitialized()) { + return false; + } + } + } + } + + return true; +} + +static bool IsMapValueMessageTyped(const FieldDescriptor* map_field) { + return map_field->message_type()->field(1)->cpp_type() == + FieldDescriptor::CPPTYPE_MESSAGE; +} + +void ReflectionOps::DiscardUnknownFields(Message* message) { + const Reflection* reflection = GetReflectionOrDie(*message); + + reflection->MutableUnknownFields(message)->Clear(); + + // Walk through the fields of this message and DiscardUnknownFields on any + // messages present. + std::vector<const FieldDescriptor*> fields; + reflection->ListFields(*message, &fields); + for (const FieldDescriptor* field : fields) { + // Skip over non-message fields. + if (field->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE) { + continue; + } + // Discard the unknown fields in maps that contain message values. + if (field->is_map() && IsMapValueMessageTyped(field)) { + const MapFieldBase* map_field = + reflection->MutableMapData(message, field); + if (map_field->IsMapValid()) { + MapIterator iter(message, field); + MapIterator end(message, field); + for (map_field->MapBegin(&iter), map_field->MapEnd(&end); iter != end; + ++iter) { + iter.MutableValueRef()->MutableMessageValue()->DiscardUnknownFields(); + } + } + // Discard every unknown field inside messages in a repeated field. + } else if (field->is_repeated()) { + int size = reflection->FieldSize(*message, field); + for (int j = 0; j < size; j++) { + reflection->MutableRepeatedMessage(message, field, j) + ->DiscardUnknownFields(); + } + // Discard the unknown fields inside an optional message. + } else { + reflection->MutableMessage(message, field)->DiscardUnknownFields(); + } + } +} + +static std::string SubMessagePrefix(const std::string& prefix, + const FieldDescriptor* field, int index) { + std::string result(prefix); + if (field->is_extension()) { + result.append("("); + result.append(field->full_name()); + result.append(")"); + } else { + result.append(field->name()); + } + if (index != -1) { + result.append("["); + result.append(StrCat(index)); + result.append("]"); + } + result.append("."); + return result; +} + +void ReflectionOps::FindInitializationErrors(const Message& message, + const std::string& prefix, + std::vector<std::string>* errors) { + const Descriptor* descriptor = message.GetDescriptor(); + const Reflection* reflection = GetReflectionOrDie(message); + + // Check required fields of this message. + { + const int field_count = descriptor->field_count(); + for (int i = 0; i < field_count; i++) { + if (descriptor->field(i)->is_required()) { + if (!reflection->HasField(message, descriptor->field(i))) { + errors->push_back(prefix + descriptor->field(i)->name()); + } + } + } + } + + // Check sub-messages. + std::vector<const FieldDescriptor*> fields; + reflection->ListFieldsOmitStripped(message, &fields); + for (const FieldDescriptor* field : fields) { + if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { + + if (field->is_repeated()) { + int size = reflection->FieldSize(message, field); + + for (int j = 0; j < size; j++) { + const Message& sub_message = + reflection->GetRepeatedMessage(message, field, j); + FindInitializationErrors(sub_message, + SubMessagePrefix(prefix, field, j), errors); + } + } else { + const Message& sub_message = reflection->GetMessage(message, field); + FindInitializationErrors(sub_message, + SubMessagePrefix(prefix, field, -1), errors); + } + } + } +} + +void GenericSwap(Message* lhs, Message* rhs) { +#ifndef PROTOBUF_FORCE_COPY_IN_SWAP + GOOGLE_DCHECK(Arena::InternalGetOwningArena(lhs) != + Arena::InternalGetOwningArena(rhs)); + GOOGLE_DCHECK(Arena::InternalGetOwningArena(lhs) != nullptr || + Arena::InternalGetOwningArena(rhs) != nullptr); +#endif // !PROTOBUF_FORCE_COPY_IN_SWAP + // At least one of these must have an arena, so make `rhs` point to it. + Arena* arena = Arena::InternalGetOwningArena(rhs); + if (arena == nullptr) { + std::swap(lhs, rhs); + arena = Arena::InternalGetOwningArena(rhs); + } + + // Improve efficiency by placing the temporary on an arena so that messages + // are copied twice rather than three times. + Message* tmp = rhs->New(arena); + tmp->CheckTypeAndMergeFrom(*lhs); + lhs->Clear(); + lhs->CheckTypeAndMergeFrom(*rhs); +#ifdef PROTOBUF_FORCE_COPY_IN_SWAP + rhs->Clear(); + rhs->CheckTypeAndMergeFrom(*tmp); + if (arena == nullptr) delete tmp; +#else // PROTOBUF_FORCE_COPY_IN_SWAP + rhs->GetReflection()->Swap(tmp, rhs); +#endif // !PROTOBUF_FORCE_COPY_IN_SWAP +} + +} // namespace internal +} // namespace protobuf +} // namespace google + +#include <google/protobuf/port_undef.inc> diff --git a/toolkit/components/protobuf/src/google/protobuf/reflection_ops.h b/toolkit/components/protobuf/src/google/protobuf/reflection_ops.h new file mode 100644 index 0000000000..0a45702f9b --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/reflection_ops.h @@ -0,0 +1,92 @@ +// 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. + +// Author: kenton@google.com (Kenton Varda) +// Based on original Protocol Buffers design by +// Sanjay Ghemawat, Jeff Dean, and others. +// +// This header is logically internal, but is made public because it is used +// from protocol-compiler-generated code, which may reside in other components. + +#ifndef GOOGLE_PROTOBUF_REFLECTION_OPS_H__ +#define GOOGLE_PROTOBUF_REFLECTION_OPS_H__ + +#include <google/protobuf/stubs/common.h> +#include <google/protobuf/message.h> + +#ifdef SWIG +#error "You cannot SWIG proto headers" +#endif + +// Must be included last. +#include <google/protobuf/port_def.inc> + +namespace google { +namespace protobuf { +namespace internal { + +// Basic operations that can be performed using reflection. +// These can be used as a cheap way to implement the corresponding +// methods of the Message interface, though they are likely to be +// slower than implementations tailored for the specific message type. +// +// This class should stay limited to operations needed to implement +// the Message interface. +// +// This class is really a namespace that contains only static methods. +class PROTOBUF_EXPORT ReflectionOps { + public: + static void Copy(const Message& from, Message* to); + static void Merge(const Message& from, Message* to); + static void Clear(Message* message); + static bool IsInitialized(const Message& message); + static bool IsInitialized(const Message& message, bool check_fields, + bool check_descendants); + static void DiscardUnknownFields(Message* message); + + // Finds all unset required fields in the message and adds their full + // paths (e.g. "foo.bar[5].baz") to *names. "prefix" will be attached to + // the front of each name. + static void FindInitializationErrors(const Message& message, + const std::string& prefix, + std::vector<std::string>* errors); + + private: + // All methods are static. No need to construct. + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ReflectionOps); +}; + +} // namespace internal +} // namespace protobuf +} // namespace google + +#include <google/protobuf/port_undef.inc> + +#endif // GOOGLE_PROTOBUF_REFLECTION_OPS_H__ diff --git a/toolkit/components/protobuf/src/google/protobuf/repeated_field.cc b/toolkit/components/protobuf/src/google/protobuf/repeated_field.cc new file mode 100644 index 0000000000..7264d0a1e3 --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/repeated_field.cc @@ -0,0 +1,71 @@ +// 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. + +// Author: kenton@google.com (Kenton Varda) +// Based on original Protocol Buffers design by +// Sanjay Ghemawat, Jeff Dean, and others. + +#include <google/protobuf/repeated_field.h> + +#include <algorithm> + +#include <google/protobuf/stubs/logging.h> +#include <google/protobuf/stubs/common.h> + +// Must be included last. +#include <google/protobuf/port_def.inc> + +namespace google { +namespace protobuf { + + +template class PROTOBUF_EXPORT_TEMPLATE_DEFINE RepeatedField<bool>; +template class PROTOBUF_EXPORT_TEMPLATE_DEFINE RepeatedField<int32_t>; +template class PROTOBUF_EXPORT_TEMPLATE_DEFINE RepeatedField<uint32_t>; +template class PROTOBUF_EXPORT_TEMPLATE_DEFINE RepeatedField<int64_t>; +template class PROTOBUF_EXPORT_TEMPLATE_DEFINE RepeatedField<uint64_t>; +template class PROTOBUF_EXPORT_TEMPLATE_DEFINE RepeatedField<float>; +template class PROTOBUF_EXPORT_TEMPLATE_DEFINE RepeatedField<double>; +template class PROTOBUF_EXPORT_TEMPLATE_DEFINE RepeatedPtrField<std::string>; + +namespace internal { +template class PROTOBUF_EXPORT_TEMPLATE_DEFINE RepeatedIterator<bool>; +template class PROTOBUF_EXPORT_TEMPLATE_DEFINE RepeatedIterator<int32_t>; +template class PROTOBUF_EXPORT_TEMPLATE_DEFINE RepeatedIterator<uint32_t>; +template class PROTOBUF_EXPORT_TEMPLATE_DEFINE RepeatedIterator<int64_t>; +template class PROTOBUF_EXPORT_TEMPLATE_DEFINE RepeatedIterator<uint64_t>; +template class PROTOBUF_EXPORT_TEMPLATE_DEFINE RepeatedIterator<float>; +template class PROTOBUF_EXPORT_TEMPLATE_DEFINE RepeatedIterator<double>; +} // namespace internal + +} // namespace protobuf +} // namespace google + +#include <google/protobuf/port_undef.inc> diff --git a/toolkit/components/protobuf/src/google/protobuf/repeated_field.h b/toolkit/components/protobuf/src/google/protobuf/repeated_field.h new file mode 100644 index 0000000000..3fb734e5cb --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/repeated_field.h @@ -0,0 +1,1219 @@ +// 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. + +// Author: kenton@google.com (Kenton Varda) +// Based on original Protocol Buffers design by +// Sanjay Ghemawat, Jeff Dean, and others. +// +// RepeatedField and RepeatedPtrField are used by generated protocol message +// classes to manipulate repeated fields. These classes are very similar to +// STL's vector, but include a number of optimizations found to be useful +// specifically in the case of Protocol Buffers. RepeatedPtrField is +// particularly different from STL vector as it manages ownership of the +// pointers that it contains. +// +// This header covers RepeatedField. + +#ifndef GOOGLE_PROTOBUF_REPEATED_FIELD_H__ +#define GOOGLE_PROTOBUF_REPEATED_FIELD_H__ + + +#include <algorithm> +#include <iterator> +#include <limits> +#include <string> +#include <type_traits> +#include <utility> + +#include <google/protobuf/stubs/logging.h> +#include <google/protobuf/stubs/common.h> +#include <google/protobuf/arena.h> +#include <google/protobuf/port.h> +#include <google/protobuf/message_lite.h> +#include <google/protobuf/repeated_ptr_field.h> + + +// Must be included last. +#include <google/protobuf/port_def.inc> + +#ifdef SWIG +#error "You cannot SWIG proto headers" +#endif + +namespace google { +namespace protobuf { + +class Message; + +namespace internal { + +template <typename T, int kRepHeaderSize> +constexpr int RepeatedFieldLowerClampLimit() { + // The header is padded to be at least `sizeof(T)` when it would be smaller + // otherwise. + static_assert(sizeof(T) <= kRepHeaderSize, ""); + // We want to pad the minimum size to be a power of two bytes, including the + // header. + // The first allocation is kRepHeaderSize bytes worth of elements for a total + // of 2*kRepHeaderSize bytes. + // For an 8-byte header, we allocate 8 bool, 2 ints, or 1 int64. + return kRepHeaderSize / sizeof(T); +} + +// kRepeatedFieldUpperClampLimit is the lowest signed integer value that +// overflows when multiplied by 2 (which is undefined behavior). Sizes above +// this will clamp to the maximum int value instead of following exponential +// growth when growing a repeated field. +constexpr int kRepeatedFieldUpperClampLimit = + (std::numeric_limits<int>::max() / 2) + 1; + +template <typename Iter> +inline int CalculateReserve(Iter begin, Iter end, std::forward_iterator_tag) { + return static_cast<int>(std::distance(begin, end)); +} + +template <typename Iter> +inline int CalculateReserve(Iter /*begin*/, Iter /*end*/, + std::input_iterator_tag /*unused*/) { + return -1; +} + +template <typename Iter> +inline int CalculateReserve(Iter begin, Iter end) { + typedef typename std::iterator_traits<Iter>::iterator_category Category; + return CalculateReserve(begin, end, Category()); +} + +// Swaps two blocks of memory of size sizeof(T). +template <typename T> +inline void SwapBlock(char* p, char* q) { + T tmp; + memcpy(&tmp, p, sizeof(T)); + memcpy(p, q, sizeof(T)); + memcpy(q, &tmp, sizeof(T)); +} + +// Swaps two blocks of memory of size kSize: +// template <int kSize> void memswap(char* p, char* q); +template <int kSize> +inline typename std::enable_if<(kSize == 0), void>::type memswap(char*, char*) { +} + +#define PROTO_MEMSWAP_DEF_SIZE(reg_type, max_size) \ + template <int kSize> \ + typename std::enable_if<(kSize >= sizeof(reg_type) && kSize < (max_size)), \ + void>::type \ + memswap(char* p, char* q) { \ + SwapBlock<reg_type>(p, q); \ + memswap<kSize - sizeof(reg_type)>(p + sizeof(reg_type), \ + q + sizeof(reg_type)); \ + } + +PROTO_MEMSWAP_DEF_SIZE(uint8_t, 2) +PROTO_MEMSWAP_DEF_SIZE(uint16_t, 4) +PROTO_MEMSWAP_DEF_SIZE(uint32_t, 8) + +#ifdef __SIZEOF_INT128__ +PROTO_MEMSWAP_DEF_SIZE(uint64_t, 16) +PROTO_MEMSWAP_DEF_SIZE(__uint128_t, (1u << 31)) +#else +PROTO_MEMSWAP_DEF_SIZE(uint64_t, (1u << 31)) +#endif + +#undef PROTO_MEMSWAP_DEF_SIZE + +template <typename Element> +class RepeatedIterator; + +} // namespace internal + +// RepeatedField is used to represent repeated fields of a primitive type (in +// other words, everything except strings and nested Messages). Most users will +// not ever use a RepeatedField directly; they will use the get-by-index, +// set-by-index, and add accessors that are generated for all repeated fields. +template <typename Element> +class RepeatedField final { + static_assert( + alignof(Arena) >= alignof(Element), + "We only support types that have an alignment smaller than Arena"); + + public: + constexpr RepeatedField(); + explicit RepeatedField(Arena* arena); + + RepeatedField(const RepeatedField& other); + + template <typename Iter, + typename = typename std::enable_if<std::is_constructible< + Element, decltype(*std::declval<Iter>())>::value>::type> + RepeatedField(Iter begin, Iter end); + + ~RepeatedField(); + + RepeatedField& operator=(const RepeatedField& other); + + RepeatedField(RepeatedField&& other) noexcept; + RepeatedField& operator=(RepeatedField&& other) noexcept; + + bool empty() const; + int size() const; + + const Element& Get(int index) const; + Element* Mutable(int index); + + const Element& operator[](int index) const { return Get(index); } + Element& operator[](int index) { return *Mutable(index); } + + const Element& at(int index) const; + Element& at(int index); + + void Set(int index, const Element& value); + void Add(const Element& value); + // Appends a new element and returns a pointer to it. + // The new element is uninitialized if |Element| is a POD type. + Element* Add(); + // Appends elements in the range [begin, end) after reserving + // the appropriate number of elements. + template <typename Iter> + void Add(Iter begin, Iter end); + + // Removes the last element in the array. + void RemoveLast(); + + // Extracts elements with indices in "[start .. start+num-1]". + // Copies them into "elements[0 .. num-1]" if "elements" is not nullptr. + // Caution: also moves elements with indices [start+num ..]. + // Calling this routine inside a loop can cause quadratic behavior. + void ExtractSubrange(int start, int num, Element* elements); + + PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear(); + void MergeFrom(const RepeatedField& other); + PROTOBUF_ATTRIBUTE_REINITIALIZES void CopyFrom(const RepeatedField& other); + + // Replaces the contents with RepeatedField(begin, end). + template <typename Iter> + PROTOBUF_ATTRIBUTE_REINITIALIZES void Assign(Iter begin, Iter end); + + // Reserves space to expand the field to at least the given size. If the + // array is grown, it will always be at least doubled in size. + void Reserve(int new_size); + + // Resizes the RepeatedField to a new, smaller size. This is O(1). + void Truncate(int new_size); + + void AddAlreadyReserved(const Element& value); + // Appends a new element and return a pointer to it. + // The new element is uninitialized if |Element| is a POD type. + // Should be called only if Capacity() > Size(). + Element* AddAlreadyReserved(); + Element* AddNAlreadyReserved(int elements); + int Capacity() const; + + // Like STL resize. Uses value to fill appended elements. + // Like Truncate() if new_size <= size(), otherwise this is + // O(new_size - size()). + void Resize(int new_size, const Element& value); + + // Gets the underlying array. This pointer is possibly invalidated by + // any add or remove operation. + Element* mutable_data(); + const Element* data() const; + + // Swaps entire contents with "other". If they are separate arenas then, + // copies data between each other. + void Swap(RepeatedField* other); + + // Swaps entire contents with "other". Should be called only if the caller can + // guarantee that both repeated fields are on the same arena or are on the + // heap. Swapping between different arenas is disallowed and caught by a + // GOOGLE_DCHECK (see API docs for details). + void UnsafeArenaSwap(RepeatedField* other); + + // Swaps two elements. + void SwapElements(int index1, int index2); + + // STL-like iterator support + typedef internal::RepeatedIterator<Element> iterator; + typedef internal::RepeatedIterator<const Element> const_iterator; + typedef Element value_type; + typedef value_type& reference; + typedef const value_type& const_reference; + typedef value_type* pointer; + typedef const value_type* const_pointer; + typedef int size_type; + typedef ptrdiff_t difference_type; + + iterator begin(); + const_iterator begin() const; + const_iterator cbegin() const; + iterator end(); + const_iterator end() const; + const_iterator cend() const; + + // Reverse iterator support + typedef std::reverse_iterator<const_iterator> const_reverse_iterator; + typedef std::reverse_iterator<iterator> reverse_iterator; + reverse_iterator rbegin() { return reverse_iterator(end()); } + const_reverse_iterator rbegin() const { + return const_reverse_iterator(end()); + } + reverse_iterator rend() { return reverse_iterator(begin()); } + const_reverse_iterator rend() const { + return const_reverse_iterator(begin()); + } + + // Returns the number of bytes used by the repeated field, excluding + // sizeof(*this) + size_t SpaceUsedExcludingSelfLong() const; + + int SpaceUsedExcludingSelf() const { + return internal::ToIntSize(SpaceUsedExcludingSelfLong()); + } + + // Removes the element referenced by position. + // + // Returns an iterator to the element immediately following the removed + // element. + // + // Invalidates all iterators at or after the removed element, including end(). + iterator erase(const_iterator position); + + // Removes the elements in the range [first, last). + // + // Returns an iterator to the element immediately following the removed range. + // + // Invalidates all iterators at or after the removed range, including end(). + iterator erase(const_iterator first, const_iterator last); + + // Gets the Arena on which this RepeatedField stores its elements. + inline Arena* GetArena() const { + return GetOwningArena(); + } + + // For internal use only. + // + // This is public due to it being called by generated code. + inline void InternalSwap(RepeatedField* other); + + private: + template <typename T> friend class Arena::InternalHelper; + + // Gets the Arena on which this RepeatedField stores its elements. + inline Arena* GetOwningArena() const { + return (total_size_ == 0) ? static_cast<Arena*>(arena_or_elements_) + : rep()->arena; + } + + static constexpr int kInitialSize = 0; + // A note on the representation here (see also comment below for + // RepeatedPtrFieldBase's struct Rep): + // + // We maintain the same sizeof(RepeatedField) as before we added arena support + // so that we do not degrade performance by bloating memory usage. Directly + // adding an arena_ element to RepeatedField is quite costly. By using + // indirection in this way, we keep the same size when the RepeatedField is + // empty (common case), and add only an 8-byte header to the elements array + // when non-empty. We make sure to place the size fields directly in the + // RepeatedField class to avoid costly cache misses due to the indirection. + int current_size_; + int total_size_; + // Pad the Rep after arena allow for power-of-two byte sizes when + // sizeof(Element) > sizeof(Arena*). eg for 16-byte objects. + static PROTOBUF_CONSTEXPR const size_t kRepHeaderSize = + sizeof(Arena*) < sizeof(Element) ? sizeof(Element) : sizeof(Arena*); + struct Rep { + Arena* arena; + Element* elements() { + return reinterpret_cast<Element*>(reinterpret_cast<char*>(this) + + kRepHeaderSize); + } + }; + + // If total_size_ == 0 this points to an Arena otherwise it points to the + // elements member of a Rep struct. Using this invariant allows the storage of + // the arena pointer without an extra allocation in the constructor. + void* arena_or_elements_; + + // Returns a pointer to elements array. + // pre-condition: the array must have been allocated. + Element* elements() const { + GOOGLE_DCHECK_GT(total_size_, 0); + // Because of above pre-condition this cast is safe. + return unsafe_elements(); + } + + // Returns a pointer to elements array if it exists; otherwise either null or + // an invalid pointer is returned. This only happens for empty repeated + // fields, where you can't dereference this pointer anyway (it's empty). + Element* unsafe_elements() const { + return static_cast<Element*>(arena_or_elements_); + } + + // Returns a pointer to the Rep struct. + // pre-condition: the Rep must have been allocated, ie elements() is safe. + Rep* rep() const { + return reinterpret_cast<Rep*>(reinterpret_cast<char*>(elements()) - + kRepHeaderSize); + } + + friend class Arena; + typedef void InternalArenaConstructable_; + + // Moves the contents of |from| into |to|, possibly clobbering |from| in the + // process. For primitive types this is just a memcpy(), but it could be + // specialized for non-primitive types to, say, swap each element instead. + void MoveArray(Element* to, Element* from, int size); + + // Copies the elements of |from| into |to|. + void CopyArray(Element* to, const Element* from, int size); + + // Internal helper to delete all elements and deallocate the storage. + void InternalDeallocate(Rep* rep, int size, bool in_destructor) { + if (rep != nullptr) { + Element* e = &rep->elements()[0]; + if (!std::is_trivial<Element>::value) { + Element* limit = &rep->elements()[size]; + for (; e < limit; e++) { + e->~Element(); + } + } + const size_t bytes = size * sizeof(*e) + kRepHeaderSize; + if (rep->arena == nullptr) { + internal::SizedDelete(rep, bytes); + } else if (!in_destructor) { + // If we are in the destructor, we might be being destroyed as part of + // the arena teardown. We can't try and return blocks to the arena then. + rep->arena->ReturnArrayMemory(rep, bytes); + } + } + } + + // This class is a performance wrapper around RepeatedField::Add(const T&) + // function. In general unless a RepeatedField is a local stack variable LLVM + // has a hard time optimizing Add. The machine code tends to be + // loop: + // mov %size, dword ptr [%repeated_field] // load + // cmp %size, dword ptr [%repeated_field + 4] + // jae fallback + // mov %buffer, qword ptr [%repeated_field + 8] + // mov dword [%buffer + %size * 4], %value + // inc %size // increment + // mov dword ptr [%repeated_field], %size // store + // jmp loop + // + // This puts a load/store in each iteration of the important loop variable + // size. It's a pretty bad compile that happens even in simple cases, but + // largely the presence of the fallback path disturbs the compilers mem-to-reg + // analysis. + // + // This class takes ownership of a repeated field for the duration of its + // lifetime. The repeated field should not be accessed during this time, ie. + // only access through this class is allowed. This class should always be a + // function local stack variable. Intended use + // + // void AddSequence(const int* begin, const int* end, RepeatedField<int>* out) + // { + // RepeatedFieldAdder<int> adder(out); // Take ownership of out + // for (auto it = begin; it != end; ++it) { + // adder.Add(*it); + // } + // } + // + // Typically, due to the fact that adder is a local stack variable, the + // compiler will be successful in mem-to-reg transformation and the machine + // code will be loop: cmp %size, %capacity jae fallback mov dword ptr [%buffer + // + %size * 4], %val inc %size jmp loop + // + // The first version executes at 7 cycles per iteration while the second + // version executes at only 1 or 2 cycles. + template <int = 0, bool = std::is_trivial<Element>::value> + class FastAdderImpl { + public: + explicit FastAdderImpl(RepeatedField* rf) : repeated_field_(rf) { + index_ = repeated_field_->current_size_; + capacity_ = repeated_field_->total_size_; + buffer_ = repeated_field_->unsafe_elements(); + } + ~FastAdderImpl() { repeated_field_->current_size_ = index_; } + + void Add(Element val) { + if (index_ == capacity_) { + repeated_field_->current_size_ = index_; + repeated_field_->Reserve(index_ + 1); + capacity_ = repeated_field_->total_size_; + buffer_ = repeated_field_->unsafe_elements(); + } + buffer_[index_++] = val; + } + + private: + RepeatedField* repeated_field_; + int index_; + int capacity_; + Element* buffer_; + + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FastAdderImpl); + }; + + // FastAdder is a wrapper for adding fields. The specialization above handles + // POD types more efficiently than RepeatedField. + template <int I> + class FastAdderImpl<I, false> { + public: + explicit FastAdderImpl(RepeatedField* rf) : repeated_field_(rf) {} + void Add(const Element& val) { repeated_field_->Add(val); } + + private: + RepeatedField* repeated_field_; + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FastAdderImpl); + }; + + using FastAdder = FastAdderImpl<>; + + friend class TestRepeatedFieldHelper; + friend class ::google::protobuf::internal::ParseContext; +}; + +namespace internal { + +// This is a helper template to copy an array of elements efficiently when they +// have a trivial copy constructor, and correctly otherwise. This really +// shouldn't be necessary, but our compiler doesn't optimize std::copy very +// effectively. +template <typename Element, + bool HasTrivialCopy = std::is_trivial<Element>::value> +struct ElementCopier { + void operator()(Element* to, const Element* from, int array_size); +}; + +} // namespace internal + +// implementation ==================================================== + +template <typename Element> +constexpr RepeatedField<Element>::RepeatedField() + : current_size_(0), total_size_(0), arena_or_elements_(nullptr) {} + +template <typename Element> +inline RepeatedField<Element>::RepeatedField(Arena* arena) + : current_size_(0), total_size_(0), arena_or_elements_(arena) {} + +template <typename Element> +inline RepeatedField<Element>::RepeatedField(const RepeatedField& other) + : current_size_(0), total_size_(0), arena_or_elements_(nullptr) { + if (other.current_size_ != 0) { + Reserve(other.size()); + AddNAlreadyReserved(other.size()); + CopyArray(Mutable(0), &other.Get(0), other.size()); + } +} + +template <typename Element> +template <typename Iter, typename> +RepeatedField<Element>::RepeatedField(Iter begin, Iter end) + : current_size_(0), total_size_(0), arena_or_elements_(nullptr) { + Add(begin, end); +} + +template <typename Element> +RepeatedField<Element>::~RepeatedField() { +#ifndef NDEBUG + // Try to trigger segfault / asan failure in non-opt builds if arena_ + // lifetime has ended before the destructor. + auto arena = GetOwningArena(); + if (arena) (void)arena->SpaceAllocated(); +#endif + if (total_size_ > 0) { + InternalDeallocate(rep(), total_size_, true); + } +} + +template <typename Element> +inline RepeatedField<Element>& RepeatedField<Element>::operator=( + const RepeatedField& other) { + if (this != &other) CopyFrom(other); + return *this; +} + +template <typename Element> +inline RepeatedField<Element>::RepeatedField(RepeatedField&& other) noexcept + : RepeatedField() { +#ifdef PROTOBUF_FORCE_COPY_IN_MOVE + CopyFrom(other); +#else // PROTOBUF_FORCE_COPY_IN_MOVE + // We don't just call Swap(&other) here because it would perform 3 copies if + // other is on an arena. This field can't be on an arena because arena + // construction always uses the Arena* accepting constructor. + if (other.GetOwningArena()) { + CopyFrom(other); + } else { + InternalSwap(&other); + } +#endif // !PROTOBUF_FORCE_COPY_IN_MOVE +} + +template <typename Element> +inline RepeatedField<Element>& RepeatedField<Element>::operator=( + RepeatedField&& other) noexcept { + // We don't just call Swap(&other) here because it would perform 3 copies if + // the two fields are on different arenas. + if (this != &other) { + if (GetOwningArena() != other.GetOwningArena() +#ifdef PROTOBUF_FORCE_COPY_IN_MOVE + || GetOwningArena() == nullptr +#endif // !PROTOBUF_FORCE_COPY_IN_MOVE + ) { + CopyFrom(other); + } else { + InternalSwap(&other); + } + } + return *this; +} + +template <typename Element> +inline bool RepeatedField<Element>::empty() const { + return current_size_ == 0; +} + +template <typename Element> +inline int RepeatedField<Element>::size() const { + return current_size_; +} + +template <typename Element> +inline int RepeatedField<Element>::Capacity() const { + return total_size_; +} + +template <typename Element> +inline void RepeatedField<Element>::AddAlreadyReserved(const Element& value) { + GOOGLE_DCHECK_LT(current_size_, total_size_); + elements()[current_size_++] = value; +} + +template <typename Element> +inline Element* RepeatedField<Element>::AddAlreadyReserved() { + GOOGLE_DCHECK_LT(current_size_, total_size_); + return &elements()[current_size_++]; +} + +template <typename Element> +inline Element* RepeatedField<Element>::AddNAlreadyReserved(int elements) { + GOOGLE_DCHECK_GE(total_size_ - current_size_, elements) + << total_size_ << ", " << current_size_; + // Warning: sometimes people call this when elements == 0 and + // total_size_ == 0. In this case the return pointer points to a zero size + // array (n == 0). Hence we can just use unsafe_elements(), because the user + // cannot dereference the pointer anyway. + Element* ret = unsafe_elements() + current_size_; + current_size_ += elements; + return ret; +} + +template <typename Element> +inline void RepeatedField<Element>::Resize(int new_size, const Element& value) { + GOOGLE_DCHECK_GE(new_size, 0); + if (new_size > current_size_) { + Reserve(new_size); + std::fill(&elements()[current_size_], &elements()[new_size], value); + } + current_size_ = new_size; +} + +template <typename Element> +inline const Element& RepeatedField<Element>::Get(int index) const { + GOOGLE_DCHECK_GE(index, 0); + GOOGLE_DCHECK_LT(index, current_size_); + return elements()[index]; +} + +template <typename Element> +inline const Element& RepeatedField<Element>::at(int index) const { + GOOGLE_CHECK_GE(index, 0); + GOOGLE_CHECK_LT(index, current_size_); + return elements()[index]; +} + +template <typename Element> +inline Element& RepeatedField<Element>::at(int index) { + GOOGLE_CHECK_GE(index, 0); + GOOGLE_CHECK_LT(index, current_size_); + return elements()[index]; +} + +template <typename Element> +inline Element* RepeatedField<Element>::Mutable(int index) { + GOOGLE_DCHECK_GE(index, 0); + GOOGLE_DCHECK_LT(index, current_size_); + return &elements()[index]; +} + +template <typename Element> +inline void RepeatedField<Element>::Set(int index, const Element& value) { + GOOGLE_DCHECK_GE(index, 0); + GOOGLE_DCHECK_LT(index, current_size_); + elements()[index] = value; +} + +template <typename Element> +inline void RepeatedField<Element>::Add(const Element& value) { + uint32_t size = current_size_; + if (static_cast<int>(size) == total_size_) { + // value could reference an element of the array. Reserving new space will + // invalidate the reference. So we must make a copy first. + auto tmp = value; + Reserve(total_size_ + 1); + elements()[size] = std::move(tmp); + } else { + elements()[size] = value; + } + current_size_ = size + 1; +} + +template <typename Element> +inline Element* RepeatedField<Element>::Add() { + uint32_t size = current_size_; + if (static_cast<int>(size) == total_size_) Reserve(total_size_ + 1); + auto ptr = &elements()[size]; + current_size_ = size + 1; + return ptr; +} + +template <typename Element> +template <typename Iter> +inline void RepeatedField<Element>::Add(Iter begin, Iter end) { + int reserve = internal::CalculateReserve(begin, end); + if (reserve != -1) { + if (reserve == 0) { + return; + } + + Reserve(reserve + size()); + // TODO(ckennelly): The compiler loses track of the buffer freshly + // allocated by Reserve() by the time we call elements, so it cannot + // guarantee that elements does not alias [begin(), end()). + // + // If restrict is available, annotating the pointer obtained from elements() + // causes this to lower to memcpy instead of memmove. + std::copy(begin, end, elements() + size()); + current_size_ = reserve + size(); + } else { + FastAdder fast_adder(this); + for (; begin != end; ++begin) fast_adder.Add(*begin); + } +} + +template <typename Element> +inline void RepeatedField<Element>::RemoveLast() { + GOOGLE_DCHECK_GT(current_size_, 0); + current_size_--; +} + +template <typename Element> +void RepeatedField<Element>::ExtractSubrange(int start, int num, + Element* elements) { + GOOGLE_DCHECK_GE(start, 0); + GOOGLE_DCHECK_GE(num, 0); + GOOGLE_DCHECK_LE(start + num, this->current_size_); + + // Save the values of the removed elements if requested. + if (elements != nullptr) { + for (int i = 0; i < num; ++i) elements[i] = this->Get(i + start); + } + + // Slide remaining elements down to fill the gap. + if (num > 0) { + for (int i = start + num; i < this->current_size_; ++i) + this->Set(i - num, this->Get(i)); + this->Truncate(this->current_size_ - num); + } +} + +template <typename Element> +inline void RepeatedField<Element>::Clear() { + current_size_ = 0; +} + +template <typename Element> +inline void RepeatedField<Element>::MergeFrom(const RepeatedField& other) { + GOOGLE_DCHECK_NE(&other, this); + if (other.current_size_ != 0) { + int existing_size = size(); + Reserve(existing_size + other.size()); + AddNAlreadyReserved(other.size()); + CopyArray(Mutable(existing_size), &other.Get(0), other.size()); + } +} + +template <typename Element> +inline void RepeatedField<Element>::CopyFrom(const RepeatedField& other) { + if (&other == this) return; + Clear(); + MergeFrom(other); +} + +template <typename Element> +template <typename Iter> +inline void RepeatedField<Element>::Assign(Iter begin, Iter end) { + Clear(); + Add(begin, end); +} + +template <typename Element> +inline typename RepeatedField<Element>::iterator RepeatedField<Element>::erase( + const_iterator position) { + return erase(position, position + 1); +} + +template <typename Element> +inline typename RepeatedField<Element>::iterator RepeatedField<Element>::erase( + const_iterator first, const_iterator last) { + size_type first_offset = first - cbegin(); + if (first != last) { + Truncate(std::copy(last, cend(), begin() + first_offset) - cbegin()); + } + return begin() + first_offset; +} + +template <typename Element> +inline Element* RepeatedField<Element>::mutable_data() { + return unsafe_elements(); +} + +template <typename Element> +inline const Element* RepeatedField<Element>::data() const { + return unsafe_elements(); +} + +template <typename Element> +inline void RepeatedField<Element>::InternalSwap(RepeatedField* other) { + GOOGLE_DCHECK(this != other); + + // Swap all fields at once. + static_assert(std::is_standard_layout<RepeatedField<Element>>::value, + "offsetof() requires standard layout before c++17"); + internal::memswap<offsetof(RepeatedField, arena_or_elements_) + + sizeof(this->arena_or_elements_) - + offsetof(RepeatedField, current_size_)>( + reinterpret_cast<char*>(this) + offsetof(RepeatedField, current_size_), + reinterpret_cast<char*>(other) + offsetof(RepeatedField, current_size_)); +} + +template <typename Element> +void RepeatedField<Element>::Swap(RepeatedField* other) { + if (this == other) return; +#ifdef PROTOBUF_FORCE_COPY_IN_SWAP + if (GetOwningArena() != nullptr && + GetOwningArena() == other->GetOwningArena()) { +#else // PROTOBUF_FORCE_COPY_IN_SWAP + if (GetOwningArena() == other->GetOwningArena()) { +#endif // !PROTOBUF_FORCE_COPY_IN_SWAP + InternalSwap(other); + } else { + RepeatedField<Element> temp(other->GetOwningArena()); + temp.MergeFrom(*this); + CopyFrom(*other); + other->UnsafeArenaSwap(&temp); + } +} + +template <typename Element> +void RepeatedField<Element>::UnsafeArenaSwap(RepeatedField* other) { + if (this == other) return; + GOOGLE_DCHECK_EQ(GetOwningArena(), other->GetOwningArena()); + InternalSwap(other); +} + +template <typename Element> +void RepeatedField<Element>::SwapElements(int index1, int index2) { + using std::swap; // enable ADL with fallback + swap(elements()[index1], elements()[index2]); +} + +template <typename Element> +inline typename RepeatedField<Element>::iterator +RepeatedField<Element>::begin() { + return iterator(unsafe_elements()); +} +template <typename Element> +inline typename RepeatedField<Element>::const_iterator +RepeatedField<Element>::begin() const { + return const_iterator(unsafe_elements()); +} +template <typename Element> +inline typename RepeatedField<Element>::const_iterator +RepeatedField<Element>::cbegin() const { + return const_iterator(unsafe_elements()); +} +template <typename Element> +inline typename RepeatedField<Element>::iterator RepeatedField<Element>::end() { + return iterator(unsafe_elements() + current_size_); +} +template <typename Element> +inline typename RepeatedField<Element>::const_iterator +RepeatedField<Element>::end() const { + return const_iterator(unsafe_elements() + current_size_); +} +template <typename Element> +inline typename RepeatedField<Element>::const_iterator +RepeatedField<Element>::cend() const { + return const_iterator(unsafe_elements() + current_size_); +} + +template <typename Element> +inline size_t RepeatedField<Element>::SpaceUsedExcludingSelfLong() const { + return total_size_ > 0 ? (total_size_ * sizeof(Element) + kRepHeaderSize) : 0; +} + +namespace internal { +// Returns the new size for a reserved field based on its 'total_size' and the +// requested 'new_size'. The result is clamped to the closed interval: +// [internal::kMinRepeatedFieldAllocationSize, +// std::numeric_limits<int>::max()] +// Requires: +// new_size > total_size && +// (total_size == 0 || +// total_size >= kRepeatedFieldLowerClampLimit) +template <typename T, int kRepHeaderSize> +inline int CalculateReserveSize(int total_size, int new_size) { + constexpr int lower_limit = RepeatedFieldLowerClampLimit<T, kRepHeaderSize>(); + if (new_size < lower_limit) { + // Clamp to smallest allowed size. + return lower_limit; + } + constexpr int kMaxSizeBeforeClamp = + (std::numeric_limits<int>::max() - kRepHeaderSize) / 2; + if (PROTOBUF_PREDICT_FALSE(total_size > kMaxSizeBeforeClamp)) { + return std::numeric_limits<int>::max(); + } + // We want to double the number of bytes, not the number of elements, to try + // to stay within power-of-two allocations. + // The allocation has kRepHeaderSize + sizeof(T) * capacity. + int doubled_size = 2 * total_size + kRepHeaderSize / sizeof(T); + return std::max(doubled_size, new_size); +} +} // namespace internal + +// Avoid inlining of Reserve(): new, copy, and delete[] lead to a significant +// amount of code bloat. +template <typename Element> +void RepeatedField<Element>::Reserve(int new_size) { + if (total_size_ >= new_size) return; + Rep* old_rep = total_size_ > 0 ? rep() : nullptr; + Rep* new_rep; + Arena* arena = GetOwningArena(); + + new_size = internal::CalculateReserveSize<Element, kRepHeaderSize>( + total_size_, new_size); + + GOOGLE_DCHECK_LE( + static_cast<size_t>(new_size), + (std::numeric_limits<size_t>::max() - kRepHeaderSize) / sizeof(Element)) + << "Requested size is too large to fit into size_t."; + size_t bytes = + kRepHeaderSize + sizeof(Element) * static_cast<size_t>(new_size); + if (arena == nullptr) { + new_rep = static_cast<Rep*>(::operator new(bytes)); + } else { + new_rep = reinterpret_cast<Rep*>(Arena::CreateArray<char>(arena, bytes)); + } + new_rep->arena = arena; + int old_total_size = total_size_; + // Already known: new_size >= internal::kMinRepeatedFieldAllocationSize + // Maintain invariant: + // total_size_ == 0 || + // total_size_ >= internal::kMinRepeatedFieldAllocationSize + total_size_ = new_size; + arena_or_elements_ = new_rep->elements(); + // Invoke placement-new on newly allocated elements. We shouldn't have to do + // this, since Element is supposed to be POD, but a previous version of this + // code allocated storage with "new Element[size]" and some code uses + // RepeatedField with non-POD types, relying on constructor invocation. If + // Element has a trivial constructor (e.g., int32_t), gcc (tested with -O2) + // completely removes this loop because the loop body is empty, so this has no + // effect unless its side-effects are required for correctness. + // Note that we do this before MoveArray() below because Element's copy + // assignment implementation will want an initialized instance first. + Element* e = &elements()[0]; + Element* limit = e + total_size_; + for (; e < limit; e++) { + new (e) Element; + } + if (current_size_ > 0) { + MoveArray(&elements()[0], old_rep->elements(), current_size_); + } + + // Likewise, we need to invoke destructors on the old array. + InternalDeallocate(old_rep, old_total_size, false); + +} + +template <typename Element> +inline void RepeatedField<Element>::Truncate(int new_size) { + GOOGLE_DCHECK_LE(new_size, current_size_); + if (current_size_ > 0) { + current_size_ = new_size; + } +} + +template <typename Element> +inline void RepeatedField<Element>::MoveArray(Element* to, Element* from, + int array_size) { + CopyArray(to, from, array_size); +} + +template <typename Element> +inline void RepeatedField<Element>::CopyArray(Element* to, const Element* from, + int array_size) { + internal::ElementCopier<Element>()(to, from, array_size); +} + +namespace internal { + +template <typename Element, bool HasTrivialCopy> +void ElementCopier<Element, HasTrivialCopy>::operator()(Element* to, + const Element* from, + int array_size) { + std::copy(from, from + array_size, to); +} + +template <typename Element> +struct ElementCopier<Element, true> { + void operator()(Element* to, const Element* from, int array_size) { + memcpy(to, from, static_cast<size_t>(array_size) * sizeof(Element)); + } +}; + +} // namespace internal + + +// ------------------------------------------------------------------- + +// Iterators and helper functions that follow the spirit of the STL +// std::back_insert_iterator and std::back_inserter but are tailor-made +// for RepeatedField and RepeatedPtrField. Typical usage would be: +// +// std::copy(some_sequence.begin(), some_sequence.end(), +// RepeatedFieldBackInserter(proto.mutable_sequence())); +// +// Ported by johannes from util/gtl/proto-array-iterators.h + +namespace internal { + +// STL-like iterator implementation for RepeatedField. You should not +// refer to this class directly; use RepeatedField<T>::iterator instead. +// +// Note: All of the iterator operators *must* be inlined to avoid performance +// regressions. This is caused by the extern template declarations below (which +// are required because of the RepeatedField extern template declarations). If +// any of these functions aren't explicitly inlined (e.g. defined in the class), +// the compiler isn't allowed to inline them. +template <typename Element> +class RepeatedIterator { + public: + using iterator_category = std::random_access_iterator_tag; + // Note: remove_const is necessary for std::partial_sum, which uses value_type + // to determine the summation variable type. + using value_type = typename std::remove_const<Element>::type; + using difference_type = std::ptrdiff_t; + using pointer = Element*; + using reference = Element&; + + constexpr RepeatedIterator() noexcept : it_(nullptr) {} + + // Allows "upcasting" from RepeatedIterator<T**> to + // RepeatedIterator<const T*const*>. + template <typename OtherElement, + typename std::enable_if<std::is_convertible< + OtherElement*, pointer>::value>::type* = nullptr> + constexpr RepeatedIterator( + const RepeatedIterator<OtherElement>& other) noexcept + : it_(other.it_) {} + + // dereferenceable + constexpr reference operator*() const noexcept { return *it_; } + constexpr pointer operator->() const noexcept { return it_; } + + private: + // Helper alias to hide the internal type. + using iterator = RepeatedIterator<Element>; + + public: + // {inc,dec}rementable + iterator& operator++() noexcept { + ++it_; + return *this; + } + iterator operator++(int) noexcept { return iterator(it_++); } + iterator& operator--() noexcept { + --it_; + return *this; + } + iterator operator--(int) noexcept { return iterator(it_--); } + + // equality_comparable + friend constexpr bool operator==(const iterator& x, + const iterator& y) noexcept { + return x.it_ == y.it_; + } + friend constexpr bool operator!=(const iterator& x, + const iterator& y) noexcept { + return x.it_ != y.it_; + } + + // less_than_comparable + friend constexpr bool operator<(const iterator& x, + const iterator& y) noexcept { + return x.it_ < y.it_; + } + friend constexpr bool operator<=(const iterator& x, + const iterator& y) noexcept { + return x.it_ <= y.it_; + } + friend constexpr bool operator>(const iterator& x, + const iterator& y) noexcept { + return x.it_ > y.it_; + } + friend constexpr bool operator>=(const iterator& x, + const iterator& y) noexcept { + return x.it_ >= y.it_; + } + + // addable, subtractable + iterator& operator+=(difference_type d) noexcept { + it_ += d; + return *this; + } + constexpr iterator operator+(difference_type d) const noexcept { + return iterator(it_ + d); + } + friend constexpr iterator operator+(const difference_type d, + iterator it) noexcept { + return it + d; + } + + iterator& operator-=(difference_type d) noexcept { + it_ -= d; + return *this; + } + iterator constexpr operator-(difference_type d) const noexcept { + return iterator(it_ - d); + } + + // indexable + constexpr reference operator[](difference_type d) const noexcept { + return it_[d]; + } + + // random access iterator + friend constexpr difference_type operator-(iterator it1, + iterator it2) noexcept { + return it1.it_ - it2.it_; + } + + private: + template <typename OtherElement> + friend class RepeatedIterator; + + // Allow construction from RepeatedField. + friend class RepeatedField<value_type>; + explicit RepeatedIterator(Element* it) noexcept : it_(it) {} + + // The internal iterator. + Element* it_; +}; + +// A back inserter for RepeatedField objects. +template <typename T> +class RepeatedFieldBackInsertIterator { + public: + using iterator_category = std::output_iterator_tag; + using value_type = T; + using pointer = void; + using reference = void; + using difference_type = std::ptrdiff_t; + + explicit RepeatedFieldBackInsertIterator( + RepeatedField<T>* const mutable_field) + : field_(mutable_field) {} + RepeatedFieldBackInsertIterator<T>& operator=(const T& value) { + field_->Add(value); + return *this; + } + RepeatedFieldBackInsertIterator<T>& operator*() { return *this; } + RepeatedFieldBackInsertIterator<T>& operator++() { return *this; } + RepeatedFieldBackInsertIterator<T>& operator++(int /* unused */) { + return *this; + } + + private: + RepeatedField<T>* field_; +}; + +} // namespace internal + +// Provides a back insert iterator for RepeatedField instances, +// similar to std::back_inserter(). +template <typename T> +internal::RepeatedFieldBackInsertIterator<T> RepeatedFieldBackInserter( + RepeatedField<T>* const mutable_field) { + return internal::RepeatedFieldBackInsertIterator<T>(mutable_field); +} + +// Extern declarations of common instantiations to reduce library bloat. +extern template class PROTOBUF_EXPORT_TEMPLATE_DECLARE RepeatedField<bool>; +extern template class PROTOBUF_EXPORT_TEMPLATE_DECLARE RepeatedField<int32_t>; +extern template class PROTOBUF_EXPORT_TEMPLATE_DECLARE RepeatedField<uint32_t>; +extern template class PROTOBUF_EXPORT_TEMPLATE_DECLARE RepeatedField<int64_t>; +extern template class PROTOBUF_EXPORT_TEMPLATE_DECLARE RepeatedField<uint64_t>; +extern template class PROTOBUF_EXPORT_TEMPLATE_DECLARE RepeatedField<float>; +extern template class PROTOBUF_EXPORT_TEMPLATE_DECLARE RepeatedField<double>; + +namespace internal { +extern template class PROTOBUF_EXPORT_TEMPLATE_DECLARE RepeatedIterator<bool>; +extern template class PROTOBUF_EXPORT_TEMPLATE_DECLARE + RepeatedIterator<int32_t>; +extern template class PROTOBUF_EXPORT_TEMPLATE_DECLARE + RepeatedIterator<uint32_t>; +extern template class PROTOBUF_EXPORT_TEMPLATE_DECLARE + RepeatedIterator<int64_t>; +extern template class PROTOBUF_EXPORT_TEMPLATE_DECLARE + RepeatedIterator<uint64_t>; +extern template class PROTOBUF_EXPORT_TEMPLATE_DECLARE RepeatedIterator<float>; +extern template class PROTOBUF_EXPORT_TEMPLATE_DECLARE RepeatedIterator<double>; +} // namespace internal + +} // namespace protobuf +} // namespace google + +#include <google/protobuf/port_undef.inc> + +#endif // GOOGLE_PROTOBUF_REPEATED_FIELD_H__ diff --git a/toolkit/components/protobuf/src/google/protobuf/repeated_ptr_field.cc b/toolkit/components/protobuf/src/google/protobuf/repeated_ptr_field.cc new file mode 100644 index 0000000000..8e86727144 --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/repeated_ptr_field.cc @@ -0,0 +1,152 @@ +// 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. + +// Author: kenton@google.com (Kenton Varda) +// Based on original Protocol Buffers design by +// Sanjay Ghemawat, Jeff Dean, and others. + +#include <algorithm> + +#include <google/protobuf/stubs/logging.h> +#include <google/protobuf/stubs/common.h> +#include <google/protobuf/implicit_weak_message.h> +#include <google/protobuf/repeated_field.h> +#include <google/protobuf/port.h> + +// Must be included last. +#include <google/protobuf/port_def.inc> + +namespace google { +namespace protobuf { + +namespace internal { + +void** RepeatedPtrFieldBase::InternalExtend(int extend_amount) { + int new_size = current_size_ + extend_amount; + if (total_size_ >= new_size) { + // N.B.: rep_ is non-nullptr because extend_amount is always > 0, hence + // total_size must be non-zero since it is lower-bounded by new_size. + return &rep_->elements[current_size_]; + } + Rep* old_rep = rep_; + Arena* arena = GetOwningArena(); + new_size = internal::CalculateReserveSize<void*, kRepHeaderSize>(total_size_, + new_size); + GOOGLE_CHECK_LE(static_cast<int64_t>(new_size), + static_cast<int64_t>( + (std::numeric_limits<size_t>::max() - kRepHeaderSize) / + sizeof(old_rep->elements[0]))) + << "Requested size is too large to fit into size_t."; + size_t bytes = kRepHeaderSize + sizeof(old_rep->elements[0]) * new_size; + if (arena == nullptr) { + rep_ = reinterpret_cast<Rep*>(::operator new(bytes)); + } else { + rep_ = reinterpret_cast<Rep*>(Arena::CreateArray<char>(arena, bytes)); + } + const int old_total_size = total_size_; + total_size_ = new_size; + if (old_rep) { + if (old_rep->allocated_size > 0) { + memcpy(rep_->elements, old_rep->elements, + old_rep->allocated_size * sizeof(rep_->elements[0])); + } + rep_->allocated_size = old_rep->allocated_size; + + const size_t old_size = + old_total_size * sizeof(rep_->elements[0]) + kRepHeaderSize; + if (arena == nullptr) { + internal::SizedDelete(old_rep, old_size); + } else { + arena_->ReturnArrayMemory(old_rep, old_size); + } + } else { + rep_->allocated_size = 0; + } + return &rep_->elements[current_size_]; +} + +void RepeatedPtrFieldBase::Reserve(int new_size) { + if (new_size > current_size_) { + InternalExtend(new_size - current_size_); + } +} + +void RepeatedPtrFieldBase::DestroyProtos() { + GOOGLE_DCHECK(rep_); + GOOGLE_DCHECK(arena_ == nullptr); + int n = rep_->allocated_size; + void* const* elements = rep_->elements; + for (int i = 0; i < n; i++) { + delete static_cast<MessageLite*>(elements[i]); + } + const size_t size = total_size_ * sizeof(elements[0]) + kRepHeaderSize; + internal::SizedDelete(rep_, size); + rep_ = nullptr; +} + +void* RepeatedPtrFieldBase::AddOutOfLineHelper(void* obj) { + if (!rep_ || rep_->allocated_size == total_size_) { + InternalExtend(1); // Equivalent to "Reserve(total_size_ + 1)" + } + ++rep_->allocated_size; + rep_->elements[current_size_++] = obj; + return obj; +} + +void RepeatedPtrFieldBase::CloseGap(int start, int num) { + if (rep_ == nullptr) return; + // Close up a gap of "num" elements starting at offset "start". + for (int i = start + num; i < rep_->allocated_size; ++i) + rep_->elements[i - num] = rep_->elements[i]; + current_size_ -= num; + rep_->allocated_size -= num; +} + +MessageLite* RepeatedPtrFieldBase::AddWeak(const MessageLite* prototype) { + if (rep_ != nullptr && current_size_ < rep_->allocated_size) { + return reinterpret_cast<MessageLite*>(rep_->elements[current_size_++]); + } + if (!rep_ || rep_->allocated_size == total_size_) { + Reserve(total_size_ + 1); + } + ++rep_->allocated_size; + MessageLite* result = prototype + ? prototype->New(arena_) + : Arena::CreateMessage<ImplicitWeakMessage>(arena_); + rep_->elements[current_size_++] = result; + return result; +} + +} // namespace internal + +} // namespace protobuf +} // namespace google + +#include <google/protobuf/port_undef.inc> diff --git a/toolkit/components/protobuf/src/google/protobuf/repeated_ptr_field.h b/toolkit/components/protobuf/src/google/protobuf/repeated_ptr_field.h new file mode 100644 index 0000000000..401230bf51 --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/repeated_ptr_field.h @@ -0,0 +1,1970 @@ +// 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. + +// Author: kenton@google.com (Kenton Varda) +// Based on original Protocol Buffers design by +// Sanjay Ghemawat, Jeff Dean, and others. +// +// RepeatedField and RepeatedPtrField are used by generated protocol message +// classes to manipulate repeated fields. These classes are very similar to +// STL's vector, but include a number of optimizations found to be useful +// specifically in the case of Protocol Buffers. RepeatedPtrField is +// particularly different from STL vector as it manages ownership of the +// pointers that it contains. +// +// This header covers RepeatedPtrField. + +// IWYU pragma: private, include "net/proto2/public/repeated_field.h" + +#ifndef GOOGLE_PROTOBUF_REPEATED_PTR_FIELD_H__ +#define GOOGLE_PROTOBUF_REPEATED_PTR_FIELD_H__ + +#include <utility> + +#ifdef _MSC_VER +// This is required for min/max on VS2013 only. +#include <algorithm> +#endif + +#include <iterator> +#include <limits> +#include <string> +#include <type_traits> + +#include <google/protobuf/stubs/logging.h> +#include <google/protobuf/stubs/common.h> +#include <google/protobuf/arena.h> +#include <google/protobuf/port.h> +#include <google/protobuf/message_lite.h> + + +// Must be included last. +#include <google/protobuf/port_def.inc> + +#ifdef SWIG +#error "You cannot SWIG proto headers" +#endif + +namespace google { +namespace protobuf { + +class Message; +class Reflection; + +template <typename T> +struct WeakRepeatedPtrField; + +namespace internal { + +class MergePartialFromCodedStreamHelper; +class SwapFieldHelper; + + +} // namespace internal + +namespace internal { +template <typename It> +class RepeatedPtrIterator; +template <typename It, typename VoidPtr> +class RepeatedPtrOverPtrsIterator; +} // namespace internal + +namespace internal { + +// type-traits helper for RepeatedPtrFieldBase: we only want to invoke +// arena-related "copy if on different arena" behavior if the necessary methods +// exist on the contained type. In particular, we rely on MergeFrom() existing +// as a general proxy for the fact that a copy will work, and we also provide a +// specific override for std::string*. +template <typename T> +struct TypeImplementsMergeBehaviorProbeForMergeFrom { + typedef char HasMerge; + typedef long HasNoMerge; + + // We accept either of: + // - void MergeFrom(const T& other) + // - bool MergeFrom(const T& other) + // + // We mangle these names a bit to avoid compatibility issues in 'unclean' + // include environments that may have, e.g., "#define test ..." (yes, this + // exists). + template <typename U, typename RetType, RetType (U::*)(const U& arg)> + struct CheckType; + template <typename U> + static HasMerge Check(CheckType<U, void, &U::MergeFrom>*); + template <typename U> + static HasMerge Check(CheckType<U, bool, &U::MergeFrom>*); + template <typename U> + static HasNoMerge Check(...); + + // Resolves to either std::true_type or std::false_type. + typedef std::integral_constant<bool, + (sizeof(Check<T>(0)) == sizeof(HasMerge))> + type; +}; + +template <typename T, typename = void> +struct TypeImplementsMergeBehavior + : TypeImplementsMergeBehaviorProbeForMergeFrom<T> {}; + + +template <> +struct TypeImplementsMergeBehavior<std::string> { + typedef std::true_type type; +}; + +template <typename T> +struct IsMovable + : std::integral_constant<bool, std::is_move_constructible<T>::value && + std::is_move_assignable<T>::value> {}; + +// This is the common base class for RepeatedPtrFields. It deals only in void* +// pointers. Users should not use this interface directly. +// +// The methods of this interface correspond to the methods of RepeatedPtrField, +// but may have a template argument called TypeHandler. Its signature is: +// class TypeHandler { +// public: +// typedef MyType Type; +// static Type* New(); +// static Type* NewFromPrototype(const Type* prototype, +// Arena* arena); +// static void Delete(Type*); +// static void Clear(Type*); +// static void Merge(const Type& from, Type* to); +// +// // Only needs to be implemented if SpaceUsedExcludingSelf() is called. +// static int SpaceUsedLong(const Type&); +// }; +class PROTOBUF_EXPORT RepeatedPtrFieldBase { + protected: + constexpr RepeatedPtrFieldBase() + : arena_(nullptr), current_size_(0), total_size_(0), rep_(nullptr) {} + explicit RepeatedPtrFieldBase(Arena* arena) + : arena_(arena), current_size_(0), total_size_(0), rep_(nullptr) {} + + RepeatedPtrFieldBase(const RepeatedPtrFieldBase&) = delete; + RepeatedPtrFieldBase& operator=(const RepeatedPtrFieldBase&) = delete; + + ~RepeatedPtrFieldBase() { +#ifndef NDEBUG + // Try to trigger segfault / asan failure in non-opt builds. If arena_ + // lifetime has ended before the destructor. + if (arena_) (void)arena_->SpaceAllocated(); +#endif + } + + bool empty() const { return current_size_ == 0; } + int size() const { return current_size_; } + int Capacity() const { return total_size_; } + + template <typename TypeHandler> + const typename TypeHandler::Type& at(int index) const { + GOOGLE_CHECK_GE(index, 0); + GOOGLE_CHECK_LT(index, current_size_); + return *cast<TypeHandler>(rep_->elements[index]); + } + + template <typename TypeHandler> + typename TypeHandler::Type& at(int index) { + GOOGLE_CHECK_GE(index, 0); + GOOGLE_CHECK_LT(index, current_size_); + return *cast<TypeHandler>(rep_->elements[index]); + } + + template <typename TypeHandler> + typename TypeHandler::Type* Mutable(int index) { + GOOGLE_DCHECK_GE(index, 0); + GOOGLE_DCHECK_LT(index, current_size_); + return cast<TypeHandler>(rep_->elements[index]); + } + + template <typename TypeHandler> + typename TypeHandler::Type* Add( + const typename TypeHandler::Type* prototype = nullptr) { + if (rep_ != nullptr && current_size_ < rep_->allocated_size) { + return cast<TypeHandler>(rep_->elements[current_size_++]); + } + typename TypeHandler::Type* result = + TypeHandler::NewFromPrototype(prototype, arena_); + return reinterpret_cast<typename TypeHandler::Type*>( + AddOutOfLineHelper(result)); + } + + template < + typename TypeHandler, + typename std::enable_if<TypeHandler::Movable::value>::type* = nullptr> + inline void Add(typename TypeHandler::Type&& value) { + if (rep_ != nullptr && current_size_ < rep_->allocated_size) { + *cast<TypeHandler>(rep_->elements[current_size_++]) = std::move(value); + return; + } + if (!rep_ || rep_->allocated_size == total_size_) { + Reserve(total_size_ + 1); + } + ++rep_->allocated_size; + typename TypeHandler::Type* result = + TypeHandler::New(arena_, std::move(value)); + rep_->elements[current_size_++] = result; + } + + template <typename TypeHandler> + void Delete(int index) { + GOOGLE_DCHECK_GE(index, 0); + GOOGLE_DCHECK_LT(index, current_size_); + TypeHandler::Delete(cast<TypeHandler>(rep_->elements[index]), arena_); + } + + // Must be called from destructor. + template <typename TypeHandler> + void Destroy() { + if (rep_ != nullptr && arena_ == nullptr) { + int n = rep_->allocated_size; + void* const* elements = rep_->elements; + for (int i = 0; i < n; i++) { + TypeHandler::Delete(cast<TypeHandler>(elements[i]), nullptr); + } + const size_t size = total_size_ * sizeof(elements[0]) + kRepHeaderSize; + internal::SizedDelete(rep_, size); + } + rep_ = nullptr; + } + + bool NeedsDestroy() const { return rep_ != nullptr && arena_ == nullptr; } + void DestroyProtos(); // implemented in the cc file + + public: + // The next few methods are public so that they can be called from generated + // code when implicit weak fields are used, but they should never be called by + // application code. + + template <typename TypeHandler> + const typename TypeHandler::Type& Get(int index) const { + GOOGLE_DCHECK_GE(index, 0); + GOOGLE_DCHECK_LT(index, current_size_); + return *cast<TypeHandler>(rep_->elements[index]); + } + + // Creates and adds an element using the given prototype, without introducing + // a link-time dependency on the concrete message type. This method is used to + // implement implicit weak fields. The prototype may be nullptr, in which case + // an ImplicitWeakMessage will be used as a placeholder. + MessageLite* AddWeak(const MessageLite* prototype); + + template <typename TypeHandler> + void Clear() { + const int n = current_size_; + GOOGLE_DCHECK_GE(n, 0); + if (n > 0) { + void* const* elements = rep_->elements; + int i = 0; + do { + TypeHandler::Clear(cast<TypeHandler>(elements[i++])); + } while (i < n); + current_size_ = 0; + } + } + + template <typename TypeHandler> + void MergeFrom(const RepeatedPtrFieldBase& other) { + // To avoid unnecessary code duplication and reduce binary size, we use a + // layered approach to implementing MergeFrom(). The toplevel method is + // templated, so we get a small thunk per concrete message type in the + // binary. This calls a shared implementation with most of the logic, + // passing a function pointer to another type-specific piece of code that + // calls the object-allocate and merge handlers. + GOOGLE_DCHECK_NE(&other, this); + if (other.current_size_ == 0) return; + MergeFromInternal(other, + &RepeatedPtrFieldBase::MergeFromInnerLoop<TypeHandler>); + } + + inline void InternalSwap(RepeatedPtrFieldBase* rhs) { + GOOGLE_DCHECK(this != rhs); + + // Swap all fields at once. + auto temp = std::make_tuple(rhs->arena_, rhs->current_size_, + rhs->total_size_, rhs->rep_); + std::tie(rhs->arena_, rhs->current_size_, rhs->total_size_, rhs->rep_) = + std::make_tuple(arena_, current_size_, total_size_, rep_); + std::tie(arena_, current_size_, total_size_, rep_) = temp; + } + + protected: + template <typename TypeHandler> + void RemoveLast() { + GOOGLE_DCHECK_GT(current_size_, 0); + TypeHandler::Clear(cast<TypeHandler>(rep_->elements[--current_size_])); + } + + template <typename TypeHandler> + void CopyFrom(const RepeatedPtrFieldBase& other) { + if (&other == this) return; + RepeatedPtrFieldBase::Clear<TypeHandler>(); + RepeatedPtrFieldBase::MergeFrom<TypeHandler>(other); + } + + void CloseGap(int start, int num); // implemented in the cc file + + void Reserve(int new_size); // implemented in the cc file + + template <typename TypeHandler> + static inline typename TypeHandler::Type* copy( + typename TypeHandler::Type* value) { + auto* new_value = TypeHandler::NewFromPrototype(value, nullptr); + TypeHandler::Merge(*value, new_value); + return new_value; + } + + // Used for constructing iterators. + void* const* raw_data() const { return rep_ ? rep_->elements : nullptr; } + void** raw_mutable_data() const { + return rep_ ? const_cast<void**>(rep_->elements) : nullptr; + } + + template <typename TypeHandler> + typename TypeHandler::Type** mutable_data() { + // TODO(kenton): Breaks C++ aliasing rules. We should probably remove this + // method entirely. + return reinterpret_cast<typename TypeHandler::Type**>(raw_mutable_data()); + } + + template <typename TypeHandler> + const typename TypeHandler::Type* const* data() const { + // TODO(kenton): Breaks C++ aliasing rules. We should probably remove this + // method entirely. + return reinterpret_cast<const typename TypeHandler::Type* const*>( + raw_data()); + } + + template <typename TypeHandler> + PROTOBUF_NDEBUG_INLINE void Swap(RepeatedPtrFieldBase* other) { +#ifdef PROTOBUF_FORCE_COPY_IN_SWAP + if (GetOwningArena() != nullptr && + GetOwningArena() == other->GetOwningArena()) +#else // PROTOBUF_FORCE_COPY_IN_SWAP + if (GetOwningArena() == other->GetOwningArena()) +#endif // !PROTOBUF_FORCE_COPY_IN_SWAP + { + InternalSwap(other); + } else { + SwapFallback<TypeHandler>(other); + } + } + + void SwapElements(int index1, int index2) { + using std::swap; // enable ADL with fallback + swap(rep_->elements[index1], rep_->elements[index2]); + } + + template <typename TypeHandler> + size_t SpaceUsedExcludingSelfLong() const { + size_t allocated_bytes = static_cast<size_t>(total_size_) * sizeof(void*); + if (rep_ != nullptr) { + for (int i = 0; i < rep_->allocated_size; ++i) { + allocated_bytes += + TypeHandler::SpaceUsedLong(*cast<TypeHandler>(rep_->elements[i])); + } + allocated_bytes += kRepHeaderSize; + } + return allocated_bytes; + } + + // Advanced memory management -------------------------------------- + + // Like Add(), but if there are no cleared objects to use, returns nullptr. + template <typename TypeHandler> + typename TypeHandler::Type* AddFromCleared() { + if (rep_ != nullptr && current_size_ < rep_->allocated_size) { + return cast<TypeHandler>(rep_->elements[current_size_++]); + } else { + return nullptr; + } + } + + template <typename TypeHandler> + void AddAllocated(typename TypeHandler::Type* value) { + typename TypeImplementsMergeBehavior<typename TypeHandler::Type>::type t; + AddAllocatedInternal<TypeHandler>(value, t); + } + + template <typename TypeHandler> + void UnsafeArenaAddAllocated(typename TypeHandler::Type* value) { + // Make room for the new pointer. + if (!rep_ || current_size_ == total_size_) { + // The array is completely full with no cleared objects, so grow it. + Reserve(total_size_ + 1); + ++rep_->allocated_size; + } else if (rep_->allocated_size == total_size_) { + // There is no more space in the pointer array because it contains some + // cleared objects awaiting reuse. We don't want to grow the array in + // this case because otherwise a loop calling AddAllocated() followed by + // Clear() would leak memory. + TypeHandler::Delete(cast<TypeHandler>(rep_->elements[current_size_]), + arena_); + } else if (current_size_ < rep_->allocated_size) { + // We have some cleared objects. We don't care about their order, so we + // can just move the first one to the end to make space. + rep_->elements[rep_->allocated_size] = rep_->elements[current_size_]; + ++rep_->allocated_size; + } else { + // There are no cleared objects. + ++rep_->allocated_size; + } + + rep_->elements[current_size_++] = value; + } + + template <typename TypeHandler> + PROTOBUF_NODISCARD typename TypeHandler::Type* ReleaseLast() { + typename TypeImplementsMergeBehavior<typename TypeHandler::Type>::type t; + return ReleaseLastInternal<TypeHandler>(t); + } + + // Releases and returns the last element, but does not do out-of-arena copy. + // Instead, just returns the raw pointer to the contained element in the + // arena. + template <typename TypeHandler> + typename TypeHandler::Type* UnsafeArenaReleaseLast() { + GOOGLE_DCHECK_GT(current_size_, 0); + typename TypeHandler::Type* result = + cast<TypeHandler>(rep_->elements[--current_size_]); + --rep_->allocated_size; + if (current_size_ < rep_->allocated_size) { + // There are cleared elements on the end; replace the removed element + // with the last allocated element. + rep_->elements[current_size_] = rep_->elements[rep_->allocated_size]; + } + return result; + } + + int ClearedCount() const { + return rep_ ? (rep_->allocated_size - current_size_) : 0; + } + + template <typename TypeHandler> + void AddCleared(typename TypeHandler::Type* value) { + GOOGLE_DCHECK(GetOwningArena() == nullptr) << "AddCleared() can only be used on a " + "RepeatedPtrField not on an arena."; + GOOGLE_DCHECK(TypeHandler::GetOwningArena(value) == nullptr) + << "AddCleared() can only accept values not on an arena."; + if (!rep_ || rep_->allocated_size == total_size_) { + Reserve(total_size_ + 1); + } + rep_->elements[rep_->allocated_size++] = value; + } + + template <typename TypeHandler> + PROTOBUF_NODISCARD typename TypeHandler::Type* ReleaseCleared() { + GOOGLE_DCHECK(GetOwningArena() == nullptr) + << "ReleaseCleared() can only be used on a RepeatedPtrField not on " + << "an arena."; + GOOGLE_DCHECK(GetOwningArena() == nullptr); + GOOGLE_DCHECK(rep_ != nullptr); + GOOGLE_DCHECK_GT(rep_->allocated_size, current_size_); + return cast<TypeHandler>(rep_->elements[--rep_->allocated_size]); + } + + template <typename TypeHandler> + void AddAllocatedInternal(typename TypeHandler::Type* value, std::true_type) { + // AddAllocated version that implements arena-safe copying behavior. + Arena* element_arena = + reinterpret_cast<Arena*>(TypeHandler::GetOwningArena(value)); + Arena* arena = GetOwningArena(); + if (arena == element_arena && rep_ && rep_->allocated_size < total_size_) { + // Fast path: underlying arena representation (tagged pointer) is equal to + // our arena pointer, and we can add to array without resizing it (at + // least one slot that is not allocated). + void** elems = rep_->elements; + if (current_size_ < rep_->allocated_size) { + // Make space at [current] by moving first allocated element to end of + // allocated list. + elems[rep_->allocated_size] = elems[current_size_]; + } + elems[current_size_] = value; + current_size_ = current_size_ + 1; + rep_->allocated_size = rep_->allocated_size + 1; + } else { + AddAllocatedSlowWithCopy<TypeHandler>(value, element_arena, arena); + } + } + + template <typename TypeHandler> + void AddAllocatedInternal( + // AddAllocated version that does not implement arena-safe copying + // behavior. + typename TypeHandler::Type* value, std::false_type) { + if (rep_ && rep_->allocated_size < total_size_) { + // Fast path: underlying arena representation (tagged pointer) is equal to + // our arena pointer, and we can add to array without resizing it (at + // least one slot that is not allocated). + void** elems = rep_->elements; + if (current_size_ < rep_->allocated_size) { + // Make space at [current] by moving first allocated element to end of + // allocated list. + elems[rep_->allocated_size] = elems[current_size_]; + } + elems[current_size_] = value; + current_size_ = current_size_ + 1; + ++rep_->allocated_size; + } else { + UnsafeArenaAddAllocated<TypeHandler>(value); + } + } + + // Slowpath handles all cases, copying if necessary. + template <typename TypeHandler> + PROTOBUF_NOINLINE void AddAllocatedSlowWithCopy( + // Pass value_arena and my_arena to avoid duplicate virtual call (value) + // or load (mine). + typename TypeHandler::Type* value, Arena* value_arena, Arena* my_arena) { + // Ensure that either the value is in the same arena, or if not, we do the + // appropriate thing: Own() it (if it's on heap and we're in an arena) or + // copy it to our arena/heap (otherwise). + if (my_arena != nullptr && value_arena == nullptr) { + my_arena->Own(value); + } else if (my_arena != value_arena) { + typename TypeHandler::Type* new_value = + TypeHandler::NewFromPrototype(value, my_arena); + TypeHandler::Merge(*value, new_value); + TypeHandler::Delete(value, value_arena); + value = new_value; + } + + UnsafeArenaAddAllocated<TypeHandler>(value); + } + + template <typename TypeHandler> + typename TypeHandler::Type* ReleaseLastInternal(std::true_type) { + // ReleaseLast() for types that implement merge/copy behavior. + // First, release an element. + typename TypeHandler::Type* result = UnsafeArenaReleaseLast<TypeHandler>(); + // Now perform a copy if we're on an arena. + Arena* arena = GetOwningArena(); + + typename TypeHandler::Type* new_result; +#ifdef PROTOBUF_FORCE_COPY_IN_RELEASE + new_result = copy<TypeHandler>(result); + if (arena == nullptr) delete result; +#else // PROTOBUF_FORCE_COPY_IN_RELEASE + new_result = (arena == nullptr) ? result : copy<TypeHandler>(result); +#endif // !PROTOBUF_FORCE_COPY_IN_RELEASE + return new_result; + } + + template <typename TypeHandler> + typename TypeHandler::Type* ReleaseLastInternal(std::false_type) { + // ReleaseLast() for types that *do not* implement merge/copy behavior -- + // this is the same as UnsafeArenaReleaseLast(). Note that we GOOGLE_DCHECK-fail if + // we're on an arena, since the user really should implement the copy + // operation in this case. + GOOGLE_DCHECK(GetOwningArena() == nullptr) + << "ReleaseLast() called on a RepeatedPtrField that is on an arena, " + << "with a type that does not implement MergeFrom. This is unsafe; " + << "please implement MergeFrom for your type."; + return UnsafeArenaReleaseLast<TypeHandler>(); + } + + template <typename TypeHandler> + PROTOBUF_NOINLINE void SwapFallback(RepeatedPtrFieldBase* other) { +#ifdef PROTOBUF_FORCE_COPY_IN_SWAP + GOOGLE_DCHECK(GetOwningArena() == nullptr || + other->GetOwningArena() != GetOwningArena()); +#else // PROTOBUF_FORCE_COPY_IN_SWAP + GOOGLE_DCHECK(other->GetOwningArena() != GetOwningArena()); +#endif // !PROTOBUF_FORCE_COPY_IN_SWAP + + // Copy semantics in this case. We try to improve efficiency by placing the + // temporary on |other|'s arena so that messages are copied twice rather + // than three times. + RepeatedPtrFieldBase temp(other->GetOwningArena()); + temp.MergeFrom<TypeHandler>(*this); + this->Clear<TypeHandler>(); + this->MergeFrom<TypeHandler>(*other); + other->InternalSwap(&temp); + temp.Destroy<TypeHandler>(); // Frees rep_ if `other` had no arena. + } + + inline Arena* GetArena() const { return arena_; } + + protected: + inline Arena* GetOwningArena() const { return arena_; } + + private: + template <typename T> friend class Arena::InternalHelper; + + static constexpr int kInitialSize = 0; + // A few notes on internal representation: + // + // We use an indirected approach, with struct Rep, to keep + // sizeof(RepeatedPtrFieldBase) equivalent to what it was before arena support + // was added; namely, 3 8-byte machine words on x86-64. An instance of Rep is + // allocated only when the repeated field is non-empty, and it is a + // dynamically-sized struct (the header is directly followed by elements[]). + // We place arena_ and current_size_ directly in the object to avoid cache + // misses due to the indirection, because these fields are checked frequently. + // Placing all fields directly in the RepeatedPtrFieldBase instance would cost + // significant performance for memory-sensitive workloads. + Arena* arena_; + int current_size_; + int total_size_; + struct Rep { + int allocated_size; + // Here we declare a huge array as a way of approximating C's "flexible + // array member" feature without relying on undefined behavior. + void* elements[(std::numeric_limits<int>::max() - 2 * sizeof(int)) / + sizeof(void*)]; + }; + static constexpr size_t kRepHeaderSize = offsetof(Rep, elements); + Rep* rep_; + + template <typename TypeHandler> + static inline typename TypeHandler::Type* cast(void* element) { + return reinterpret_cast<typename TypeHandler::Type*>(element); + } + template <typename TypeHandler> + static inline const typename TypeHandler::Type* cast(const void* element) { + return reinterpret_cast<const typename TypeHandler::Type*>(element); + } + + // Non-templated inner function to avoid code duplication. Takes a function + // pointer to the type-specific (templated) inner allocate/merge loop. + void MergeFromInternal(const RepeatedPtrFieldBase& other, + void (RepeatedPtrFieldBase::*inner_loop)(void**, + void**, int, + int)) { + // Note: wrapper has already guaranteed that other.rep_ != nullptr here. + int other_size = other.current_size_; + void** other_elements = other.rep_->elements; + void** new_elements = InternalExtend(other_size); + int allocated_elems = rep_->allocated_size - current_size_; + (this->*inner_loop)(new_elements, other_elements, other_size, + allocated_elems); + current_size_ += other_size; + if (rep_->allocated_size < current_size_) { + rep_->allocated_size = current_size_; + } + } + + // Merges other_elems to our_elems. + template <typename TypeHandler> + PROTOBUF_NOINLINE void MergeFromInnerLoop(void** our_elems, + void** other_elems, int length, + int already_allocated) { + if (already_allocated < length) { + Arena* arena = GetOwningArena(); + typename TypeHandler::Type* elem_prototype = + reinterpret_cast<typename TypeHandler::Type*>(other_elems[0]); + for (int i = already_allocated; i < length; i++) { + // Allocate a new empty element that we'll merge into below + typename TypeHandler::Type* new_elem = + TypeHandler::NewFromPrototype(elem_prototype, arena); + our_elems[i] = new_elem; + } + } + // Main loop that does the actual merging + for (int i = 0; i < length; i++) { + // Already allocated: use existing element. + typename TypeHandler::Type* other_elem = + reinterpret_cast<typename TypeHandler::Type*>(other_elems[i]); + typename TypeHandler::Type* new_elem = + reinterpret_cast<typename TypeHandler::Type*>(our_elems[i]); + TypeHandler::Merge(*other_elem, new_elem); + } + } + + // Internal helper: extends array space if necessary to contain + // |extend_amount| more elements, and returns a pointer to the element + // immediately following the old list of elements. This interface factors out + // common behavior from Reserve() and MergeFrom() to reduce code size. + // |extend_amount| must be > 0. + void** InternalExtend(int extend_amount); + + // Internal helper for Add: adds "obj" as the next element in the + // array, including potentially resizing the array with Reserve if + // needed + void* AddOutOfLineHelper(void* obj); + + // The reflection implementation needs to call protected methods directly, + // reinterpreting pointers as being to Message instead of a specific Message + // subclass. + friend class ::PROTOBUF_NAMESPACE_ID::Reflection; + friend class ::PROTOBUF_NAMESPACE_ID::internal::SwapFieldHelper; + + // ExtensionSet stores repeated message extensions as + // RepeatedPtrField<MessageLite>, but non-lite ExtensionSets need to implement + // SpaceUsedLong(), and thus need to call SpaceUsedExcludingSelfLong() + // reinterpreting MessageLite as Message. ExtensionSet also needs to make use + // of AddFromCleared(), which is not part of the public interface. + friend class ExtensionSet; + + // The MapFieldBase implementation needs to call protected methods directly, + // reinterpreting pointers as being to Message instead of a specific Message + // subclass. + friend class MapFieldBase; + friend class MapFieldBaseStub; + + // The table-driven MergePartialFromCodedStream implementation needs to + // operate on RepeatedPtrField<MessageLite>. + friend class MergePartialFromCodedStreamHelper; + friend class AccessorHelper; + template <typename T> + friend struct google::protobuf::WeakRepeatedPtrField; + friend class internal::TcParser; // TODO(jorg): Remove this friend. +}; + +template <typename GenericType> +class GenericTypeHandler { + public: + typedef GenericType Type; + using Movable = IsMovable<GenericType>; + + static inline GenericType* New(Arena* arena) { + return Arena::CreateMaybeMessage<Type>(arena); + } + static inline GenericType* New(Arena* arena, GenericType&& value) { + return Arena::Create<GenericType>(arena, std::move(value)); + } + static inline GenericType* NewFromPrototype(const GenericType* /*prototype*/, + Arena* arena = nullptr) { + return New(arena); + } + static inline void Delete(GenericType* value, Arena* arena) { + if (arena == nullptr) { + delete value; + } + } + static inline Arena* GetOwningArena(GenericType* value) { + return Arena::GetOwningArena<Type>(value); + } + + static inline void Clear(GenericType* value) { value->Clear(); } + static void Merge(const GenericType& from, GenericType* to); + static inline size_t SpaceUsedLong(const GenericType& value) { + return value.SpaceUsedLong(); + } +}; + +// NewFromPrototypeHelper() is not defined inline here, as we will need to do a +// virtual function dispatch anyways to go from Message* to call New/Merge. (The +// additional helper is needed as a workaround for MSVC.) +MessageLite* NewFromPrototypeHelper(const MessageLite* prototype, Arena* arena); + +template <> +inline MessageLite* GenericTypeHandler<MessageLite>::NewFromPrototype( + const MessageLite* prototype, Arena* arena) { + return NewFromPrototypeHelper(prototype, arena); +} +template <> +inline Arena* GenericTypeHandler<MessageLite>::GetOwningArena( + MessageLite* value) { + return value->GetOwningArena(); +} + +template <typename GenericType> +PROTOBUF_NOINLINE inline void GenericTypeHandler<GenericType>::Merge( + const GenericType& from, GenericType* to) { + to->MergeFrom(from); +} +template <> +void GenericTypeHandler<MessageLite>::Merge(const MessageLite& from, + MessageLite* to); + +template <> +inline void GenericTypeHandler<std::string>::Clear(std::string* value) { + value->clear(); +} +template <> +void GenericTypeHandler<std::string>::Merge(const std::string& from, + std::string* to); + +// Message specialization bodies defined in message.cc. This split is necessary +// to allow proto2-lite (which includes this header) to be independent of +// Message. +template <> +PROTOBUF_EXPORT Message* GenericTypeHandler<Message>::NewFromPrototype( + const Message* prototype, Arena* arena); +template <> +PROTOBUF_EXPORT Arena* GenericTypeHandler<Message>::GetOwningArena( + Message* value); + +class StringTypeHandler { + public: + typedef std::string Type; + using Movable = IsMovable<Type>; + + static inline std::string* New(Arena* arena) { + return Arena::Create<std::string>(arena); + } + static inline std::string* New(Arena* arena, std::string&& value) { + return Arena::Create<std::string>(arena, std::move(value)); + } + static inline std::string* NewFromPrototype(const std::string*, + Arena* arena) { + return New(arena); + } + static inline Arena* GetOwningArena(std::string*) { return nullptr; } + static inline void Delete(std::string* value, Arena* arena) { + if (arena == nullptr) { + delete value; + } + } + static inline void Clear(std::string* value) { value->clear(); } + static inline void Merge(const std::string& from, std::string* to) { + *to = from; + } + static size_t SpaceUsedLong(const std::string& value) { + return sizeof(value) + StringSpaceUsedExcludingSelfLong(value); + } +}; + +} // namespace internal + +// RepeatedPtrField is like RepeatedField, but used for repeated strings or +// Messages. +template <typename Element> +class RepeatedPtrField final : private internal::RepeatedPtrFieldBase { + + public: + constexpr RepeatedPtrField(); + explicit RepeatedPtrField(Arena* arena); + + RepeatedPtrField(const RepeatedPtrField& other); + + template <typename Iter, + typename = typename std::enable_if<std::is_constructible< + Element, decltype(*std::declval<Iter>())>::value>::type> + RepeatedPtrField(Iter begin, Iter end); + + ~RepeatedPtrField(); + + RepeatedPtrField& operator=(const RepeatedPtrField& other); + + RepeatedPtrField(RepeatedPtrField&& other) noexcept; + RepeatedPtrField& operator=(RepeatedPtrField&& other) noexcept; + + bool empty() const; + int size() const; + + const Element& Get(int index) const; + Element* Mutable(int index); + + // Unlike std::vector, adding an element to a RepeatedPtrField doesn't always + // make a new element; it might re-use an element left over from when the + // field was Clear()'d or reize()'d smaller. For this reason, Add() is the + // fastest API for adding a new element. + Element* Add(); + + // `Add(std::move(value));` is equivalent to `*Add() = std::move(value);` + // It will either move-construct to the end of this field, or swap value + // with the new-or-recycled element at the end of this field. Note that + // this operation is very slow if this RepeatedPtrField is not on the + // same Arena, if any, as `value`. + void Add(Element&& value); + + // Copying to the end of this RepeatedPtrField is slowest of all; it can't + // reliably copy-construct to the last element of this RepeatedPtrField, for + // example (unlike std::vector). + // We currently block this API. The right way to add to the end is to call + // Add() and modify the element it points to. + // If you must add an existing value, call `*Add() = value;` + void Add(const Element& value) = delete; + + // Append elements in the range [begin, end) after reserving + // the appropriate number of elements. + template <typename Iter> + void Add(Iter begin, Iter end); + + const Element& operator[](int index) const { return Get(index); } + Element& operator[](int index) { return *Mutable(index); } + + const Element& at(int index) const; + Element& at(int index); + + // Removes the last element in the array. + // Ownership of the element is retained by the array. + void RemoveLast(); + + // Deletes elements with indices in the range [start .. start+num-1]. + // Caution: moves all elements with indices [start+num .. ]. + // Calling this routine inside a loop can cause quadratic behavior. + void DeleteSubrange(int start, int num); + + PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear(); + void MergeFrom(const RepeatedPtrField& other); + PROTOBUF_ATTRIBUTE_REINITIALIZES void CopyFrom(const RepeatedPtrField& other); + + // Replaces the contents with RepeatedPtrField(begin, end). + template <typename Iter> + PROTOBUF_ATTRIBUTE_REINITIALIZES void Assign(Iter begin, Iter end); + + // Reserves space to expand the field to at least the given size. This only + // resizes the pointer array; it doesn't allocate any objects. If the + // array is grown, it will always be at least doubled in size. + void Reserve(int new_size); + + int Capacity() const; + + // Gets the underlying array. This pointer is possibly invalidated by + // any add or remove operation. + // + // This API is deprecated. Instead of directly working with element array, + // use APIs in repeated_field_util.h; e.g. sorting, etc. + PROTOBUF_DEPRECATED_MSG("Use APIs in repeated_field_util.h") + Element** mutable_data(); + const Element* const* data() const; + + // Swaps entire contents with "other". If they are on separate arenas, then + // copies data. + void Swap(RepeatedPtrField* other); + + // Swaps entire contents with "other". Caller should guarantee that either + // both fields are on the same arena or both are on the heap. Swapping between + // different arenas with this function is disallowed and is caught via + // GOOGLE_DCHECK. + void UnsafeArenaSwap(RepeatedPtrField* other); + + // Swaps two elements. + void SwapElements(int index1, int index2); + + // STL-like iterator support + typedef internal::RepeatedPtrIterator<Element> iterator; + typedef internal::RepeatedPtrIterator<const Element> const_iterator; + typedef Element value_type; + typedef value_type& reference; + typedef const value_type& const_reference; + typedef value_type* pointer; + typedef const value_type* const_pointer; + typedef int size_type; + typedef ptrdiff_t difference_type; + + iterator begin(); + const_iterator begin() const; + const_iterator cbegin() const; + iterator end(); + const_iterator end() const; + const_iterator cend() const; + + // Reverse iterator support + typedef std::reverse_iterator<const_iterator> const_reverse_iterator; + typedef std::reverse_iterator<iterator> reverse_iterator; + reverse_iterator rbegin() { return reverse_iterator(end()); } + const_reverse_iterator rbegin() const { + return const_reverse_iterator(end()); + } + reverse_iterator rend() { return reverse_iterator(begin()); } + const_reverse_iterator rend() const { + return const_reverse_iterator(begin()); + } + + // Custom STL-like iterator that iterates over and returns the underlying + // pointers to Element rather than Element itself. + typedef internal::RepeatedPtrOverPtrsIterator<Element*, void*> + pointer_iterator; + typedef internal::RepeatedPtrOverPtrsIterator<const Element* const, + const void* const> + const_pointer_iterator; + pointer_iterator pointer_begin(); + const_pointer_iterator pointer_begin() const; + pointer_iterator pointer_end(); + const_pointer_iterator pointer_end() const; + + // Returns (an estimate of) the number of bytes used by the repeated field, + // excluding sizeof(*this). + size_t SpaceUsedExcludingSelfLong() const; + + int SpaceUsedExcludingSelf() const { + return internal::ToIntSize(SpaceUsedExcludingSelfLong()); + } + + // Advanced memory management -------------------------------------- + // When hardcore memory management becomes necessary -- as it sometimes + // does here at Google -- the following methods may be useful. + + // Adds an already-allocated object, passing ownership to the + // RepeatedPtrField. + // + // Note that some special behavior occurs with respect to arenas: + // + // (i) if this field holds submessages, the new submessage will be copied if + // the original is in an arena and this RepeatedPtrField is either in a + // different arena, or on the heap. + // (ii) if this field holds strings, the passed-in string *must* be + // heap-allocated, not arena-allocated. There is no way to dynamically check + // this at runtime, so User Beware. + void AddAllocated(Element* value); + + // Removes and returns the last element, passing ownership to the caller. + // Requires: size() > 0 + // + // If this RepeatedPtrField is on an arena, an object copy is required to pass + // ownership back to the user (for compatible semantics). Use + // UnsafeArenaReleaseLast() if this behavior is undesired. + PROTOBUF_NODISCARD Element* ReleaseLast(); + + // Adds an already-allocated object, skipping arena-ownership checks. The user + // must guarantee that the given object is in the same arena as this + // RepeatedPtrField. + // It is also useful in legacy code that uses temporary ownership to avoid + // copies. Example: + // RepeatedPtrField<T> temp_field; + // temp_field.UnsafeArenaAddAllocated(new T); + // ... // Do something with temp_field + // temp_field.UnsafeArenaExtractSubrange(0, temp_field.size(), nullptr); + // If you put temp_field on the arena this fails, because the ownership + // transfers to the arena at the "AddAllocated" call and is not released + // anymore, causing a double delete. UnsafeArenaAddAllocated prevents this. + void UnsafeArenaAddAllocated(Element* value); + + // Removes and returns the last element. Unlike ReleaseLast, the returned + // pointer is always to the original object. This may be in an arena, in + // which case it would have the arena's lifetime. + // Requires: current_size_ > 0 + Element* UnsafeArenaReleaseLast(); + + // Extracts elements with indices in the range "[start .. start+num-1]". + // The caller assumes ownership of the extracted elements and is responsible + // for deleting them when they are no longer needed. + // If "elements" is non-nullptr, then pointers to the extracted elements + // are stored in "elements[0 .. num-1]" for the convenience of the caller. + // If "elements" is nullptr, then the caller must use some other mechanism + // to perform any further operations (like deletion) on these elements. + // Caution: implementation also moves elements with indices [start+num ..]. + // Calling this routine inside a loop can cause quadratic behavior. + // + // Memory copying behavior is identical to ReleaseLast(), described above: if + // this RepeatedPtrField is on an arena, an object copy is performed for each + // returned element, so that all returned element pointers are to + // heap-allocated copies. If this copy is not desired, the user should call + // UnsafeArenaExtractSubrange(). + void ExtractSubrange(int start, int num, Element** elements); + + // Identical to ExtractSubrange() described above, except that no object + // copies are ever performed. Instead, the raw object pointers are returned. + // Thus, if on an arena, the returned objects must not be freed, because they + // will not be heap-allocated objects. + void UnsafeArenaExtractSubrange(int start, int num, Element** elements); + + // When elements are removed by calls to RemoveLast() or Clear(), they + // are not actually freed. Instead, they are cleared and kept so that + // they can be reused later. This can save lots of CPU time when + // repeatedly reusing a protocol message for similar purposes. + // + // Hardcore programs may choose to manipulate these cleared objects + // to better optimize memory management using the following routines. + + // Gets the number of cleared objects that are currently being kept + // around for reuse. + int ClearedCount() const; +#ifndef PROTOBUF_FUTURE_BREAKING_CHANGES + // Adds an element to the pool of cleared objects, passing ownership to + // the RepeatedPtrField. The element must be cleared prior to calling + // this method. + // + // This method cannot be called when either the repeated field or |value| is + // on an arena; both cases will trigger a GOOGLE_DCHECK-failure. + void AddCleared(Element* value); + // Removes and returns a single element from the cleared pool, passing + // ownership to the caller. The element is guaranteed to be cleared. + // Requires: ClearedCount() > 0 + // + // This method cannot be called when the repeated field is on an arena; doing + // so will trigger a GOOGLE_DCHECK-failure. + PROTOBUF_NODISCARD Element* ReleaseCleared(); +#endif // !PROTOBUF_FUTURE_BREAKING_CHANGES + + // Removes the element referenced by position. + // + // Returns an iterator to the element immediately following the removed + // element. + // + // Invalidates all iterators at or after the removed element, including end(). + iterator erase(const_iterator position); + + // Removes the elements in the range [first, last). + // + // Returns an iterator to the element immediately following the removed range. + // + // Invalidates all iterators at or after the removed range, including end(). + iterator erase(const_iterator first, const_iterator last); + + // Gets the arena on which this RepeatedPtrField stores its elements. + inline Arena* GetArena() const; + + // For internal use only. + // + // This is public due to it being called by generated code. + void InternalSwap(RepeatedPtrField* other) { + internal::RepeatedPtrFieldBase::InternalSwap(other); + } + + private: + // Note: RepeatedPtrField SHOULD NOT be subclassed by users. + class TypeHandler; + + // Internal version of GetArena(). + inline Arena* GetOwningArena() const; + + // Implementations for ExtractSubrange(). The copying behavior must be + // included only if the type supports the necessary operations (e.g., + // MergeFrom()), so we must resolve this at compile time. ExtractSubrange() + // uses SFINAE to choose one of the below implementations. + void ExtractSubrangeInternal(int start, int num, Element** elements, + std::true_type); + void ExtractSubrangeInternal(int start, int num, Element** elements, + std::false_type); + + friend class Arena; + + template <typename T> + friend struct WeakRepeatedPtrField; + + typedef void InternalArenaConstructable_; + +}; + +// ------------------------------------------------------------------- + +template <typename Element> +class RepeatedPtrField<Element>::TypeHandler + : public internal::GenericTypeHandler<Element> {}; + +template <> +class RepeatedPtrField<std::string>::TypeHandler + : public internal::StringTypeHandler {}; + +template <typename Element> +constexpr RepeatedPtrField<Element>::RepeatedPtrField() + : RepeatedPtrFieldBase() {} + +template <typename Element> +inline RepeatedPtrField<Element>::RepeatedPtrField(Arena* arena) + : RepeatedPtrFieldBase(arena) {} + +template <typename Element> +inline RepeatedPtrField<Element>::RepeatedPtrField( + const RepeatedPtrField& other) + : RepeatedPtrFieldBase() { + MergeFrom(other); +} + +template <typename Element> +template <typename Iter, typename> +inline RepeatedPtrField<Element>::RepeatedPtrField(Iter begin, Iter end) { + Add(begin, end); +} + +template <typename Element> +RepeatedPtrField<Element>::~RepeatedPtrField() { +#ifdef __cpp_if_constexpr + if constexpr (std::is_base_of<MessageLite, Element>::value) { +#else + if (std::is_base_of<MessageLite, Element>::value) { +#endif + if (NeedsDestroy()) DestroyProtos(); + } else { + Destroy<TypeHandler>(); + } +} + +template <typename Element> +inline RepeatedPtrField<Element>& RepeatedPtrField<Element>::operator=( + const RepeatedPtrField& other) { + if (this != &other) CopyFrom(other); + return *this; +} + +template <typename Element> +inline RepeatedPtrField<Element>::RepeatedPtrField( + RepeatedPtrField&& other) noexcept + : RepeatedPtrField() { +#ifdef PROTOBUF_FORCE_COPY_IN_MOVE + CopyFrom(other); +#else // PROTOBUF_FORCE_COPY_IN_MOVE + // We don't just call Swap(&other) here because it would perform 3 copies if + // other is on an arena. This field can't be on an arena because arena + // construction always uses the Arena* accepting constructor. + if (other.GetOwningArena()) { + CopyFrom(other); + } else { + InternalSwap(&other); + } +#endif // !PROTOBUF_FORCE_COPY_IN_MOVE +} + +template <typename Element> +inline RepeatedPtrField<Element>& RepeatedPtrField<Element>::operator=( + RepeatedPtrField&& other) noexcept { + // We don't just call Swap(&other) here because it would perform 3 copies if + // the two fields are on different arenas. + if (this != &other) { + if (GetOwningArena() != other.GetOwningArena() +#ifdef PROTOBUF_FORCE_COPY_IN_MOVE + || GetOwningArena() == nullptr +#endif // !PROTOBUF_FORCE_COPY_IN_MOVE + ) { + CopyFrom(other); + } else { + InternalSwap(&other); + } + } + return *this; +} + +template <typename Element> +inline bool RepeatedPtrField<Element>::empty() const { + return RepeatedPtrFieldBase::empty(); +} + +template <typename Element> +inline int RepeatedPtrField<Element>::size() const { + return RepeatedPtrFieldBase::size(); +} + +template <typename Element> +inline const Element& RepeatedPtrField<Element>::Get(int index) const { + return RepeatedPtrFieldBase::Get<TypeHandler>(index); +} + +template <typename Element> +inline const Element& RepeatedPtrField<Element>::at(int index) const { + return RepeatedPtrFieldBase::at<TypeHandler>(index); +} + +template <typename Element> +inline Element& RepeatedPtrField<Element>::at(int index) { + return RepeatedPtrFieldBase::at<TypeHandler>(index); +} + + +template <typename Element> +inline Element* RepeatedPtrField<Element>::Mutable(int index) { + return RepeatedPtrFieldBase::Mutable<TypeHandler>(index); +} + +template <typename Element> +inline Element* RepeatedPtrField<Element>::Add() { + return RepeatedPtrFieldBase::Add<TypeHandler>(); +} + +template <typename Element> +inline void RepeatedPtrField<Element>::Add(Element&& value) { + RepeatedPtrFieldBase::Add<TypeHandler>(std::move(value)); +} + +template <typename Element> +template <typename Iter> +inline void RepeatedPtrField<Element>::Add(Iter begin, Iter end) { + if (std::is_base_of< + std::forward_iterator_tag, + typename std::iterator_traits<Iter>::iterator_category>::value) { + int reserve = std::distance(begin, end); + Reserve(size() + reserve); + } + for (; begin != end; ++begin) { + *Add() = *begin; + } +} + +template <typename Element> +inline void RepeatedPtrField<Element>::RemoveLast() { + RepeatedPtrFieldBase::RemoveLast<TypeHandler>(); +} + +template <typename Element> +inline void RepeatedPtrField<Element>::DeleteSubrange(int start, int num) { + GOOGLE_DCHECK_GE(start, 0); + GOOGLE_DCHECK_GE(num, 0); + GOOGLE_DCHECK_LE(start + num, size()); + for (int i = 0; i < num; ++i) { + RepeatedPtrFieldBase::Delete<TypeHandler>(start + i); + } + UnsafeArenaExtractSubrange(start, num, nullptr); +} + +template <typename Element> +inline void RepeatedPtrField<Element>::ExtractSubrange(int start, int num, + Element** elements) { + typename internal::TypeImplementsMergeBehavior< + typename TypeHandler::Type>::type t; + ExtractSubrangeInternal(start, num, elements, t); +} + +// ExtractSubrange() implementation for types that implement merge/copy +// behavior. +template <typename Element> +inline void RepeatedPtrField<Element>::ExtractSubrangeInternal( + int start, int num, Element** elements, std::true_type) { + GOOGLE_DCHECK_GE(start, 0); + GOOGLE_DCHECK_GE(num, 0); + GOOGLE_DCHECK_LE(start + num, size()); + + if (num == 0) return; + + GOOGLE_DCHECK_NE(elements, nullptr) + << "Releasing elements without transferring ownership is an unsafe " + "operation. Use UnsafeArenaExtractSubrange."; + if (elements == nullptr) { + CloseGap(start, num); + return; + } + + Arena* arena = GetOwningArena(); +#ifdef PROTOBUF_FORCE_COPY_IN_RELEASE + // Always copy. + for (int i = 0; i < num; ++i) { + elements[i] = copy<TypeHandler>( + RepeatedPtrFieldBase::Mutable<TypeHandler>(i + start)); + } + if (arena == nullptr) { + for (int i = 0; i < num; ++i) { + delete RepeatedPtrFieldBase::Mutable<TypeHandler>(i + start); + } + } +#else // PROTOBUF_FORCE_COPY_IN_RELEASE + // If we're on an arena, we perform a copy for each element so that the + // returned elements are heap-allocated. Otherwise, just forward it. + if (arena != nullptr) { + for (int i = 0; i < num; ++i) { + elements[i] = copy<TypeHandler>( + RepeatedPtrFieldBase::Mutable<TypeHandler>(i + start)); + } + } else { + for (int i = 0; i < num; ++i) { + elements[i] = RepeatedPtrFieldBase::Mutable<TypeHandler>(i + start); + } + } +#endif // !PROTOBUF_FORCE_COPY_IN_RELEASE + CloseGap(start, num); +} + +// ExtractSubrange() implementation for types that do not implement merge/copy +// behavior. +template <typename Element> +inline void RepeatedPtrField<Element>::ExtractSubrangeInternal( + int start, int num, Element** elements, std::false_type) { + // This case is identical to UnsafeArenaExtractSubrange(). However, since + // ExtractSubrange() must return heap-allocated objects by contract, and we + // cannot fulfill this contract if we are an on arena, we must GOOGLE_DCHECK() that + // we are not on an arena. + GOOGLE_DCHECK(GetOwningArena() == nullptr) + << "ExtractSubrange() when arena is non-nullptr is only supported when " + << "the Element type supplies a MergeFrom() operation to make copies."; + UnsafeArenaExtractSubrange(start, num, elements); +} + +template <typename Element> +inline void RepeatedPtrField<Element>::UnsafeArenaExtractSubrange( + int start, int num, Element** elements) { + GOOGLE_DCHECK_GE(start, 0); + GOOGLE_DCHECK_GE(num, 0); + GOOGLE_DCHECK_LE(start + num, size()); + + if (num > 0) { + // Save the values of the removed elements if requested. + if (elements != nullptr) { + for (int i = 0; i < num; ++i) { + elements[i] = RepeatedPtrFieldBase::Mutable<TypeHandler>(i + start); + } + } + CloseGap(start, num); + } +} + +template <typename Element> +inline void RepeatedPtrField<Element>::Clear() { + RepeatedPtrFieldBase::Clear<TypeHandler>(); +} + +template <typename Element> +inline void RepeatedPtrField<Element>::MergeFrom( + const RepeatedPtrField& other) { + RepeatedPtrFieldBase::MergeFrom<TypeHandler>(other); +} + +template <typename Element> +inline void RepeatedPtrField<Element>::CopyFrom(const RepeatedPtrField& other) { + RepeatedPtrFieldBase::CopyFrom<TypeHandler>(other); +} + +template <typename Element> +template <typename Iter> +inline void RepeatedPtrField<Element>::Assign(Iter begin, Iter end) { + Clear(); + Add(begin, end); +} + +template <typename Element> +inline typename RepeatedPtrField<Element>::iterator +RepeatedPtrField<Element>::erase(const_iterator position) { + return erase(position, position + 1); +} + +template <typename Element> +inline typename RepeatedPtrField<Element>::iterator +RepeatedPtrField<Element>::erase(const_iterator first, const_iterator last) { + size_type pos_offset = std::distance(cbegin(), first); + size_type last_offset = std::distance(cbegin(), last); + DeleteSubrange(pos_offset, last_offset - pos_offset); + return begin() + pos_offset; +} + +template <typename Element> +inline Element** RepeatedPtrField<Element>::mutable_data() { + return RepeatedPtrFieldBase::mutable_data<TypeHandler>(); +} + +template <typename Element> +inline const Element* const* RepeatedPtrField<Element>::data() const { + return RepeatedPtrFieldBase::data<TypeHandler>(); +} + +template <typename Element> +inline void RepeatedPtrField<Element>::Swap(RepeatedPtrField* other) { + if (this == other) return; + RepeatedPtrFieldBase::Swap<TypeHandler>(other); +} + +template <typename Element> +inline void RepeatedPtrField<Element>::UnsafeArenaSwap( + RepeatedPtrField* other) { + if (this == other) return; + GOOGLE_DCHECK_EQ(GetOwningArena(), other->GetOwningArena()); + RepeatedPtrFieldBase::InternalSwap(other); +} + +template <typename Element> +inline void RepeatedPtrField<Element>::SwapElements(int index1, int index2) { + RepeatedPtrFieldBase::SwapElements(index1, index2); +} + +template <typename Element> +inline Arena* RepeatedPtrField<Element>::GetArena() const { + return RepeatedPtrFieldBase::GetArena(); +} + +template <typename Element> +inline Arena* RepeatedPtrField<Element>::GetOwningArena() const { + return RepeatedPtrFieldBase::GetOwningArena(); +} + +template <typename Element> +inline size_t RepeatedPtrField<Element>::SpaceUsedExcludingSelfLong() const { + return RepeatedPtrFieldBase::SpaceUsedExcludingSelfLong<TypeHandler>(); +} + +template <typename Element> +inline void RepeatedPtrField<Element>::AddAllocated(Element* value) { + RepeatedPtrFieldBase::AddAllocated<TypeHandler>(value); +} + +template <typename Element> +inline void RepeatedPtrField<Element>::UnsafeArenaAddAllocated(Element* value) { + RepeatedPtrFieldBase::UnsafeArenaAddAllocated<TypeHandler>(value); +} + +template <typename Element> +inline Element* RepeatedPtrField<Element>::ReleaseLast() { + return RepeatedPtrFieldBase::ReleaseLast<TypeHandler>(); +} + +template <typename Element> +inline Element* RepeatedPtrField<Element>::UnsafeArenaReleaseLast() { + return RepeatedPtrFieldBase::UnsafeArenaReleaseLast<TypeHandler>(); +} + +template <typename Element> +inline int RepeatedPtrField<Element>::ClearedCount() const { + return RepeatedPtrFieldBase::ClearedCount(); +} + +#ifndef PROTOBUF_FUTURE_BREAKING_CHANGES +template <typename Element> +inline void RepeatedPtrField<Element>::AddCleared(Element* value) { + return RepeatedPtrFieldBase::AddCleared<TypeHandler>(value); +} + +template <typename Element> +inline Element* RepeatedPtrField<Element>::ReleaseCleared() { + return RepeatedPtrFieldBase::ReleaseCleared<TypeHandler>(); +} +#endif // !PROTOBUF_FUTURE_BREAKING_CHANGES + +template <typename Element> +inline void RepeatedPtrField<Element>::Reserve(int new_size) { + return RepeatedPtrFieldBase::Reserve(new_size); +} + +template <typename Element> +inline int RepeatedPtrField<Element>::Capacity() const { + return RepeatedPtrFieldBase::Capacity(); +} + +// ------------------------------------------------------------------- + +namespace internal { + +// STL-like iterator implementation for RepeatedPtrField. You should not +// refer to this class directly; use RepeatedPtrField<T>::iterator instead. +// +// The iterator for RepeatedPtrField<T>, RepeatedPtrIterator<T>, is +// very similar to iterator_ptr<T**> in util/gtl/iterator_adaptors.h, +// but adds random-access operators and is modified to wrap a void** base +// iterator (since RepeatedPtrField stores its array as a void* array and +// casting void** to T** would violate C++ aliasing rules). +// +// This code based on net/proto/proto-array-internal.h by Jeffrey Yasskin +// (jyasskin@google.com). +template <typename Element> +class RepeatedPtrIterator { + public: + using iterator = RepeatedPtrIterator<Element>; + using iterator_category = std::random_access_iterator_tag; + using value_type = typename std::remove_const<Element>::type; + using difference_type = std::ptrdiff_t; + using pointer = Element*; + using reference = Element&; + + RepeatedPtrIterator() : it_(nullptr) {} + explicit RepeatedPtrIterator(void* const* it) : it_(it) {} + + // Allows "upcasting" from RepeatedPtrIterator<T**> to + // RepeatedPtrIterator<const T*const*>. + template <typename OtherElement, + typename std::enable_if<std::is_convertible< + OtherElement*, pointer>::value>::type* = nullptr> + RepeatedPtrIterator(const RepeatedPtrIterator<OtherElement>& other) + : it_(other.it_) {} + + // dereferenceable + reference operator*() const { return *reinterpret_cast<Element*>(*it_); } + pointer operator->() const { return &(operator*()); } + + // {inc,dec}rementable + iterator& operator++() { + ++it_; + return *this; + } + iterator operator++(int) { return iterator(it_++); } + iterator& operator--() { + --it_; + return *this; + } + iterator operator--(int) { return iterator(it_--); } + + // equality_comparable + friend bool operator==(const iterator& x, const iterator& y) { + return x.it_ == y.it_; + } + friend bool operator!=(const iterator& x, const iterator& y) { + return x.it_ != y.it_; + } + + // less_than_comparable + friend bool operator<(const iterator& x, const iterator& y) { + return x.it_ < y.it_; + } + friend bool operator<=(const iterator& x, const iterator& y) { + return x.it_ <= y.it_; + } + friend bool operator>(const iterator& x, const iterator& y) { + return x.it_ > y.it_; + } + friend bool operator>=(const iterator& x, const iterator& y) { + return x.it_ >= y.it_; + } + + // addable, subtractable + iterator& operator+=(difference_type d) { + it_ += d; + return *this; + } + friend iterator operator+(iterator it, const difference_type d) { + it += d; + return it; + } + friend iterator operator+(const difference_type d, iterator it) { + it += d; + return it; + } + iterator& operator-=(difference_type d) { + it_ -= d; + return *this; + } + friend iterator operator-(iterator it, difference_type d) { + it -= d; + return it; + } + + // indexable + reference operator[](difference_type d) const { return *(*this + d); } + + // random access iterator + friend difference_type operator-(iterator it1, iterator it2) { + return it1.it_ - it2.it_; + } + + private: + template <typename OtherElement> + friend class RepeatedPtrIterator; + + // The internal iterator. + void* const* it_; +}; + +// Provides an iterator that operates on pointers to the underlying objects +// rather than the objects themselves as RepeatedPtrIterator does. +// Consider using this when working with stl algorithms that change +// the array. +// The VoidPtr template parameter holds the type-agnostic pointer value +// referenced by the iterator. It should either be "void *" for a mutable +// iterator, or "const void* const" for a constant iterator. +template <typename Element, typename VoidPtr> +class RepeatedPtrOverPtrsIterator { + public: + using iterator = RepeatedPtrOverPtrsIterator<Element, VoidPtr>; + using iterator_category = std::random_access_iterator_tag; + using value_type = typename std::remove_const<Element>::type; + using difference_type = std::ptrdiff_t; + using pointer = Element*; + using reference = Element&; + + RepeatedPtrOverPtrsIterator() : it_(nullptr) {} + explicit RepeatedPtrOverPtrsIterator(VoidPtr* it) : it_(it) {} + + // Allows "upcasting" from RepeatedPtrOverPtrsIterator<T**> to + // RepeatedPtrOverPtrsIterator<const T*const*>. + template < + typename OtherElement, typename OtherVoidPtr, + typename std::enable_if< + std::is_convertible<OtherElement*, pointer>::value && + std::is_convertible<OtherVoidPtr*, VoidPtr>::value>::type* = nullptr> + RepeatedPtrOverPtrsIterator( + const RepeatedPtrOverPtrsIterator<OtherElement, OtherVoidPtr>& other) + : it_(other.it_) {} + + // dereferenceable + reference operator*() const { return *reinterpret_cast<Element*>(it_); } + pointer operator->() const { return &(operator*()); } + + // {inc,dec}rementable + iterator& operator++() { + ++it_; + return *this; + } + iterator operator++(int) { return iterator(it_++); } + iterator& operator--() { + --it_; + return *this; + } + iterator operator--(int) { return iterator(it_--); } + + // equality_comparable + friend bool operator==(const iterator& x, const iterator& y) { + return x.it_ == y.it_; + } + friend bool operator!=(const iterator& x, const iterator& y) { + return x.it_ != y.it_; + } + + // less_than_comparable + friend bool operator<(const iterator& x, const iterator& y) { + return x.it_ < y.it_; + } + friend bool operator<=(const iterator& x, const iterator& y) { + return x.it_ <= y.it_; + } + friend bool operator>(const iterator& x, const iterator& y) { + return x.it_ > y.it_; + } + friend bool operator>=(const iterator& x, const iterator& y) { + return x.it_ >= y.it_; + } + + // addable, subtractable + iterator& operator+=(difference_type d) { + it_ += d; + return *this; + } + friend iterator operator+(iterator it, difference_type d) { + it += d; + return it; + } + friend iterator operator+(difference_type d, iterator it) { + it += d; + return it; + } + iterator& operator-=(difference_type d) { + it_ -= d; + return *this; + } + friend iterator operator-(iterator it, difference_type d) { + it -= d; + return it; + } + + // indexable + reference operator[](difference_type d) const { return *(*this + d); } + + // random access iterator + friend difference_type operator-(iterator it1, iterator it2) { + return it1.it_ - it2.it_; + } + + private: + template <typename OtherElement, typename OtherVoidPtr> + friend class RepeatedPtrOverPtrsIterator; + + // The internal iterator. + VoidPtr* it_; +}; + +} // namespace internal + +template <typename Element> +inline typename RepeatedPtrField<Element>::iterator +RepeatedPtrField<Element>::begin() { + return iterator(raw_data()); +} +template <typename Element> +inline typename RepeatedPtrField<Element>::const_iterator +RepeatedPtrField<Element>::begin() const { + return iterator(raw_data()); +} +template <typename Element> +inline typename RepeatedPtrField<Element>::const_iterator +RepeatedPtrField<Element>::cbegin() const { + return begin(); +} +template <typename Element> +inline typename RepeatedPtrField<Element>::iterator +RepeatedPtrField<Element>::end() { + return iterator(raw_data() + size()); +} +template <typename Element> +inline typename RepeatedPtrField<Element>::const_iterator +RepeatedPtrField<Element>::end() const { + return iterator(raw_data() + size()); +} +template <typename Element> +inline typename RepeatedPtrField<Element>::const_iterator +RepeatedPtrField<Element>::cend() const { + return end(); +} + +template <typename Element> +inline typename RepeatedPtrField<Element>::pointer_iterator +RepeatedPtrField<Element>::pointer_begin() { + return pointer_iterator(raw_mutable_data()); +} +template <typename Element> +inline typename RepeatedPtrField<Element>::const_pointer_iterator +RepeatedPtrField<Element>::pointer_begin() const { + return const_pointer_iterator(const_cast<const void* const*>(raw_data())); +} +template <typename Element> +inline typename RepeatedPtrField<Element>::pointer_iterator +RepeatedPtrField<Element>::pointer_end() { + return pointer_iterator(raw_mutable_data() + size()); +} +template <typename Element> +inline typename RepeatedPtrField<Element>::const_pointer_iterator +RepeatedPtrField<Element>::pointer_end() const { + return const_pointer_iterator( + const_cast<const void* const*>(raw_data() + size())); +} + +// Iterators and helper functions that follow the spirit of the STL +// std::back_insert_iterator and std::back_inserter but are tailor-made +// for RepeatedField and RepeatedPtrField. Typical usage would be: +// +// std::copy(some_sequence.begin(), some_sequence.end(), +// RepeatedFieldBackInserter(proto.mutable_sequence())); +// +// Ported by johannes from util/gtl/proto-array-iterators.h + +namespace internal { + +// A back inserter for RepeatedPtrField objects. +template <typename T> +class RepeatedPtrFieldBackInsertIterator { + public: + using iterator_category = std::output_iterator_tag; + using value_type = T; + using pointer = void; + using reference = void; + using difference_type = std::ptrdiff_t; + + RepeatedPtrFieldBackInsertIterator(RepeatedPtrField<T>* const mutable_field) + : field_(mutable_field) {} + RepeatedPtrFieldBackInsertIterator<T>& operator=(const T& value) { + *field_->Add() = value; + return *this; + } + RepeatedPtrFieldBackInsertIterator<T>& operator=( + const T* const ptr_to_value) { + *field_->Add() = *ptr_to_value; + return *this; + } + RepeatedPtrFieldBackInsertIterator<T>& operator=(T&& value) { + *field_->Add() = std::move(value); + return *this; + } + RepeatedPtrFieldBackInsertIterator<T>& operator*() { return *this; } + RepeatedPtrFieldBackInsertIterator<T>& operator++() { return *this; } + RepeatedPtrFieldBackInsertIterator<T>& operator++(int /* unused */) { + return *this; + } + + private: + RepeatedPtrField<T>* field_; +}; + +// A back inserter for RepeatedPtrFields that inserts by transferring ownership +// of a pointer. +template <typename T> +class AllocatedRepeatedPtrFieldBackInsertIterator { + public: + using iterator_category = std::output_iterator_tag; + using value_type = T; + using pointer = void; + using reference = void; + using difference_type = std::ptrdiff_t; + + explicit AllocatedRepeatedPtrFieldBackInsertIterator( + RepeatedPtrField<T>* const mutable_field) + : field_(mutable_field) {} + AllocatedRepeatedPtrFieldBackInsertIterator<T>& operator=( + T* const ptr_to_value) { + field_->AddAllocated(ptr_to_value); + return *this; + } + AllocatedRepeatedPtrFieldBackInsertIterator<T>& operator*() { return *this; } + AllocatedRepeatedPtrFieldBackInsertIterator<T>& operator++() { return *this; } + AllocatedRepeatedPtrFieldBackInsertIterator<T>& operator++(int /* unused */) { + return *this; + } + + private: + RepeatedPtrField<T>* field_; +}; + +// Almost identical to AllocatedRepeatedPtrFieldBackInsertIterator. This one +// uses the UnsafeArenaAddAllocated instead. +template <typename T> +class UnsafeArenaAllocatedRepeatedPtrFieldBackInsertIterator { + public: + using iterator_category = std::output_iterator_tag; + using value_type = T; + using pointer = void; + using reference = void; + using difference_type = std::ptrdiff_t; + + explicit UnsafeArenaAllocatedRepeatedPtrFieldBackInsertIterator( + RepeatedPtrField<T>* const mutable_field) + : field_(mutable_field) {} + UnsafeArenaAllocatedRepeatedPtrFieldBackInsertIterator<T>& operator=( + T const* const ptr_to_value) { + field_->UnsafeArenaAddAllocated(const_cast<T*>(ptr_to_value)); + return *this; + } + UnsafeArenaAllocatedRepeatedPtrFieldBackInsertIterator<T>& operator*() { + return *this; + } + UnsafeArenaAllocatedRepeatedPtrFieldBackInsertIterator<T>& operator++() { + return *this; + } + UnsafeArenaAllocatedRepeatedPtrFieldBackInsertIterator<T>& operator++( + int /* unused */) { + return *this; + } + + private: + RepeatedPtrField<T>* field_; +}; + +} // namespace internal + +// Provides a back insert iterator for RepeatedPtrField instances, +// similar to std::back_inserter(). +template <typename T> +internal::RepeatedPtrFieldBackInsertIterator<T> RepeatedPtrFieldBackInserter( + RepeatedPtrField<T>* const mutable_field) { + return internal::RepeatedPtrFieldBackInsertIterator<T>(mutable_field); +} + +// Special back insert iterator for RepeatedPtrField instances, just in +// case someone wants to write generic template code that can access both +// RepeatedFields and RepeatedPtrFields using a common name. +template <typename T> +internal::RepeatedPtrFieldBackInsertIterator<T> RepeatedFieldBackInserter( + RepeatedPtrField<T>* const mutable_field) { + return internal::RepeatedPtrFieldBackInsertIterator<T>(mutable_field); +} + +// Provides a back insert iterator for RepeatedPtrField instances +// similar to std::back_inserter() which transfers the ownership while +// copying elements. +template <typename T> +internal::AllocatedRepeatedPtrFieldBackInsertIterator<T> +AllocatedRepeatedPtrFieldBackInserter( + RepeatedPtrField<T>* const mutable_field) { + return internal::AllocatedRepeatedPtrFieldBackInsertIterator<T>( + mutable_field); +} + +// Similar to AllocatedRepeatedPtrFieldBackInserter, using +// UnsafeArenaAddAllocated instead of AddAllocated. +// This is slightly faster if that matters. It is also useful in legacy code +// that uses temporary ownership to avoid copies. Example: +// RepeatedPtrField<T> temp_field; +// temp_field.UnsafeArenaAddAllocated(new T); +// ... // Do something with temp_field +// temp_field.UnsafeArenaExtractSubrange(0, temp_field.size(), nullptr); +// Putting temp_field on the arena fails because the ownership transfers to the +// arena at the "AddAllocated" call and is not released anymore causing a +// double delete. This function uses UnsafeArenaAddAllocated to prevent this. +template <typename T> +internal::UnsafeArenaAllocatedRepeatedPtrFieldBackInsertIterator<T> +UnsafeArenaAllocatedRepeatedPtrFieldBackInserter( + RepeatedPtrField<T>* const mutable_field) { + return internal::UnsafeArenaAllocatedRepeatedPtrFieldBackInsertIterator<T>( + mutable_field); +} + +extern template class PROTOBUF_EXPORT_TEMPLATE_DECLARE + RepeatedPtrField<std::string>; + +} // namespace protobuf +} // namespace google + +#include <google/protobuf/port_undef.inc> + +#endif // GOOGLE_PROTOBUF_REPEATED_PTR_FIELD_H__ diff --git a/toolkit/components/protobuf/src/google/protobuf/service.cc b/toolkit/components/protobuf/src/google/protobuf/service.cc new file mode 100644 index 0000000000..53945684cb --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/service.cc @@ -0,0 +1,45 @@ +// 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. + +// Author: kenton@google.com (Kenton Varda) +// Based on original Protocol Buffers design by +// Sanjay Ghemawat, Jeff Dean, and others. + +#include <google/protobuf/service.h> + +namespace google { +namespace protobuf { + +Service::~Service() {} +RpcChannel::~RpcChannel() {} +RpcController::~RpcController() {} + +} // namespace protobuf +} // namespace google diff --git a/toolkit/components/protobuf/src/google/protobuf/service.h b/toolkit/components/protobuf/src/google/protobuf/service.h new file mode 100644 index 0000000000..d288eb554a --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/service.h @@ -0,0 +1,295 @@ +// 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. + +// Author: kenton@google.com (Kenton Varda) +// Based on original Protocol Buffers design by +// Sanjay Ghemawat, Jeff Dean, and others. +// +// DEPRECATED: This module declares the abstract interfaces underlying proto2 +// RPC services. These are intended to be independent of any particular RPC +// implementation, so that proto2 services can be used on top of a variety +// of implementations. Starting with version 2.3.0, RPC implementations should +// not try to build on these, but should instead provide code generator plugins +// which generate code specific to the particular RPC implementation. This way +// the generated code can be more appropriate for the implementation in use +// and can avoid unnecessary layers of indirection. +// +// +// When you use the protocol compiler to compile a service definition, it +// generates two classes: An abstract interface for the service (with +// methods matching the service definition) and a "stub" implementation. +// A stub is just a type-safe wrapper around an RpcChannel which emulates a +// local implementation of the service. +// +// For example, the service definition: +// service MyService { +// rpc Foo(MyRequest) returns(MyResponse); +// } +// will generate abstract interface "MyService" and class "MyService::Stub". +// You could implement a MyService as follows: +// class MyServiceImpl : public MyService { +// public: +// MyServiceImpl() {} +// ~MyServiceImpl() {} +// +// // implements MyService --------------------------------------- +// +// void Foo(google::protobuf::RpcController* controller, +// const MyRequest* request, +// MyResponse* response, +// Closure* done) { +// // ... read request and fill in response ... +// done->Run(); +// } +// }; +// You would then register an instance of MyServiceImpl with your RPC server +// implementation. (How to do that depends on the implementation.) +// +// To call a remote MyServiceImpl, first you need an RpcChannel connected to it. +// How to construct a channel depends, again, on your RPC implementation. +// Here we use a hypothetical "MyRpcChannel" as an example: +// MyRpcChannel channel("rpc:hostname:1234/myservice"); +// MyRpcController controller; +// MyServiceImpl::Stub stub(&channel); +// FooRequest request; +// FooResponse response; +// +// // ... fill in request ... +// +// stub.Foo(&controller, request, &response, NewCallback(HandleResponse)); +// +// On Thread-Safety: +// +// Different RPC implementations may make different guarantees about what +// threads they may run callbacks on, and what threads the application is +// allowed to use to call the RPC system. Portable software should be ready +// for callbacks to be called on any thread, but should not try to call the +// RPC system from any thread except for the ones on which it received the +// callbacks. Realistically, though, simple software will probably want to +// use a single-threaded RPC system while high-end software will want to +// use multiple threads. RPC implementations should provide multiple +// choices. + +#ifndef GOOGLE_PROTOBUF_SERVICE_H__ +#define GOOGLE_PROTOBUF_SERVICE_H__ + + +#include <string> +#include <google/protobuf/stubs/callback.h> +#include <google/protobuf/stubs/common.h> + +#ifdef SWIG +#error "You cannot SWIG proto headers" +#endif + +// Must be included last. +#include <google/protobuf/port_def.inc> + +namespace google { +namespace protobuf { + +// Defined in this file. +class Service; +class RpcController; +class RpcChannel; + +// Defined in other files. +class Descriptor; // descriptor.h +class ServiceDescriptor; // descriptor.h +class MethodDescriptor; // descriptor.h +class Message; // message.h + +// Abstract base interface for protocol-buffer-based RPC services. Services +// themselves are abstract interfaces (implemented either by servers or as +// stubs), but they subclass this base interface. The methods of this +// interface can be used to call the methods of the Service without knowing +// its exact type at compile time (analogous to Reflection). +class PROTOBUF_EXPORT Service { + public: + inline Service() {} + virtual ~Service(); + + // When constructing a stub, you may pass STUB_OWNS_CHANNEL as the second + // parameter to the constructor to tell it to delete its RpcChannel when + // destroyed. + enum ChannelOwnership { STUB_OWNS_CHANNEL, STUB_DOESNT_OWN_CHANNEL }; + + // Get the ServiceDescriptor describing this service and its methods. + virtual const ServiceDescriptor* GetDescriptor() = 0; + + // Call a method of the service specified by MethodDescriptor. This is + // normally implemented as a simple switch() that calls the standard + // definitions of the service's methods. + // + // Preconditions: + // * method->service() == GetDescriptor() + // * request and response are of the exact same classes as the objects + // returned by GetRequestPrototype(method) and + // GetResponsePrototype(method). + // * After the call has started, the request must not be modified and the + // response must not be accessed at all until "done" is called. + // * "controller" is of the correct type for the RPC implementation being + // used by this Service. For stubs, the "correct type" depends on the + // RpcChannel which the stub is using. Server-side Service + // implementations are expected to accept whatever type of RpcController + // the server-side RPC implementation uses. + // + // Postconditions: + // * "done" will be called when the method is complete. This may be + // before CallMethod() returns or it may be at some point in the future. + // * If the RPC succeeded, "response" contains the response returned by + // the server. + // * If the RPC failed, "response"'s contents are undefined. The + // RpcController can be queried to determine if an error occurred and + // possibly to get more information about the error. + virtual void CallMethod(const MethodDescriptor* method, + RpcController* controller, const Message* request, + Message* response, Closure* done) = 0; + + // CallMethod() requires that the request and response passed in are of a + // particular subclass of Message. GetRequestPrototype() and + // GetResponsePrototype() get the default instances of these required types. + // You can then call Message::New() on these instances to construct mutable + // objects which you can then pass to CallMethod(). + // + // Example: + // const MethodDescriptor* method = + // service->GetDescriptor()->FindMethodByName("Foo"); + // Message* request = stub->GetRequestPrototype (method)->New(); + // Message* response = stub->GetResponsePrototype(method)->New(); + // request->ParseFromString(input); + // service->CallMethod(method, *request, response, callback); + virtual const Message& GetRequestPrototype( + const MethodDescriptor* method) const = 0; + virtual const Message& GetResponsePrototype( + const MethodDescriptor* method) const = 0; + + private: + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Service); +}; + +// An RpcController mediates a single method call. The primary purpose of +// the controller is to provide a way to manipulate settings specific to the +// RPC implementation and to find out about RPC-level errors. +// +// The methods provided by the RpcController interface are intended to be a +// "least common denominator" set of features which we expect all +// implementations to support. Specific implementations may provide more +// advanced features (e.g. deadline propagation). +class PROTOBUF_EXPORT RpcController { + public: + inline RpcController() {} + virtual ~RpcController(); + + // Client-side methods --------------------------------------------- + // These calls may be made from the client side only. Their results + // are undefined on the server side (may crash). + + // Resets the RpcController to its initial state so that it may be reused in + // a new call. Must not be called while an RPC is in progress. + virtual void Reset() = 0; + + // After a call has finished, returns true if the call failed. The possible + // reasons for failure depend on the RPC implementation. Failed() must not + // be called before a call has finished. If Failed() returns true, the + // contents of the response message are undefined. + virtual bool Failed() const = 0; + + // If Failed() is true, returns a human-readable description of the error. + virtual std::string ErrorText() const = 0; + + // Advises the RPC system that the caller desires that the RPC call be + // canceled. The RPC system may cancel it immediately, may wait awhile and + // then cancel it, or may not even cancel the call at all. If the call is + // canceled, the "done" callback will still be called and the RpcController + // will indicate that the call failed at that time. + virtual void StartCancel() = 0; + + // Server-side methods --------------------------------------------- + // These calls may be made from the server side only. Their results + // are undefined on the client side (may crash). + + // Causes Failed() to return true on the client side. "reason" will be + // incorporated into the message returned by ErrorText(). If you find + // you need to return machine-readable information about failures, you + // should incorporate it into your response protocol buffer and should + // NOT call SetFailed(). + virtual void SetFailed(const std::string& reason) = 0; + + // If true, indicates that the client canceled the RPC, so the server may + // as well give up on replying to it. The server should still call the + // final "done" callback. + virtual bool IsCanceled() const = 0; + + // Asks that the given callback be called when the RPC is canceled. The + // callback will always be called exactly once. If the RPC completes without + // being canceled, the callback will be called after completion. If the RPC + // has already been canceled when NotifyOnCancel() is called, the callback + // will be called immediately. + // + // NotifyOnCancel() must be called no more than once per request. + virtual void NotifyOnCancel(Closure* callback) = 0; + + private: + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RpcController); +}; + +// Abstract interface for an RPC channel. An RpcChannel represents a +// communication line to a Service which can be used to call that Service's +// methods. The Service may be running on another machine. Normally, you +// should not call an RpcChannel directly, but instead construct a stub Service +// wrapping it. Example: +// RpcChannel* channel = new MyRpcChannel("remotehost.example.com:1234"); +// MyService* service = new MyService::Stub(channel); +// service->MyMethod(request, &response, callback); +class PROTOBUF_EXPORT RpcChannel { + public: + inline RpcChannel() {} + virtual ~RpcChannel(); + + // Call the given method of the remote service. The signature of this + // procedure looks the same as Service::CallMethod(), but the requirements + // are less strict in one important way: the request and response objects + // need not be of any specific class as long as their descriptors are + // method->input_type() and method->output_type(). + virtual void CallMethod(const MethodDescriptor* method, + RpcController* controller, const Message* request, + Message* response, Closure* done) = 0; + + private: + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RpcChannel); +}; + +} // namespace protobuf +} // namespace google + +#include <google/protobuf/port_undef.inc> + +#endif // GOOGLE_PROTOBUF_SERVICE_H__ diff --git a/toolkit/components/protobuf/src/google/protobuf/source_context.pb.cc b/toolkit/components/protobuf/src/google/protobuf/source_context.pb.cc new file mode 100644 index 0000000000..e7525e99cf --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/source_context.pb.cc @@ -0,0 +1,297 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: google/protobuf/source_context.proto + +#include <google/protobuf/source_context.pb.h> + +#include <algorithm> + +#include <google/protobuf/io/coded_stream.h> +#include <google/protobuf/extension_set.h> +#include <google/protobuf/wire_format_lite.h> +#include <google/protobuf/descriptor.h> +#include <google/protobuf/generated_message_reflection.h> +#include <google/protobuf/reflection_ops.h> +#include <google/protobuf/wire_format.h> +// @@protoc_insertion_point(includes) +#include <google/protobuf/port_def.inc> + +PROTOBUF_PRAGMA_INIT_SEG + +namespace _pb = ::PROTOBUF_NAMESPACE_ID; +namespace _pbi = _pb::internal; + +PROTOBUF_NAMESPACE_OPEN +PROTOBUF_CONSTEXPR SourceContext::SourceContext( + ::_pbi::ConstantInitialized): _impl_{ + /*decltype(_impl_.file_name_)*/{&::_pbi::fixed_address_empty_string, ::_pbi::ConstantInitialized{}} + , /*decltype(_impl_._cached_size_)*/{}} {} +struct SourceContextDefaultTypeInternal { + PROTOBUF_CONSTEXPR SourceContextDefaultTypeInternal() + : _instance(::_pbi::ConstantInitialized{}) {} + ~SourceContextDefaultTypeInternal() {} + union { + SourceContext _instance; + }; +}; +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 SourceContextDefaultTypeInternal _SourceContext_default_instance_; +PROTOBUF_NAMESPACE_CLOSE +static ::_pb::Metadata file_level_metadata_google_2fprotobuf_2fsource_5fcontext_2eproto[1]; +static constexpr ::_pb::EnumDescriptor const** file_level_enum_descriptors_google_2fprotobuf_2fsource_5fcontext_2eproto = nullptr; +static constexpr ::_pb::ServiceDescriptor const** file_level_service_descriptors_google_2fprotobuf_2fsource_5fcontext_2eproto = nullptr; + +const uint32_t TableStruct_google_2fprotobuf_2fsource_5fcontext_2eproto::offsets[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = { + ~0u, // no _has_bits_ + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::SourceContext, _internal_metadata_), + ~0u, // no _extensions_ + ~0u, // no _oneof_case_ + ~0u, // no _weak_field_map_ + ~0u, // no _inlined_string_donated_ + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::SourceContext, _impl_.file_name_), +}; +static const ::_pbi::MigrationSchema schemas[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = { + { 0, -1, -1, sizeof(::PROTOBUF_NAMESPACE_ID::SourceContext)}, +}; + +static const ::_pb::Message* const file_default_instances[] = { + &::PROTOBUF_NAMESPACE_ID::_SourceContext_default_instance_._instance, +}; + +const char descriptor_table_protodef_google_2fprotobuf_2fsource_5fcontext_2eproto[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = + "\n$google/protobuf/source_context.proto\022\017" + "google.protobuf\"\"\n\rSourceContext\022\021\n\tfile" + "_name\030\001 \001(\tB\212\001\n\023com.google.protobufB\022Sou" + "rceContextProtoP\001Z6google.golang.org/pro" + "tobuf/types/known/sourcecontextpb\242\002\003GPB\252" + "\002\036Google.Protobuf.WellKnownTypesb\006proto3" + ; +static ::_pbi::once_flag descriptor_table_google_2fprotobuf_2fsource_5fcontext_2eproto_once; +const ::_pbi::DescriptorTable descriptor_table_google_2fprotobuf_2fsource_5fcontext_2eproto = { + false, false, 240, descriptor_table_protodef_google_2fprotobuf_2fsource_5fcontext_2eproto, + "google/protobuf/source_context.proto", + &descriptor_table_google_2fprotobuf_2fsource_5fcontext_2eproto_once, nullptr, 0, 1, + schemas, file_default_instances, TableStruct_google_2fprotobuf_2fsource_5fcontext_2eproto::offsets, + file_level_metadata_google_2fprotobuf_2fsource_5fcontext_2eproto, file_level_enum_descriptors_google_2fprotobuf_2fsource_5fcontext_2eproto, + file_level_service_descriptors_google_2fprotobuf_2fsource_5fcontext_2eproto, +}; +PROTOBUF_ATTRIBUTE_WEAK const ::_pbi::DescriptorTable* descriptor_table_google_2fprotobuf_2fsource_5fcontext_2eproto_getter() { + return &descriptor_table_google_2fprotobuf_2fsource_5fcontext_2eproto; +} + +// Force running AddDescriptors() at dynamic initialization time. +PROTOBUF_ATTRIBUTE_INIT_PRIORITY2 static ::_pbi::AddDescriptorsRunner dynamic_init_dummy_google_2fprotobuf_2fsource_5fcontext_2eproto(&descriptor_table_google_2fprotobuf_2fsource_5fcontext_2eproto); +PROTOBUF_NAMESPACE_OPEN + +// =================================================================== + +class SourceContext::_Internal { + public: +}; + +SourceContext::SourceContext(::PROTOBUF_NAMESPACE_ID::Arena* arena, + bool is_message_owned) + : ::PROTOBUF_NAMESPACE_ID::Message(arena, is_message_owned) { + SharedCtor(arena, is_message_owned); + // @@protoc_insertion_point(arena_constructor:google.protobuf.SourceContext) +} +SourceContext::SourceContext(const SourceContext& from) + : ::PROTOBUF_NAMESPACE_ID::Message() { + SourceContext* const _this = this; (void)_this; + new (&_impl_) Impl_{ + decltype(_impl_.file_name_){} + , /*decltype(_impl_._cached_size_)*/{}}; + + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); + _impl_.file_name_.InitDefault(); + #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + _impl_.file_name_.Set("", GetArenaForAllocation()); + #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (!from._internal_file_name().empty()) { + _this->_impl_.file_name_.Set(from._internal_file_name(), + _this->GetArenaForAllocation()); + } + // @@protoc_insertion_point(copy_constructor:google.protobuf.SourceContext) +} + +inline void SourceContext::SharedCtor( + ::_pb::Arena* arena, bool is_message_owned) { + (void)arena; + (void)is_message_owned; + new (&_impl_) Impl_{ + decltype(_impl_.file_name_){} + , /*decltype(_impl_._cached_size_)*/{} + }; + _impl_.file_name_.InitDefault(); + #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + _impl_.file_name_.Set("", GetArenaForAllocation()); + #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING +} + +SourceContext::~SourceContext() { + // @@protoc_insertion_point(destructor:google.protobuf.SourceContext) + if (auto *arena = _internal_metadata_.DeleteReturnArena<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>()) { + (void)arena; + return; + } + SharedDtor(); +} + +inline void SourceContext::SharedDtor() { + GOOGLE_DCHECK(GetArenaForAllocation() == nullptr); + _impl_.file_name_.Destroy(); +} + +void SourceContext::SetCachedSize(int size) const { + _impl_._cached_size_.Set(size); +} + +void SourceContext::Clear() { +// @@protoc_insertion_point(message_clear_start:google.protobuf.SourceContext) + uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + _impl_.file_name_.ClearToEmpty(); + _internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); +} + +const char* SourceContext::_InternalParse(const char* ptr, ::_pbi::ParseContext* ctx) { +#define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure + while (!ctx->Done(&ptr)) { + uint32_t tag; + ptr = ::_pbi::ReadTag(ptr, &tag); + switch (tag >> 3) { + // string file_name = 1; + case 1: + if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 10)) { + auto str = _internal_mutable_file_name(); + ptr = ::_pbi::InlineGreedyStringParser(str, ptr, ctx); + CHK_(ptr); + CHK_(::_pbi::VerifyUTF8(str, "google.protobuf.SourceContext.file_name")); + } else + goto handle_unusual; + continue; + default: + goto handle_unusual; + } // switch + handle_unusual: + if ((tag == 0) || ((tag & 7) == 4)) { + CHK_(ptr); + ctx->SetLastTag(tag); + goto message_done; + } + ptr = UnknownFieldParse( + tag, + _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(), + ptr, ctx); + CHK_(ptr != nullptr); + } // while +message_done: + return ptr; +failure: + ptr = nullptr; + goto message_done; +#undef CHK_ +} + +uint8_t* SourceContext::_InternalSerialize( + uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const { + // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.SourceContext) + uint32_t cached_has_bits = 0; + (void) cached_has_bits; + + // string file_name = 1; + if (!this->_internal_file_name().empty()) { + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::VerifyUtf8String( + this->_internal_file_name().data(), static_cast<int>(this->_internal_file_name().length()), + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::SERIALIZE, + "google.protobuf.SourceContext.file_name"); + target = stream->WriteStringMaybeAliased( + 1, this->_internal_file_name(), target); + } + + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + target = ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( + _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.SourceContext) + return target; +} + +size_t SourceContext::ByteSizeLong() const { +// @@protoc_insertion_point(message_byte_size_start:google.protobuf.SourceContext) + size_t total_size = 0; + + uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + // string file_name = 1; + if (!this->_internal_file_name().empty()) { + total_size += 1 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize( + this->_internal_file_name()); + } + + return MaybeComputeUnknownFieldsSize(total_size, &_impl_._cached_size_); +} + +const ::PROTOBUF_NAMESPACE_ID::Message::ClassData SourceContext::_class_data_ = { + ::PROTOBUF_NAMESPACE_ID::Message::CopyWithSourceCheck, + SourceContext::MergeImpl +}; +const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*SourceContext::GetClassData() const { return &_class_data_; } + + +void SourceContext::MergeImpl(::PROTOBUF_NAMESPACE_ID::Message& to_msg, const ::PROTOBUF_NAMESPACE_ID::Message& from_msg) { + auto* const _this = static_cast<SourceContext*>(&to_msg); + auto& from = static_cast<const SourceContext&>(from_msg); + // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.SourceContext) + GOOGLE_DCHECK_NE(&from, _this); + uint32_t cached_has_bits = 0; + (void) cached_has_bits; + + if (!from._internal_file_name().empty()) { + _this->_internal_set_file_name(from._internal_file_name()); + } + _this->_internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); +} + +void SourceContext::CopyFrom(const SourceContext& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.SourceContext) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool SourceContext::IsInitialized() const { + return true; +} + +void SourceContext::InternalSwap(SourceContext* other) { + using std::swap; + auto* lhs_arena = GetArenaForAllocation(); + auto* rhs_arena = other->GetArenaForAllocation(); + _internal_metadata_.InternalSwap(&other->_internal_metadata_); + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::InternalSwap( + &_impl_.file_name_, lhs_arena, + &other->_impl_.file_name_, rhs_arena + ); +} + +::PROTOBUF_NAMESPACE_ID::Metadata SourceContext::GetMetadata() const { + return ::_pbi::AssignDescriptors( + &descriptor_table_google_2fprotobuf_2fsource_5fcontext_2eproto_getter, &descriptor_table_google_2fprotobuf_2fsource_5fcontext_2eproto_once, + file_level_metadata_google_2fprotobuf_2fsource_5fcontext_2eproto[0]); +} + +// @@protoc_insertion_point(namespace_scope) +PROTOBUF_NAMESPACE_CLOSE +PROTOBUF_NAMESPACE_OPEN +template<> PROTOBUF_NOINLINE ::PROTOBUF_NAMESPACE_ID::SourceContext* +Arena::CreateMaybeMessage< ::PROTOBUF_NAMESPACE_ID::SourceContext >(Arena* arena) { + return Arena::CreateMessageInternal< ::PROTOBUF_NAMESPACE_ID::SourceContext >(arena); +} +PROTOBUF_NAMESPACE_CLOSE + +// @@protoc_insertion_point(global_scope) +#include <google/protobuf/port_undef.inc> diff --git a/toolkit/components/protobuf/src/google/protobuf/source_context.pb.h b/toolkit/components/protobuf/src/google/protobuf/source_context.pb.h new file mode 100644 index 0000000000..e9c41bdea7 --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/source_context.pb.h @@ -0,0 +1,282 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: google/protobuf/source_context.proto + +#ifndef GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2fsource_5fcontext_2eproto +#define GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2fsource_5fcontext_2eproto + +#include <limits> +#include <string> + +#include <google/protobuf/port_def.inc> +#if PROTOBUF_VERSION < 3021000 +#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 3021006 < 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. +#endif + +#include <google/protobuf/port_undef.inc> +#include <google/protobuf/io/coded_stream.h> +#include <google/protobuf/arena.h> +#include <google/protobuf/arenastring.h> +#include <google/protobuf/generated_message_util.h> +#include <google/protobuf/metadata_lite.h> +#include <google/protobuf/generated_message_reflection.h> +#include <google/protobuf/message.h> +#include <google/protobuf/repeated_field.h> // IWYU pragma: export +#include <google/protobuf/extension_set.h> // IWYU pragma: export +#include <google/protobuf/unknown_field_set.h> +// @@protoc_insertion_point(includes) +#include <google/protobuf/port_def.inc> +#define PROTOBUF_INTERNAL_EXPORT_google_2fprotobuf_2fsource_5fcontext_2eproto PROTOBUF_EXPORT +PROTOBUF_NAMESPACE_OPEN +namespace internal { +class AnyMetadata; +} // namespace internal +PROTOBUF_NAMESPACE_CLOSE + +// Internal implementation detail -- do not use these members. +struct PROTOBUF_EXPORT TableStruct_google_2fprotobuf_2fsource_5fcontext_2eproto { + static const uint32_t offsets[]; +}; +PROTOBUF_EXPORT extern const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable descriptor_table_google_2fprotobuf_2fsource_5fcontext_2eproto; +PROTOBUF_NAMESPACE_OPEN +class SourceContext; +struct SourceContextDefaultTypeInternal; +PROTOBUF_EXPORT extern SourceContextDefaultTypeInternal _SourceContext_default_instance_; +PROTOBUF_NAMESPACE_CLOSE +PROTOBUF_NAMESPACE_OPEN +template<> PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::SourceContext* Arena::CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::SourceContext>(Arena*); +PROTOBUF_NAMESPACE_CLOSE +PROTOBUF_NAMESPACE_OPEN + +// =================================================================== + +class PROTOBUF_EXPORT SourceContext final : + public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.SourceContext) */ { + public: + inline SourceContext() : SourceContext(nullptr) {} + ~SourceContext() override; + explicit PROTOBUF_CONSTEXPR SourceContext(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized); + + SourceContext(const SourceContext& from); + SourceContext(SourceContext&& from) noexcept + : SourceContext() { + *this = ::std::move(from); + } + + inline SourceContext& operator=(const SourceContext& from) { + CopyFrom(from); + return *this; + } + inline SourceContext& operator=(SourceContext&& from) noexcept { + if (this == &from) return *this; + if (GetOwningArena() == from.GetOwningArena() + #ifdef PROTOBUF_FORCE_COPY_IN_MOVE + && GetOwningArena() != nullptr + #endif // !PROTOBUF_FORCE_COPY_IN_MOVE + ) { + InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* descriptor() { + return GetDescriptor(); + } + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() { + return default_instance().GetMetadata().descriptor; + } + static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() { + return default_instance().GetMetadata().reflection; + } + static const SourceContext& default_instance() { + return *internal_default_instance(); + } + static inline const SourceContext* internal_default_instance() { + return reinterpret_cast<const SourceContext*>( + &_SourceContext_default_instance_); + } + static constexpr int kIndexInFileMessages = + 0; + + friend void swap(SourceContext& a, SourceContext& b) { + a.Swap(&b); + } + inline void Swap(SourceContext* other) { + if (other == this) return; + #ifdef PROTOBUF_FORCE_COPY_IN_SWAP + if (GetOwningArena() != nullptr && + GetOwningArena() == other->GetOwningArena()) { + #else // PROTOBUF_FORCE_COPY_IN_SWAP + if (GetOwningArena() == other->GetOwningArena()) { + #endif // !PROTOBUF_FORCE_COPY_IN_SWAP + InternalSwap(other); + } else { + ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(SourceContext* other) { + if (other == this) return; + GOOGLE_DCHECK(GetOwningArena() == other->GetOwningArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + SourceContext* New(::PROTOBUF_NAMESPACE_ID::Arena* arena = nullptr) const final { + return CreateMaybeMessage<SourceContext>(arena); + } + using ::PROTOBUF_NAMESPACE_ID::Message::CopyFrom; + void CopyFrom(const SourceContext& from); + using ::PROTOBUF_NAMESPACE_ID::Message::MergeFrom; + void MergeFrom( const SourceContext& from) { + SourceContext::MergeImpl(*this, from); + } + private: + static void MergeImpl(::PROTOBUF_NAMESPACE_ID::Message& to_msg, const ::PROTOBUF_NAMESPACE_ID::Message& from_msg); + public: + PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + bool IsInitialized() const final; + + size_t ByteSizeLong() const final; + const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final; + uint8_t* _InternalSerialize( + uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final; + int GetCachedSize() const final { return _impl_._cached_size_.Get(); } + + private: + void SharedCtor(::PROTOBUF_NAMESPACE_ID::Arena* arena, bool is_message_owned); + void SharedDtor(); + void SetCachedSize(int size) const final; + void InternalSwap(SourceContext* other); + + private: + friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata; + static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() { + return "google.protobuf.SourceContext"; + } + protected: + explicit SourceContext(::PROTOBUF_NAMESPACE_ID::Arena* arena, + bool is_message_owned = false); + public: + + static const ClassData _class_data_; + const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*GetClassData() const final; + + ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final; + + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + + enum : int { + kFileNameFieldNumber = 1, + }; + // string file_name = 1; + void clear_file_name(); + const std::string& file_name() const; + template <typename ArgT0 = const std::string&, typename... ArgT> + void set_file_name(ArgT0&& arg0, ArgT... args); + std::string* mutable_file_name(); + PROTOBUF_NODISCARD std::string* release_file_name(); + void set_allocated_file_name(std::string* file_name); + private: + const std::string& _internal_file_name() const; + inline PROTOBUF_ALWAYS_INLINE void _internal_set_file_name(const std::string& value); + std::string* _internal_mutable_file_name(); + public: + + // @@protoc_insertion_point(class_scope:google.protobuf.SourceContext) + private: + class _Internal; + + template <typename T> friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper; + typedef void InternalArenaConstructable_; + typedef void DestructorSkippable_; + struct Impl_ { + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr file_name_; + mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_; + }; + union { Impl_ _impl_; }; + friend struct ::TableStruct_google_2fprotobuf_2fsource_5fcontext_2eproto; +}; +// =================================================================== + + +// =================================================================== + +#ifdef __GNUC__ + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wstrict-aliasing" +#endif // __GNUC__ +// SourceContext + +// string file_name = 1; +inline void SourceContext::clear_file_name() { + _impl_.file_name_.ClearToEmpty(); +} +inline const std::string& SourceContext::file_name() const { + // @@protoc_insertion_point(field_get:google.protobuf.SourceContext.file_name) + return _internal_file_name(); +} +template <typename ArgT0, typename... ArgT> +inline PROTOBUF_ALWAYS_INLINE +void SourceContext::set_file_name(ArgT0&& arg0, ArgT... args) { + + _impl_.file_name_.Set(static_cast<ArgT0 &&>(arg0), args..., GetArenaForAllocation()); + // @@protoc_insertion_point(field_set:google.protobuf.SourceContext.file_name) +} +inline std::string* SourceContext::mutable_file_name() { + std::string* _s = _internal_mutable_file_name(); + // @@protoc_insertion_point(field_mutable:google.protobuf.SourceContext.file_name) + return _s; +} +inline const std::string& SourceContext::_internal_file_name() const { + return _impl_.file_name_.Get(); +} +inline void SourceContext::_internal_set_file_name(const std::string& value) { + + _impl_.file_name_.Set(value, GetArenaForAllocation()); +} +inline std::string* SourceContext::_internal_mutable_file_name() { + + return _impl_.file_name_.Mutable(GetArenaForAllocation()); +} +inline std::string* SourceContext::release_file_name() { + // @@protoc_insertion_point(field_release:google.protobuf.SourceContext.file_name) + return _impl_.file_name_.Release(); +} +inline void SourceContext::set_allocated_file_name(std::string* file_name) { + if (file_name != nullptr) { + + } else { + + } + _impl_.file_name_.SetAllocated(file_name, GetArenaForAllocation()); +#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (_impl_.file_name_.IsDefault()) { + _impl_.file_name_.Set("", GetArenaForAllocation()); + } +#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + // @@protoc_insertion_point(field_set_allocated:google.protobuf.SourceContext.file_name) +} + +#ifdef __GNUC__ + #pragma GCC diagnostic pop +#endif // __GNUC__ + +// @@protoc_insertion_point(namespace_scope) + +PROTOBUF_NAMESPACE_CLOSE + +// @@protoc_insertion_point(global_scope) + +#include <google/protobuf/port_undef.inc> +#endif // GOOGLE_PROTOBUF_INCLUDED_GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2fsource_5fcontext_2eproto diff --git a/toolkit/components/protobuf/src/google/protobuf/source_context.proto b/toolkit/components/protobuf/src/google/protobuf/source_context.proto new file mode 100644 index 0000000000..06bfc43a78 --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/source_context.proto @@ -0,0 +1,48 @@ +// 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. + +syntax = "proto3"; + +package google.protobuf; + +option csharp_namespace = "Google.Protobuf.WellKnownTypes"; +option java_package = "com.google.protobuf"; +option java_outer_classname = "SourceContextProto"; +option java_multiple_files = true; +option objc_class_prefix = "GPB"; +option go_package = "google.golang.org/protobuf/types/known/sourcecontextpb"; + +// `SourceContext` represents information about the source of a +// protobuf element, like the file in which it is defined. +message SourceContext { + // The path-qualified name of the .proto file that contained the associated + // protobuf element. For example: `"google/protobuf/source_context.proto"`. + string file_name = 1; +} diff --git a/toolkit/components/protobuf/src/google/protobuf/string_member_robber.h b/toolkit/components/protobuf/src/google/protobuf/string_member_robber.h new file mode 100644 index 0000000000..a4c1051e01 --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/string_member_robber.h @@ -0,0 +1,38 @@ +// 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. + +#ifndef GOOGLE_PROTOBUF_STRING_MEMBER_ROBBER_H__ +#define GOOGLE_PROTOBUF_STRING_MEMBER_ROBBER_H__ + +#include <string> +#include <type_traits> + + +#endif // GOOGLE_PROTOBUF_STRING_MEMBER_ROBBER_H__ diff --git a/toolkit/components/protobuf/src/google/protobuf/struct.pb.cc b/toolkit/components/protobuf/src/google/protobuf/struct.pb.cc new file mode 100644 index 0000000000..87c72d4aa4 --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/struct.pb.cc @@ -0,0 +1,1057 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: google/protobuf/struct.proto + +#include <google/protobuf/struct.pb.h> + +#include <algorithm> + +#include <google/protobuf/io/coded_stream.h> +#include <google/protobuf/extension_set.h> +#include <google/protobuf/wire_format_lite.h> +#include <google/protobuf/descriptor.h> +#include <google/protobuf/generated_message_reflection.h> +#include <google/protobuf/reflection_ops.h> +#include <google/protobuf/wire_format.h> +// @@protoc_insertion_point(includes) +#include <google/protobuf/port_def.inc> + +PROTOBUF_PRAGMA_INIT_SEG + +namespace _pb = ::PROTOBUF_NAMESPACE_ID; +namespace _pbi = _pb::internal; + +PROTOBUF_NAMESPACE_OPEN +PROTOBUF_CONSTEXPR Struct_FieldsEntry_DoNotUse::Struct_FieldsEntry_DoNotUse( + ::_pbi::ConstantInitialized) {} +struct Struct_FieldsEntry_DoNotUseDefaultTypeInternal { + PROTOBUF_CONSTEXPR Struct_FieldsEntry_DoNotUseDefaultTypeInternal() + : _instance(::_pbi::ConstantInitialized{}) {} + ~Struct_FieldsEntry_DoNotUseDefaultTypeInternal() {} + union { + Struct_FieldsEntry_DoNotUse _instance; + }; +}; +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 Struct_FieldsEntry_DoNotUseDefaultTypeInternal _Struct_FieldsEntry_DoNotUse_default_instance_; +PROTOBUF_CONSTEXPR Struct::Struct( + ::_pbi::ConstantInitialized): _impl_{ + /*decltype(_impl_.fields_)*/{::_pbi::ConstantInitialized()} + , /*decltype(_impl_._cached_size_)*/{}} {} +struct StructDefaultTypeInternal { + PROTOBUF_CONSTEXPR StructDefaultTypeInternal() + : _instance(::_pbi::ConstantInitialized{}) {} + ~StructDefaultTypeInternal() {} + union { + Struct _instance; + }; +}; +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 StructDefaultTypeInternal _Struct_default_instance_; +PROTOBUF_CONSTEXPR Value::Value( + ::_pbi::ConstantInitialized): _impl_{ + /*decltype(_impl_.kind_)*/{} + , /*decltype(_impl_._cached_size_)*/{} + , /*decltype(_impl_._oneof_case_)*/{}} {} +struct ValueDefaultTypeInternal { + PROTOBUF_CONSTEXPR ValueDefaultTypeInternal() + : _instance(::_pbi::ConstantInitialized{}) {} + ~ValueDefaultTypeInternal() {} + union { + Value _instance; + }; +}; +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 ValueDefaultTypeInternal _Value_default_instance_; +PROTOBUF_CONSTEXPR ListValue::ListValue( + ::_pbi::ConstantInitialized): _impl_{ + /*decltype(_impl_.values_)*/{} + , /*decltype(_impl_._cached_size_)*/{}} {} +struct ListValueDefaultTypeInternal { + PROTOBUF_CONSTEXPR ListValueDefaultTypeInternal() + : _instance(::_pbi::ConstantInitialized{}) {} + ~ListValueDefaultTypeInternal() {} + union { + ListValue _instance; + }; +}; +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 ListValueDefaultTypeInternal _ListValue_default_instance_; +PROTOBUF_NAMESPACE_CLOSE +static ::_pb::Metadata file_level_metadata_google_2fprotobuf_2fstruct_2eproto[4]; +static const ::_pb::EnumDescriptor* file_level_enum_descriptors_google_2fprotobuf_2fstruct_2eproto[1]; +static constexpr ::_pb::ServiceDescriptor const** file_level_service_descriptors_google_2fprotobuf_2fstruct_2eproto = nullptr; + +const uint32_t TableStruct_google_2fprotobuf_2fstruct_2eproto::offsets[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = { + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Struct_FieldsEntry_DoNotUse, _has_bits_), + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Struct_FieldsEntry_DoNotUse, _internal_metadata_), + ~0u, // no _extensions_ + ~0u, // no _oneof_case_ + ~0u, // no _weak_field_map_ + ~0u, // no _inlined_string_donated_ + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Struct_FieldsEntry_DoNotUse, key_), + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Struct_FieldsEntry_DoNotUse, value_), + 0, + 1, + ~0u, // no _has_bits_ + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Struct, _internal_metadata_), + ~0u, // no _extensions_ + ~0u, // no _oneof_case_ + ~0u, // no _weak_field_map_ + ~0u, // no _inlined_string_donated_ + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Struct, _impl_.fields_), + ~0u, // no _has_bits_ + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Value, _internal_metadata_), + ~0u, // no _extensions_ + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Value, _impl_._oneof_case_[0]), + ~0u, // no _weak_field_map_ + ~0u, // no _inlined_string_donated_ + ::_pbi::kInvalidFieldOffsetTag, + ::_pbi::kInvalidFieldOffsetTag, + ::_pbi::kInvalidFieldOffsetTag, + ::_pbi::kInvalidFieldOffsetTag, + ::_pbi::kInvalidFieldOffsetTag, + ::_pbi::kInvalidFieldOffsetTag, + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Value, _impl_.kind_), + ~0u, // no _has_bits_ + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::ListValue, _internal_metadata_), + ~0u, // no _extensions_ + ~0u, // no _oneof_case_ + ~0u, // no _weak_field_map_ + ~0u, // no _inlined_string_donated_ + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::ListValue, _impl_.values_), +}; +static const ::_pbi::MigrationSchema schemas[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = { + { 0, 8, -1, sizeof(::PROTOBUF_NAMESPACE_ID::Struct_FieldsEntry_DoNotUse)}, + { 10, -1, -1, sizeof(::PROTOBUF_NAMESPACE_ID::Struct)}, + { 17, -1, -1, sizeof(::PROTOBUF_NAMESPACE_ID::Value)}, + { 30, -1, -1, sizeof(::PROTOBUF_NAMESPACE_ID::ListValue)}, +}; + +static const ::_pb::Message* const file_default_instances[] = { + &::PROTOBUF_NAMESPACE_ID::_Struct_FieldsEntry_DoNotUse_default_instance_._instance, + &::PROTOBUF_NAMESPACE_ID::_Struct_default_instance_._instance, + &::PROTOBUF_NAMESPACE_ID::_Value_default_instance_._instance, + &::PROTOBUF_NAMESPACE_ID::_ListValue_default_instance_._instance, +}; + +const char descriptor_table_protodef_google_2fprotobuf_2fstruct_2eproto[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = + "\n\034google/protobuf/struct.proto\022\017google.p" + "rotobuf\"\204\001\n\006Struct\0223\n\006fields\030\001 \003(\0132#.goo" + "gle.protobuf.Struct.FieldsEntry\032E\n\013Field" + "sEntry\022\013\n\003key\030\001 \001(\t\022%\n\005value\030\002 \001(\0132\026.goo" + "gle.protobuf.Value:\0028\001\"\352\001\n\005Value\0220\n\nnull" + "_value\030\001 \001(\0162\032.google.protobuf.NullValue" + "H\000\022\026\n\014number_value\030\002 \001(\001H\000\022\026\n\014string_val" + "ue\030\003 \001(\tH\000\022\024\n\nbool_value\030\004 \001(\010H\000\022/\n\014stru" + "ct_value\030\005 \001(\0132\027.google.protobuf.StructH" + "\000\0220\n\nlist_value\030\006 \001(\0132\032.google.protobuf." + "ListValueH\000B\006\n\004kind\"3\n\tListValue\022&\n\006valu" + "es\030\001 \003(\0132\026.google.protobuf.Value*\033\n\tNull" + "Value\022\016\n\nNULL_VALUE\020\000B\177\n\023com.google.prot" + "obufB\013StructProtoP\001Z/google.golang.org/p" + "rotobuf/types/known/structpb\370\001\001\242\002\003GPB\252\002\036" + "Google.Protobuf.WellKnownTypesb\006proto3" + ; +static ::_pbi::once_flag descriptor_table_google_2fprotobuf_2fstruct_2eproto_once; +const ::_pbi::DescriptorTable descriptor_table_google_2fprotobuf_2fstruct_2eproto = { + false, false, 638, descriptor_table_protodef_google_2fprotobuf_2fstruct_2eproto, + "google/protobuf/struct.proto", + &descriptor_table_google_2fprotobuf_2fstruct_2eproto_once, nullptr, 0, 4, + schemas, file_default_instances, TableStruct_google_2fprotobuf_2fstruct_2eproto::offsets, + file_level_metadata_google_2fprotobuf_2fstruct_2eproto, file_level_enum_descriptors_google_2fprotobuf_2fstruct_2eproto, + file_level_service_descriptors_google_2fprotobuf_2fstruct_2eproto, +}; +PROTOBUF_ATTRIBUTE_WEAK const ::_pbi::DescriptorTable* descriptor_table_google_2fprotobuf_2fstruct_2eproto_getter() { + return &descriptor_table_google_2fprotobuf_2fstruct_2eproto; +} + +// Force running AddDescriptors() at dynamic initialization time. +PROTOBUF_ATTRIBUTE_INIT_PRIORITY2 static ::_pbi::AddDescriptorsRunner dynamic_init_dummy_google_2fprotobuf_2fstruct_2eproto(&descriptor_table_google_2fprotobuf_2fstruct_2eproto); +PROTOBUF_NAMESPACE_OPEN +const ::PROTOBUF_NAMESPACE_ID::EnumDescriptor* NullValue_descriptor() { + ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&descriptor_table_google_2fprotobuf_2fstruct_2eproto); + return file_level_enum_descriptors_google_2fprotobuf_2fstruct_2eproto[0]; +} +bool NullValue_IsValid(int value) { + switch (value) { + case 0: + return true; + default: + return false; + } +} + + +// =================================================================== + +Struct_FieldsEntry_DoNotUse::Struct_FieldsEntry_DoNotUse() {} +Struct_FieldsEntry_DoNotUse::Struct_FieldsEntry_DoNotUse(::PROTOBUF_NAMESPACE_ID::Arena* arena) + : SuperType(arena) {} +void Struct_FieldsEntry_DoNotUse::MergeFrom(const Struct_FieldsEntry_DoNotUse& other) { + MergeFromInternal(other); +} +::PROTOBUF_NAMESPACE_ID::Metadata Struct_FieldsEntry_DoNotUse::GetMetadata() const { + return ::_pbi::AssignDescriptors( + &descriptor_table_google_2fprotobuf_2fstruct_2eproto_getter, &descriptor_table_google_2fprotobuf_2fstruct_2eproto_once, + file_level_metadata_google_2fprotobuf_2fstruct_2eproto[0]); +} + +// =================================================================== + +class Struct::_Internal { + public: +}; + +Struct::Struct(::PROTOBUF_NAMESPACE_ID::Arena* arena, + bool is_message_owned) + : ::PROTOBUF_NAMESPACE_ID::Message(arena, is_message_owned) { + SharedCtor(arena, is_message_owned); + if (arena != nullptr && !is_message_owned) { + arena->OwnCustomDestructor(this, &Struct::ArenaDtor); + } + // @@protoc_insertion_point(arena_constructor:google.protobuf.Struct) +} +Struct::Struct(const Struct& from) + : ::PROTOBUF_NAMESPACE_ID::Message() { + Struct* const _this = this; (void)_this; + new (&_impl_) Impl_{ + /*decltype(_impl_.fields_)*/{} + , /*decltype(_impl_._cached_size_)*/{}}; + + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); + _this->_impl_.fields_.MergeFrom(from._impl_.fields_); + // @@protoc_insertion_point(copy_constructor:google.protobuf.Struct) +} + +inline void Struct::SharedCtor( + ::_pb::Arena* arena, bool is_message_owned) { + (void)arena; + (void)is_message_owned; + new (&_impl_) Impl_{ + /*decltype(_impl_.fields_)*/{::_pbi::ArenaInitialized(), arena} + , /*decltype(_impl_._cached_size_)*/{} + }; +} + +Struct::~Struct() { + // @@protoc_insertion_point(destructor:google.protobuf.Struct) + if (auto *arena = _internal_metadata_.DeleteReturnArena<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>()) { + (void)arena; + ArenaDtor(this); + return; + } + SharedDtor(); +} + +inline void Struct::SharedDtor() { + GOOGLE_DCHECK(GetArenaForAllocation() == nullptr); + _impl_.fields_.Destruct(); + _impl_.fields_.~MapField(); +} + +void Struct::ArenaDtor(void* object) { + Struct* _this = reinterpret_cast< Struct* >(object); + _this->_impl_.fields_.Destruct(); +} +void Struct::SetCachedSize(int size) const { + _impl_._cached_size_.Set(size); +} + +void Struct::Clear() { +// @@protoc_insertion_point(message_clear_start:google.protobuf.Struct) + uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + _impl_.fields_.Clear(); + _internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); +} + +const char* Struct::_InternalParse(const char* ptr, ::_pbi::ParseContext* ctx) { +#define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure + while (!ctx->Done(&ptr)) { + uint32_t tag; + ptr = ::_pbi::ReadTag(ptr, &tag); + switch (tag >> 3) { + // map<string, .google.protobuf.Value> fields = 1; + case 1: + if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 10)) { + ptr -= 1; + do { + ptr += 1; + ptr = ctx->ParseMessage(&_impl_.fields_, ptr); + CHK_(ptr); + if (!ctx->DataAvailable(ptr)) break; + } while (::PROTOBUF_NAMESPACE_ID::internal::ExpectTag<10>(ptr)); + } else + goto handle_unusual; + continue; + default: + goto handle_unusual; + } // switch + handle_unusual: + if ((tag == 0) || ((tag & 7) == 4)) { + CHK_(ptr); + ctx->SetLastTag(tag); + goto message_done; + } + ptr = UnknownFieldParse( + tag, + _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(), + ptr, ctx); + CHK_(ptr != nullptr); + } // while +message_done: + return ptr; +failure: + ptr = nullptr; + goto message_done; +#undef CHK_ +} + +uint8_t* Struct::_InternalSerialize( + uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const { + // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.Struct) + uint32_t cached_has_bits = 0; + (void) cached_has_bits; + + // map<string, .google.protobuf.Value> fields = 1; + if (!this->_internal_fields().empty()) { + using MapType = ::_pb::Map<std::string, ::PROTOBUF_NAMESPACE_ID::Value>; + using WireHelper = Struct_FieldsEntry_DoNotUse::Funcs; + const auto& map_field = this->_internal_fields(); + auto check_utf8 = [](const MapType::value_type& entry) { + (void)entry; + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::VerifyUtf8String( + entry.first.data(), static_cast<int>(entry.first.length()), + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::SERIALIZE, + "google.protobuf.Struct.FieldsEntry.key"); + }; + + if (stream->IsSerializationDeterministic() && map_field.size() > 1) { + for (const auto& entry : ::_pbi::MapSorterPtr<MapType>(map_field)) { + target = WireHelper::InternalSerialize(1, entry.first, entry.second, target, stream); + check_utf8(entry); + } + } else { + for (const auto& entry : map_field) { + target = WireHelper::InternalSerialize(1, entry.first, entry.second, target, stream); + check_utf8(entry); + } + } + } + + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + target = ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( + _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.Struct) + return target; +} + +size_t Struct::ByteSizeLong() const { +// @@protoc_insertion_point(message_byte_size_start:google.protobuf.Struct) + size_t total_size = 0; + + uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + // map<string, .google.protobuf.Value> fields = 1; + total_size += 1 * + ::PROTOBUF_NAMESPACE_ID::internal::FromIntSize(this->_internal_fields_size()); + for (::PROTOBUF_NAMESPACE_ID::Map< std::string, ::PROTOBUF_NAMESPACE_ID::Value >::const_iterator + it = this->_internal_fields().begin(); + it != this->_internal_fields().end(); ++it) { + total_size += Struct_FieldsEntry_DoNotUse::Funcs::ByteSizeLong(it->first, it->second); + } + + return MaybeComputeUnknownFieldsSize(total_size, &_impl_._cached_size_); +} + +const ::PROTOBUF_NAMESPACE_ID::Message::ClassData Struct::_class_data_ = { + ::PROTOBUF_NAMESPACE_ID::Message::CopyWithSourceCheck, + Struct::MergeImpl +}; +const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*Struct::GetClassData() const { return &_class_data_; } + + +void Struct::MergeImpl(::PROTOBUF_NAMESPACE_ID::Message& to_msg, const ::PROTOBUF_NAMESPACE_ID::Message& from_msg) { + auto* const _this = static_cast<Struct*>(&to_msg); + auto& from = static_cast<const Struct&>(from_msg); + // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.Struct) + GOOGLE_DCHECK_NE(&from, _this); + uint32_t cached_has_bits = 0; + (void) cached_has_bits; + + _this->_impl_.fields_.MergeFrom(from._impl_.fields_); + _this->_internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); +} + +void Struct::CopyFrom(const Struct& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.Struct) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool Struct::IsInitialized() const { + return true; +} + +void Struct::InternalSwap(Struct* other) { + using std::swap; + _internal_metadata_.InternalSwap(&other->_internal_metadata_); + _impl_.fields_.InternalSwap(&other->_impl_.fields_); +} + +::PROTOBUF_NAMESPACE_ID::Metadata Struct::GetMetadata() const { + return ::_pbi::AssignDescriptors( + &descriptor_table_google_2fprotobuf_2fstruct_2eproto_getter, &descriptor_table_google_2fprotobuf_2fstruct_2eproto_once, + file_level_metadata_google_2fprotobuf_2fstruct_2eproto[1]); +} + +// =================================================================== + +class Value::_Internal { + public: + static const ::PROTOBUF_NAMESPACE_ID::Struct& struct_value(const Value* msg); + static const ::PROTOBUF_NAMESPACE_ID::ListValue& list_value(const Value* msg); +}; + +const ::PROTOBUF_NAMESPACE_ID::Struct& +Value::_Internal::struct_value(const Value* msg) { + return *msg->_impl_.kind_.struct_value_; +} +const ::PROTOBUF_NAMESPACE_ID::ListValue& +Value::_Internal::list_value(const Value* msg) { + return *msg->_impl_.kind_.list_value_; +} +void Value::set_allocated_struct_value(::PROTOBUF_NAMESPACE_ID::Struct* struct_value) { + ::PROTOBUF_NAMESPACE_ID::Arena* message_arena = GetArenaForAllocation(); + clear_kind(); + if (struct_value) { + ::PROTOBUF_NAMESPACE_ID::Arena* submessage_arena = + ::PROTOBUF_NAMESPACE_ID::Arena::InternalGetOwningArena(struct_value); + if (message_arena != submessage_arena) { + struct_value = ::PROTOBUF_NAMESPACE_ID::internal::GetOwnedMessage( + message_arena, struct_value, submessage_arena); + } + set_has_struct_value(); + _impl_.kind_.struct_value_ = struct_value; + } + // @@protoc_insertion_point(field_set_allocated:google.protobuf.Value.struct_value) +} +void Value::set_allocated_list_value(::PROTOBUF_NAMESPACE_ID::ListValue* list_value) { + ::PROTOBUF_NAMESPACE_ID::Arena* message_arena = GetArenaForAllocation(); + clear_kind(); + if (list_value) { + ::PROTOBUF_NAMESPACE_ID::Arena* submessage_arena = + ::PROTOBUF_NAMESPACE_ID::Arena::InternalGetOwningArena(list_value); + if (message_arena != submessage_arena) { + list_value = ::PROTOBUF_NAMESPACE_ID::internal::GetOwnedMessage( + message_arena, list_value, submessage_arena); + } + set_has_list_value(); + _impl_.kind_.list_value_ = list_value; + } + // @@protoc_insertion_point(field_set_allocated:google.protobuf.Value.list_value) +} +Value::Value(::PROTOBUF_NAMESPACE_ID::Arena* arena, + bool is_message_owned) + : ::PROTOBUF_NAMESPACE_ID::Message(arena, is_message_owned) { + SharedCtor(arena, is_message_owned); + // @@protoc_insertion_point(arena_constructor:google.protobuf.Value) +} +Value::Value(const Value& from) + : ::PROTOBUF_NAMESPACE_ID::Message() { + Value* const _this = this; (void)_this; + new (&_impl_) Impl_{ + decltype(_impl_.kind_){} + , /*decltype(_impl_._cached_size_)*/{} + , /*decltype(_impl_._oneof_case_)*/{}}; + + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); + clear_has_kind(); + switch (from.kind_case()) { + case kNullValue: { + _this->_internal_set_null_value(from._internal_null_value()); + break; + } + case kNumberValue: { + _this->_internal_set_number_value(from._internal_number_value()); + break; + } + case kStringValue: { + _this->_internal_set_string_value(from._internal_string_value()); + break; + } + case kBoolValue: { + _this->_internal_set_bool_value(from._internal_bool_value()); + break; + } + case kStructValue: { + _this->_internal_mutable_struct_value()->::PROTOBUF_NAMESPACE_ID::Struct::MergeFrom( + from._internal_struct_value()); + break; + } + case kListValue: { + _this->_internal_mutable_list_value()->::PROTOBUF_NAMESPACE_ID::ListValue::MergeFrom( + from._internal_list_value()); + break; + } + case KIND_NOT_SET: { + break; + } + } + // @@protoc_insertion_point(copy_constructor:google.protobuf.Value) +} + +inline void Value::SharedCtor( + ::_pb::Arena* arena, bool is_message_owned) { + (void)arena; + (void)is_message_owned; + new (&_impl_) Impl_{ + decltype(_impl_.kind_){} + , /*decltype(_impl_._cached_size_)*/{} + , /*decltype(_impl_._oneof_case_)*/{} + }; + clear_has_kind(); +} + +Value::~Value() { + // @@protoc_insertion_point(destructor:google.protobuf.Value) + if (auto *arena = _internal_metadata_.DeleteReturnArena<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>()) { + (void)arena; + return; + } + SharedDtor(); +} + +inline void Value::SharedDtor() { + GOOGLE_DCHECK(GetArenaForAllocation() == nullptr); + if (has_kind()) { + clear_kind(); + } +} + +void Value::SetCachedSize(int size) const { + _impl_._cached_size_.Set(size); +} + +void Value::clear_kind() { +// @@protoc_insertion_point(one_of_clear_start:google.protobuf.Value) + switch (kind_case()) { + case kNullValue: { + // No need to clear + break; + } + case kNumberValue: { + // No need to clear + break; + } + case kStringValue: { + _impl_.kind_.string_value_.Destroy(); + break; + } + case kBoolValue: { + // No need to clear + break; + } + case kStructValue: { + if (GetArenaForAllocation() == nullptr) { + delete _impl_.kind_.struct_value_; + } + break; + } + case kListValue: { + if (GetArenaForAllocation() == nullptr) { + delete _impl_.kind_.list_value_; + } + break; + } + case KIND_NOT_SET: { + break; + } + } + _impl_._oneof_case_[0] = KIND_NOT_SET; +} + + +void Value::Clear() { +// @@protoc_insertion_point(message_clear_start:google.protobuf.Value) + uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + clear_kind(); + _internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); +} + +const char* Value::_InternalParse(const char* ptr, ::_pbi::ParseContext* ctx) { +#define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure + while (!ctx->Done(&ptr)) { + uint32_t tag; + ptr = ::_pbi::ReadTag(ptr, &tag); + switch (tag >> 3) { + // .google.protobuf.NullValue null_value = 1; + case 1: + if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 8)) { + uint64_t val = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr); + CHK_(ptr); + _internal_set_null_value(static_cast<::PROTOBUF_NAMESPACE_ID::NullValue>(val)); + } else + goto handle_unusual; + continue; + // double number_value = 2; + case 2: + if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 17)) { + _internal_set_number_value(::PROTOBUF_NAMESPACE_ID::internal::UnalignedLoad<double>(ptr)); + ptr += sizeof(double); + } else + goto handle_unusual; + continue; + // string string_value = 3; + case 3: + if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 26)) { + auto str = _internal_mutable_string_value(); + ptr = ::_pbi::InlineGreedyStringParser(str, ptr, ctx); + CHK_(ptr); + CHK_(::_pbi::VerifyUTF8(str, "google.protobuf.Value.string_value")); + } else + goto handle_unusual; + continue; + // bool bool_value = 4; + case 4: + if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 32)) { + _internal_set_bool_value(::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr)); + CHK_(ptr); + } else + goto handle_unusual; + continue; + // .google.protobuf.Struct struct_value = 5; + case 5: + if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 42)) { + ptr = ctx->ParseMessage(_internal_mutable_struct_value(), ptr); + CHK_(ptr); + } else + goto handle_unusual; + continue; + // .google.protobuf.ListValue list_value = 6; + case 6: + if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 50)) { + ptr = ctx->ParseMessage(_internal_mutable_list_value(), ptr); + CHK_(ptr); + } else + goto handle_unusual; + continue; + default: + goto handle_unusual; + } // switch + handle_unusual: + if ((tag == 0) || ((tag & 7) == 4)) { + CHK_(ptr); + ctx->SetLastTag(tag); + goto message_done; + } + ptr = UnknownFieldParse( + tag, + _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(), + ptr, ctx); + CHK_(ptr != nullptr); + } // while +message_done: + return ptr; +failure: + ptr = nullptr; + goto message_done; +#undef CHK_ +} + +uint8_t* Value::_InternalSerialize( + uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const { + // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.Value) + uint32_t cached_has_bits = 0; + (void) cached_has_bits; + + // .google.protobuf.NullValue null_value = 1; + if (_internal_has_null_value()) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteEnumToArray( + 1, this->_internal_null_value(), target); + } + + // double number_value = 2; + if (_internal_has_number_value()) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteDoubleToArray(2, this->_internal_number_value(), target); + } + + // string string_value = 3; + if (_internal_has_string_value()) { + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::VerifyUtf8String( + this->_internal_string_value().data(), static_cast<int>(this->_internal_string_value().length()), + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::SERIALIZE, + "google.protobuf.Value.string_value"); + target = stream->WriteStringMaybeAliased( + 3, this->_internal_string_value(), target); + } + + // bool bool_value = 4; + if (_internal_has_bool_value()) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteBoolToArray(4, this->_internal_bool_value(), target); + } + + // .google.protobuf.Struct struct_value = 5; + if (_internal_has_struct_value()) { + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite:: + InternalWriteMessage(5, _Internal::struct_value(this), + _Internal::struct_value(this).GetCachedSize(), target, stream); + } + + // .google.protobuf.ListValue list_value = 6; + if (_internal_has_list_value()) { + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite:: + InternalWriteMessage(6, _Internal::list_value(this), + _Internal::list_value(this).GetCachedSize(), target, stream); + } + + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + target = ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( + _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.Value) + return target; +} + +size_t Value::ByteSizeLong() const { +// @@protoc_insertion_point(message_byte_size_start:google.protobuf.Value) + size_t total_size = 0; + + uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + switch (kind_case()) { + // .google.protobuf.NullValue null_value = 1; + case kNullValue: { + total_size += 1 + + ::_pbi::WireFormatLite::EnumSize(this->_internal_null_value()); + break; + } + // double number_value = 2; + case kNumberValue: { + total_size += 1 + 8; + break; + } + // string string_value = 3; + case kStringValue: { + total_size += 1 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize( + this->_internal_string_value()); + break; + } + // bool bool_value = 4; + case kBoolValue: { + total_size += 1 + 1; + break; + } + // .google.protobuf.Struct struct_value = 5; + case kStructValue: { + total_size += 1 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::MessageSize( + *_impl_.kind_.struct_value_); + break; + } + // .google.protobuf.ListValue list_value = 6; + case kListValue: { + total_size += 1 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::MessageSize( + *_impl_.kind_.list_value_); + break; + } + case KIND_NOT_SET: { + break; + } + } + return MaybeComputeUnknownFieldsSize(total_size, &_impl_._cached_size_); +} + +const ::PROTOBUF_NAMESPACE_ID::Message::ClassData Value::_class_data_ = { + ::PROTOBUF_NAMESPACE_ID::Message::CopyWithSourceCheck, + Value::MergeImpl +}; +const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*Value::GetClassData() const { return &_class_data_; } + + +void Value::MergeImpl(::PROTOBUF_NAMESPACE_ID::Message& to_msg, const ::PROTOBUF_NAMESPACE_ID::Message& from_msg) { + auto* const _this = static_cast<Value*>(&to_msg); + auto& from = static_cast<const Value&>(from_msg); + // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.Value) + GOOGLE_DCHECK_NE(&from, _this); + uint32_t cached_has_bits = 0; + (void) cached_has_bits; + + switch (from.kind_case()) { + case kNullValue: { + _this->_internal_set_null_value(from._internal_null_value()); + break; + } + case kNumberValue: { + _this->_internal_set_number_value(from._internal_number_value()); + break; + } + case kStringValue: { + _this->_internal_set_string_value(from._internal_string_value()); + break; + } + case kBoolValue: { + _this->_internal_set_bool_value(from._internal_bool_value()); + break; + } + case kStructValue: { + _this->_internal_mutable_struct_value()->::PROTOBUF_NAMESPACE_ID::Struct::MergeFrom( + from._internal_struct_value()); + break; + } + case kListValue: { + _this->_internal_mutable_list_value()->::PROTOBUF_NAMESPACE_ID::ListValue::MergeFrom( + from._internal_list_value()); + break; + } + case KIND_NOT_SET: { + break; + } + } + _this->_internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); +} + +void Value::CopyFrom(const Value& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.Value) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool Value::IsInitialized() const { + return true; +} + +void Value::InternalSwap(Value* other) { + using std::swap; + _internal_metadata_.InternalSwap(&other->_internal_metadata_); + swap(_impl_.kind_, other->_impl_.kind_); + swap(_impl_._oneof_case_[0], other->_impl_._oneof_case_[0]); +} + +::PROTOBUF_NAMESPACE_ID::Metadata Value::GetMetadata() const { + return ::_pbi::AssignDescriptors( + &descriptor_table_google_2fprotobuf_2fstruct_2eproto_getter, &descriptor_table_google_2fprotobuf_2fstruct_2eproto_once, + file_level_metadata_google_2fprotobuf_2fstruct_2eproto[2]); +} + +// =================================================================== + +class ListValue::_Internal { + public: +}; + +ListValue::ListValue(::PROTOBUF_NAMESPACE_ID::Arena* arena, + bool is_message_owned) + : ::PROTOBUF_NAMESPACE_ID::Message(arena, is_message_owned) { + SharedCtor(arena, is_message_owned); + // @@protoc_insertion_point(arena_constructor:google.protobuf.ListValue) +} +ListValue::ListValue(const ListValue& from) + : ::PROTOBUF_NAMESPACE_ID::Message() { + ListValue* const _this = this; (void)_this; + new (&_impl_) Impl_{ + decltype(_impl_.values_){from._impl_.values_} + , /*decltype(_impl_._cached_size_)*/{}}; + + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); + // @@protoc_insertion_point(copy_constructor:google.protobuf.ListValue) +} + +inline void ListValue::SharedCtor( + ::_pb::Arena* arena, bool is_message_owned) { + (void)arena; + (void)is_message_owned; + new (&_impl_) Impl_{ + decltype(_impl_.values_){arena} + , /*decltype(_impl_._cached_size_)*/{} + }; +} + +ListValue::~ListValue() { + // @@protoc_insertion_point(destructor:google.protobuf.ListValue) + if (auto *arena = _internal_metadata_.DeleteReturnArena<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>()) { + (void)arena; + return; + } + SharedDtor(); +} + +inline void ListValue::SharedDtor() { + GOOGLE_DCHECK(GetArenaForAllocation() == nullptr); + _impl_.values_.~RepeatedPtrField(); +} + +void ListValue::SetCachedSize(int size) const { + _impl_._cached_size_.Set(size); +} + +void ListValue::Clear() { +// @@protoc_insertion_point(message_clear_start:google.protobuf.ListValue) + uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + _impl_.values_.Clear(); + _internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); +} + +const char* ListValue::_InternalParse(const char* ptr, ::_pbi::ParseContext* ctx) { +#define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure + while (!ctx->Done(&ptr)) { + uint32_t tag; + ptr = ::_pbi::ReadTag(ptr, &tag); + switch (tag >> 3) { + // repeated .google.protobuf.Value values = 1; + case 1: + if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 10)) { + ptr -= 1; + do { + ptr += 1; + ptr = ctx->ParseMessage(_internal_add_values(), ptr); + CHK_(ptr); + if (!ctx->DataAvailable(ptr)) break; + } while (::PROTOBUF_NAMESPACE_ID::internal::ExpectTag<10>(ptr)); + } else + goto handle_unusual; + continue; + default: + goto handle_unusual; + } // switch + handle_unusual: + if ((tag == 0) || ((tag & 7) == 4)) { + CHK_(ptr); + ctx->SetLastTag(tag); + goto message_done; + } + ptr = UnknownFieldParse( + tag, + _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(), + ptr, ctx); + CHK_(ptr != nullptr); + } // while +message_done: + return ptr; +failure: + ptr = nullptr; + goto message_done; +#undef CHK_ +} + +uint8_t* ListValue::_InternalSerialize( + uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const { + // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.ListValue) + uint32_t cached_has_bits = 0; + (void) cached_has_bits; + + // repeated .google.protobuf.Value values = 1; + for (unsigned i = 0, + n = static_cast<unsigned>(this->_internal_values_size()); i < n; i++) { + const auto& repfield = this->_internal_values(i); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite:: + InternalWriteMessage(1, repfield, repfield.GetCachedSize(), target, stream); + } + + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + target = ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( + _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.ListValue) + return target; +} + +size_t ListValue::ByteSizeLong() const { +// @@protoc_insertion_point(message_byte_size_start:google.protobuf.ListValue) + size_t total_size = 0; + + uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + // repeated .google.protobuf.Value values = 1; + total_size += 1UL * this->_internal_values_size(); + for (const auto& msg : this->_impl_.values_) { + total_size += + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::MessageSize(msg); + } + + return MaybeComputeUnknownFieldsSize(total_size, &_impl_._cached_size_); +} + +const ::PROTOBUF_NAMESPACE_ID::Message::ClassData ListValue::_class_data_ = { + ::PROTOBUF_NAMESPACE_ID::Message::CopyWithSourceCheck, + ListValue::MergeImpl +}; +const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*ListValue::GetClassData() const { return &_class_data_; } + + +void ListValue::MergeImpl(::PROTOBUF_NAMESPACE_ID::Message& to_msg, const ::PROTOBUF_NAMESPACE_ID::Message& from_msg) { + auto* const _this = static_cast<ListValue*>(&to_msg); + auto& from = static_cast<const ListValue&>(from_msg); + // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.ListValue) + GOOGLE_DCHECK_NE(&from, _this); + uint32_t cached_has_bits = 0; + (void) cached_has_bits; + + _this->_impl_.values_.MergeFrom(from._impl_.values_); + _this->_internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); +} + +void ListValue::CopyFrom(const ListValue& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.ListValue) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool ListValue::IsInitialized() const { + return true; +} + +void ListValue::InternalSwap(ListValue* other) { + using std::swap; + _internal_metadata_.InternalSwap(&other->_internal_metadata_); + _impl_.values_.InternalSwap(&other->_impl_.values_); +} + +::PROTOBUF_NAMESPACE_ID::Metadata ListValue::GetMetadata() const { + return ::_pbi::AssignDescriptors( + &descriptor_table_google_2fprotobuf_2fstruct_2eproto_getter, &descriptor_table_google_2fprotobuf_2fstruct_2eproto_once, + file_level_metadata_google_2fprotobuf_2fstruct_2eproto[3]); +} + +// @@protoc_insertion_point(namespace_scope) +PROTOBUF_NAMESPACE_CLOSE +PROTOBUF_NAMESPACE_OPEN +template<> PROTOBUF_NOINLINE ::PROTOBUF_NAMESPACE_ID::Struct_FieldsEntry_DoNotUse* +Arena::CreateMaybeMessage< ::PROTOBUF_NAMESPACE_ID::Struct_FieldsEntry_DoNotUse >(Arena* arena) { + return Arena::CreateMessageInternal< ::PROTOBUF_NAMESPACE_ID::Struct_FieldsEntry_DoNotUse >(arena); +} +template<> PROTOBUF_NOINLINE ::PROTOBUF_NAMESPACE_ID::Struct* +Arena::CreateMaybeMessage< ::PROTOBUF_NAMESPACE_ID::Struct >(Arena* arena) { + return Arena::CreateMessageInternal< ::PROTOBUF_NAMESPACE_ID::Struct >(arena); +} +template<> PROTOBUF_NOINLINE ::PROTOBUF_NAMESPACE_ID::Value* +Arena::CreateMaybeMessage< ::PROTOBUF_NAMESPACE_ID::Value >(Arena* arena) { + return Arena::CreateMessageInternal< ::PROTOBUF_NAMESPACE_ID::Value >(arena); +} +template<> PROTOBUF_NOINLINE ::PROTOBUF_NAMESPACE_ID::ListValue* +Arena::CreateMaybeMessage< ::PROTOBUF_NAMESPACE_ID::ListValue >(Arena* arena) { + return Arena::CreateMessageInternal< ::PROTOBUF_NAMESPACE_ID::ListValue >(arena); +} +PROTOBUF_NAMESPACE_CLOSE + +// @@protoc_insertion_point(global_scope) +#include <google/protobuf/port_undef.inc> diff --git a/toolkit/components/protobuf/src/google/protobuf/struct.pb.h b/toolkit/components/protobuf/src/google/protobuf/struct.pb.h new file mode 100644 index 0000000000..ac2d9716dd --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/struct.pb.h @@ -0,0 +1,1177 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: google/protobuf/struct.proto + +#ifndef GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2fstruct_2eproto +#define GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2fstruct_2eproto + +#include <limits> +#include <string> + +#include <google/protobuf/port_def.inc> +#if PROTOBUF_VERSION < 3021000 +#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 3021006 < 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. +#endif + +#include <google/protobuf/port_undef.inc> +#include <google/protobuf/io/coded_stream.h> +#include <google/protobuf/arena.h> +#include <google/protobuf/arenastring.h> +#include <google/protobuf/generated_message_util.h> +#include <google/protobuf/metadata_lite.h> +#include <google/protobuf/generated_message_reflection.h> +#include <google/protobuf/message.h> +#include <google/protobuf/repeated_field.h> // IWYU pragma: export +#include <google/protobuf/extension_set.h> // IWYU pragma: export +#include <google/protobuf/map.h> // IWYU pragma: export +#include <google/protobuf/map_entry.h> +#include <google/protobuf/map_field_inl.h> +#include <google/protobuf/generated_enum_reflection.h> +#include <google/protobuf/unknown_field_set.h> +// @@protoc_insertion_point(includes) +#include <google/protobuf/port_def.inc> +#define PROTOBUF_INTERNAL_EXPORT_google_2fprotobuf_2fstruct_2eproto PROTOBUF_EXPORT +PROTOBUF_NAMESPACE_OPEN +namespace internal { +class AnyMetadata; +} // namespace internal +PROTOBUF_NAMESPACE_CLOSE + +// Internal implementation detail -- do not use these members. +struct PROTOBUF_EXPORT TableStruct_google_2fprotobuf_2fstruct_2eproto { + static const uint32_t offsets[]; +}; +PROTOBUF_EXPORT extern const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable descriptor_table_google_2fprotobuf_2fstruct_2eproto; +PROTOBUF_NAMESPACE_OPEN +class ListValue; +struct ListValueDefaultTypeInternal; +PROTOBUF_EXPORT extern ListValueDefaultTypeInternal _ListValue_default_instance_; +class Struct; +struct StructDefaultTypeInternal; +PROTOBUF_EXPORT extern StructDefaultTypeInternal _Struct_default_instance_; +class Struct_FieldsEntry_DoNotUse; +struct Struct_FieldsEntry_DoNotUseDefaultTypeInternal; +PROTOBUF_EXPORT extern Struct_FieldsEntry_DoNotUseDefaultTypeInternal _Struct_FieldsEntry_DoNotUse_default_instance_; +class Value; +struct ValueDefaultTypeInternal; +PROTOBUF_EXPORT extern ValueDefaultTypeInternal _Value_default_instance_; +PROTOBUF_NAMESPACE_CLOSE +PROTOBUF_NAMESPACE_OPEN +template<> PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::ListValue* Arena::CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::ListValue>(Arena*); +template<> PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::Struct* Arena::CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::Struct>(Arena*); +template<> PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::Struct_FieldsEntry_DoNotUse* Arena::CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::Struct_FieldsEntry_DoNotUse>(Arena*); +template<> PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::Value* Arena::CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::Value>(Arena*); +PROTOBUF_NAMESPACE_CLOSE +PROTOBUF_NAMESPACE_OPEN + +enum NullValue : int { + NULL_VALUE = 0, + NullValue_INT_MIN_SENTINEL_DO_NOT_USE_ = std::numeric_limits<int32_t>::min(), + NullValue_INT_MAX_SENTINEL_DO_NOT_USE_ = std::numeric_limits<int32_t>::max() +}; +PROTOBUF_EXPORT bool NullValue_IsValid(int value); +constexpr NullValue NullValue_MIN = NULL_VALUE; +constexpr NullValue NullValue_MAX = NULL_VALUE; +constexpr int NullValue_ARRAYSIZE = NullValue_MAX + 1; + +PROTOBUF_EXPORT const ::PROTOBUF_NAMESPACE_ID::EnumDescriptor* NullValue_descriptor(); +template<typename T> +inline const std::string& NullValue_Name(T enum_t_value) { + static_assert(::std::is_same<T, NullValue>::value || + ::std::is_integral<T>::value, + "Incorrect type passed to function NullValue_Name."); + return ::PROTOBUF_NAMESPACE_ID::internal::NameOfEnum( + NullValue_descriptor(), enum_t_value); +} +inline bool NullValue_Parse( + ::PROTOBUF_NAMESPACE_ID::ConstStringParam name, NullValue* value) { + return ::PROTOBUF_NAMESPACE_ID::internal::ParseNamedEnum<NullValue>( + NullValue_descriptor(), name, value); +} +// =================================================================== + +class Struct_FieldsEntry_DoNotUse : public ::PROTOBUF_NAMESPACE_ID::internal::MapEntry<Struct_FieldsEntry_DoNotUse, + std::string, ::PROTOBUF_NAMESPACE_ID::Value, + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::TYPE_STRING, + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::TYPE_MESSAGE> { +public: + typedef ::PROTOBUF_NAMESPACE_ID::internal::MapEntry<Struct_FieldsEntry_DoNotUse, + std::string, ::PROTOBUF_NAMESPACE_ID::Value, + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::TYPE_STRING, + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::TYPE_MESSAGE> SuperType; + Struct_FieldsEntry_DoNotUse(); + explicit PROTOBUF_CONSTEXPR Struct_FieldsEntry_DoNotUse( + ::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized); + explicit Struct_FieldsEntry_DoNotUse(::PROTOBUF_NAMESPACE_ID::Arena* arena); + void MergeFrom(const Struct_FieldsEntry_DoNotUse& other); + static const Struct_FieldsEntry_DoNotUse* internal_default_instance() { return reinterpret_cast<const Struct_FieldsEntry_DoNotUse*>(&_Struct_FieldsEntry_DoNotUse_default_instance_); } + static bool ValidateKey(std::string* s) { + return ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::VerifyUtf8String(s->data(), static_cast<int>(s->size()), ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::PARSE, "google.protobuf.Struct.FieldsEntry.key"); + } + static bool ValidateValue(void*) { return true; } + using ::PROTOBUF_NAMESPACE_ID::Message::MergeFrom; + ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final; + friend struct ::TableStruct_google_2fprotobuf_2fstruct_2eproto; +}; + +// ------------------------------------------------------------------- + +class PROTOBUF_EXPORT Struct final : + public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.Struct) */ { + public: + inline Struct() : Struct(nullptr) {} + ~Struct() override; + explicit PROTOBUF_CONSTEXPR Struct(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized); + + Struct(const Struct& from); + Struct(Struct&& from) noexcept + : Struct() { + *this = ::std::move(from); + } + + inline Struct& operator=(const Struct& from) { + CopyFrom(from); + return *this; + } + inline Struct& operator=(Struct&& from) noexcept { + if (this == &from) return *this; + if (GetOwningArena() == from.GetOwningArena() + #ifdef PROTOBUF_FORCE_COPY_IN_MOVE + && GetOwningArena() != nullptr + #endif // !PROTOBUF_FORCE_COPY_IN_MOVE + ) { + InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* descriptor() { + return GetDescriptor(); + } + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() { + return default_instance().GetMetadata().descriptor; + } + static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() { + return default_instance().GetMetadata().reflection; + } + static const Struct& default_instance() { + return *internal_default_instance(); + } + static inline const Struct* internal_default_instance() { + return reinterpret_cast<const Struct*>( + &_Struct_default_instance_); + } + static constexpr int kIndexInFileMessages = + 1; + + friend void swap(Struct& a, Struct& b) { + a.Swap(&b); + } + inline void Swap(Struct* other) { + if (other == this) return; + #ifdef PROTOBUF_FORCE_COPY_IN_SWAP + if (GetOwningArena() != nullptr && + GetOwningArena() == other->GetOwningArena()) { + #else // PROTOBUF_FORCE_COPY_IN_SWAP + if (GetOwningArena() == other->GetOwningArena()) { + #endif // !PROTOBUF_FORCE_COPY_IN_SWAP + InternalSwap(other); + } else { + ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(Struct* other) { + if (other == this) return; + GOOGLE_DCHECK(GetOwningArena() == other->GetOwningArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + Struct* New(::PROTOBUF_NAMESPACE_ID::Arena* arena = nullptr) const final { + return CreateMaybeMessage<Struct>(arena); + } + using ::PROTOBUF_NAMESPACE_ID::Message::CopyFrom; + void CopyFrom(const Struct& from); + using ::PROTOBUF_NAMESPACE_ID::Message::MergeFrom; + void MergeFrom( const Struct& from) { + Struct::MergeImpl(*this, from); + } + private: + static void MergeImpl(::PROTOBUF_NAMESPACE_ID::Message& to_msg, const ::PROTOBUF_NAMESPACE_ID::Message& from_msg); + public: + PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + bool IsInitialized() const final; + + size_t ByteSizeLong() const final; + const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final; + uint8_t* _InternalSerialize( + uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final; + int GetCachedSize() const final { return _impl_._cached_size_.Get(); } + + private: + void SharedCtor(::PROTOBUF_NAMESPACE_ID::Arena* arena, bool is_message_owned); + void SharedDtor(); + void SetCachedSize(int size) const final; + void InternalSwap(Struct* other); + + private: + friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata; + static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() { + return "google.protobuf.Struct"; + } + protected: + explicit Struct(::PROTOBUF_NAMESPACE_ID::Arena* arena, + bool is_message_owned = false); + private: + static void ArenaDtor(void* object); + public: + + static const ClassData _class_data_; + const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*GetClassData() const final; + + ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final; + + // nested types ---------------------------------------------------- + + + // accessors ------------------------------------------------------- + + enum : int { + kFieldsFieldNumber = 1, + }; + // map<string, .google.protobuf.Value> fields = 1; + int fields_size() const; + private: + int _internal_fields_size() const; + public: + void clear_fields(); + private: + const ::PROTOBUF_NAMESPACE_ID::Map< std::string, ::PROTOBUF_NAMESPACE_ID::Value >& + _internal_fields() const; + ::PROTOBUF_NAMESPACE_ID::Map< std::string, ::PROTOBUF_NAMESPACE_ID::Value >* + _internal_mutable_fields(); + public: + const ::PROTOBUF_NAMESPACE_ID::Map< std::string, ::PROTOBUF_NAMESPACE_ID::Value >& + fields() const; + ::PROTOBUF_NAMESPACE_ID::Map< std::string, ::PROTOBUF_NAMESPACE_ID::Value >* + mutable_fields(); + + // @@protoc_insertion_point(class_scope:google.protobuf.Struct) + private: + class _Internal; + + template <typename T> friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper; + typedef void InternalArenaConstructable_; + typedef void DestructorSkippable_; + struct Impl_ { + ::PROTOBUF_NAMESPACE_ID::internal::MapField< + Struct_FieldsEntry_DoNotUse, + std::string, ::PROTOBUF_NAMESPACE_ID::Value, + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::TYPE_STRING, + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::TYPE_MESSAGE> fields_; + mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_; + }; + union { Impl_ _impl_; }; + friend struct ::TableStruct_google_2fprotobuf_2fstruct_2eproto; +}; +// ------------------------------------------------------------------- + +class PROTOBUF_EXPORT Value final : + public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.Value) */ { + public: + inline Value() : Value(nullptr) {} + ~Value() override; + explicit PROTOBUF_CONSTEXPR Value(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized); + + Value(const Value& from); + Value(Value&& from) noexcept + : Value() { + *this = ::std::move(from); + } + + inline Value& operator=(const Value& from) { + CopyFrom(from); + return *this; + } + inline Value& operator=(Value&& from) noexcept { + if (this == &from) return *this; + if (GetOwningArena() == from.GetOwningArena() + #ifdef PROTOBUF_FORCE_COPY_IN_MOVE + && GetOwningArena() != nullptr + #endif // !PROTOBUF_FORCE_COPY_IN_MOVE + ) { + InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* descriptor() { + return GetDescriptor(); + } + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() { + return default_instance().GetMetadata().descriptor; + } + static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() { + return default_instance().GetMetadata().reflection; + } + static const Value& default_instance() { + return *internal_default_instance(); + } + enum KindCase { + kNullValue = 1, + kNumberValue = 2, + kStringValue = 3, + kBoolValue = 4, + kStructValue = 5, + kListValue = 6, + KIND_NOT_SET = 0, + }; + + static inline const Value* internal_default_instance() { + return reinterpret_cast<const Value*>( + &_Value_default_instance_); + } + static constexpr int kIndexInFileMessages = + 2; + + friend void swap(Value& a, Value& b) { + a.Swap(&b); + } + inline void Swap(Value* other) { + if (other == this) return; + #ifdef PROTOBUF_FORCE_COPY_IN_SWAP + if (GetOwningArena() != nullptr && + GetOwningArena() == other->GetOwningArena()) { + #else // PROTOBUF_FORCE_COPY_IN_SWAP + if (GetOwningArena() == other->GetOwningArena()) { + #endif // !PROTOBUF_FORCE_COPY_IN_SWAP + InternalSwap(other); + } else { + ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(Value* other) { + if (other == this) return; + GOOGLE_DCHECK(GetOwningArena() == other->GetOwningArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + Value* New(::PROTOBUF_NAMESPACE_ID::Arena* arena = nullptr) const final { + return CreateMaybeMessage<Value>(arena); + } + using ::PROTOBUF_NAMESPACE_ID::Message::CopyFrom; + void CopyFrom(const Value& from); + using ::PROTOBUF_NAMESPACE_ID::Message::MergeFrom; + void MergeFrom( const Value& from) { + Value::MergeImpl(*this, from); + } + private: + static void MergeImpl(::PROTOBUF_NAMESPACE_ID::Message& to_msg, const ::PROTOBUF_NAMESPACE_ID::Message& from_msg); + public: + PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + bool IsInitialized() const final; + + size_t ByteSizeLong() const final; + const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final; + uint8_t* _InternalSerialize( + uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final; + int GetCachedSize() const final { return _impl_._cached_size_.Get(); } + + private: + void SharedCtor(::PROTOBUF_NAMESPACE_ID::Arena* arena, bool is_message_owned); + void SharedDtor(); + void SetCachedSize(int size) const final; + void InternalSwap(Value* other); + + private: + friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata; + static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() { + return "google.protobuf.Value"; + } + protected: + explicit Value(::PROTOBUF_NAMESPACE_ID::Arena* arena, + bool is_message_owned = false); + public: + + static const ClassData _class_data_; + const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*GetClassData() const final; + + ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final; + + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + + enum : int { + kNullValueFieldNumber = 1, + kNumberValueFieldNumber = 2, + kStringValueFieldNumber = 3, + kBoolValueFieldNumber = 4, + kStructValueFieldNumber = 5, + kListValueFieldNumber = 6, + }; + // .google.protobuf.NullValue null_value = 1; + bool has_null_value() const; + private: + bool _internal_has_null_value() const; + public: + void clear_null_value(); + ::PROTOBUF_NAMESPACE_ID::NullValue null_value() const; + void set_null_value(::PROTOBUF_NAMESPACE_ID::NullValue value); + private: + ::PROTOBUF_NAMESPACE_ID::NullValue _internal_null_value() const; + void _internal_set_null_value(::PROTOBUF_NAMESPACE_ID::NullValue value); + public: + + // double number_value = 2; + bool has_number_value() const; + private: + bool _internal_has_number_value() const; + public: + void clear_number_value(); + double number_value() const; + void set_number_value(double value); + private: + double _internal_number_value() const; + void _internal_set_number_value(double value); + public: + + // string string_value = 3; + bool has_string_value() const; + private: + bool _internal_has_string_value() const; + public: + void clear_string_value(); + const std::string& string_value() const; + template <typename ArgT0 = const std::string&, typename... ArgT> + void set_string_value(ArgT0&& arg0, ArgT... args); + std::string* mutable_string_value(); + PROTOBUF_NODISCARD std::string* release_string_value(); + void set_allocated_string_value(std::string* string_value); + private: + const std::string& _internal_string_value() const; + inline PROTOBUF_ALWAYS_INLINE void _internal_set_string_value(const std::string& value); + std::string* _internal_mutable_string_value(); + public: + + // bool bool_value = 4; + bool has_bool_value() const; + private: + bool _internal_has_bool_value() const; + public: + void clear_bool_value(); + bool bool_value() const; + void set_bool_value(bool value); + private: + bool _internal_bool_value() const; + void _internal_set_bool_value(bool value); + public: + + // .google.protobuf.Struct struct_value = 5; + bool has_struct_value() const; + private: + bool _internal_has_struct_value() const; + public: + void clear_struct_value(); + const ::PROTOBUF_NAMESPACE_ID::Struct& struct_value() const; + PROTOBUF_NODISCARD ::PROTOBUF_NAMESPACE_ID::Struct* release_struct_value(); + ::PROTOBUF_NAMESPACE_ID::Struct* mutable_struct_value(); + void set_allocated_struct_value(::PROTOBUF_NAMESPACE_ID::Struct* struct_value); + private: + const ::PROTOBUF_NAMESPACE_ID::Struct& _internal_struct_value() const; + ::PROTOBUF_NAMESPACE_ID::Struct* _internal_mutable_struct_value(); + public: + void unsafe_arena_set_allocated_struct_value( + ::PROTOBUF_NAMESPACE_ID::Struct* struct_value); + ::PROTOBUF_NAMESPACE_ID::Struct* unsafe_arena_release_struct_value(); + + // .google.protobuf.ListValue list_value = 6; + bool has_list_value() const; + private: + bool _internal_has_list_value() const; + public: + void clear_list_value(); + const ::PROTOBUF_NAMESPACE_ID::ListValue& list_value() const; + PROTOBUF_NODISCARD ::PROTOBUF_NAMESPACE_ID::ListValue* release_list_value(); + ::PROTOBUF_NAMESPACE_ID::ListValue* mutable_list_value(); + void set_allocated_list_value(::PROTOBUF_NAMESPACE_ID::ListValue* list_value); + private: + const ::PROTOBUF_NAMESPACE_ID::ListValue& _internal_list_value() const; + ::PROTOBUF_NAMESPACE_ID::ListValue* _internal_mutable_list_value(); + public: + void unsafe_arena_set_allocated_list_value( + ::PROTOBUF_NAMESPACE_ID::ListValue* list_value); + ::PROTOBUF_NAMESPACE_ID::ListValue* unsafe_arena_release_list_value(); + + void clear_kind(); + KindCase kind_case() const; + // @@protoc_insertion_point(class_scope:google.protobuf.Value) + private: + class _Internal; + void set_has_null_value(); + void set_has_number_value(); + void set_has_string_value(); + void set_has_bool_value(); + void set_has_struct_value(); + void set_has_list_value(); + + inline bool has_kind() const; + inline void clear_has_kind(); + + template <typename T> friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper; + typedef void InternalArenaConstructable_; + typedef void DestructorSkippable_; + struct Impl_ { + union KindUnion { + constexpr KindUnion() : _constinit_{} {} + ::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized _constinit_; + int null_value_; + double number_value_; + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr string_value_; + bool bool_value_; + ::PROTOBUF_NAMESPACE_ID::Struct* struct_value_; + ::PROTOBUF_NAMESPACE_ID::ListValue* list_value_; + } kind_; + mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_; + uint32_t _oneof_case_[1]; + + }; + union { Impl_ _impl_; }; + friend struct ::TableStruct_google_2fprotobuf_2fstruct_2eproto; +}; +// ------------------------------------------------------------------- + +class PROTOBUF_EXPORT ListValue final : + public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.ListValue) */ { + public: + inline ListValue() : ListValue(nullptr) {} + ~ListValue() override; + explicit PROTOBUF_CONSTEXPR ListValue(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized); + + ListValue(const ListValue& from); + ListValue(ListValue&& from) noexcept + : ListValue() { + *this = ::std::move(from); + } + + inline ListValue& operator=(const ListValue& from) { + CopyFrom(from); + return *this; + } + inline ListValue& operator=(ListValue&& from) noexcept { + if (this == &from) return *this; + if (GetOwningArena() == from.GetOwningArena() + #ifdef PROTOBUF_FORCE_COPY_IN_MOVE + && GetOwningArena() != nullptr + #endif // !PROTOBUF_FORCE_COPY_IN_MOVE + ) { + InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* descriptor() { + return GetDescriptor(); + } + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() { + return default_instance().GetMetadata().descriptor; + } + static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() { + return default_instance().GetMetadata().reflection; + } + static const ListValue& default_instance() { + return *internal_default_instance(); + } + static inline const ListValue* internal_default_instance() { + return reinterpret_cast<const ListValue*>( + &_ListValue_default_instance_); + } + static constexpr int kIndexInFileMessages = + 3; + + friend void swap(ListValue& a, ListValue& b) { + a.Swap(&b); + } + inline void Swap(ListValue* other) { + if (other == this) return; + #ifdef PROTOBUF_FORCE_COPY_IN_SWAP + if (GetOwningArena() != nullptr && + GetOwningArena() == other->GetOwningArena()) { + #else // PROTOBUF_FORCE_COPY_IN_SWAP + if (GetOwningArena() == other->GetOwningArena()) { + #endif // !PROTOBUF_FORCE_COPY_IN_SWAP + InternalSwap(other); + } else { + ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(ListValue* other) { + if (other == this) return; + GOOGLE_DCHECK(GetOwningArena() == other->GetOwningArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + ListValue* New(::PROTOBUF_NAMESPACE_ID::Arena* arena = nullptr) const final { + return CreateMaybeMessage<ListValue>(arena); + } + using ::PROTOBUF_NAMESPACE_ID::Message::CopyFrom; + void CopyFrom(const ListValue& from); + using ::PROTOBUF_NAMESPACE_ID::Message::MergeFrom; + void MergeFrom( const ListValue& from) { + ListValue::MergeImpl(*this, from); + } + private: + static void MergeImpl(::PROTOBUF_NAMESPACE_ID::Message& to_msg, const ::PROTOBUF_NAMESPACE_ID::Message& from_msg); + public: + PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + bool IsInitialized() const final; + + size_t ByteSizeLong() const final; + const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final; + uint8_t* _InternalSerialize( + uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final; + int GetCachedSize() const final { return _impl_._cached_size_.Get(); } + + private: + void SharedCtor(::PROTOBUF_NAMESPACE_ID::Arena* arena, bool is_message_owned); + void SharedDtor(); + void SetCachedSize(int size) const final; + void InternalSwap(ListValue* other); + + private: + friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata; + static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() { + return "google.protobuf.ListValue"; + } + protected: + explicit ListValue(::PROTOBUF_NAMESPACE_ID::Arena* arena, + bool is_message_owned = false); + public: + + static const ClassData _class_data_; + const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*GetClassData() const final; + + ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final; + + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + + enum : int { + kValuesFieldNumber = 1, + }; + // repeated .google.protobuf.Value values = 1; + int values_size() const; + private: + int _internal_values_size() const; + public: + void clear_values(); + ::PROTOBUF_NAMESPACE_ID::Value* mutable_values(int index); + ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::Value >* + mutable_values(); + private: + const ::PROTOBUF_NAMESPACE_ID::Value& _internal_values(int index) const; + ::PROTOBUF_NAMESPACE_ID::Value* _internal_add_values(); + public: + const ::PROTOBUF_NAMESPACE_ID::Value& values(int index) const; + ::PROTOBUF_NAMESPACE_ID::Value* add_values(); + const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::Value >& + values() const; + + // @@protoc_insertion_point(class_scope:google.protobuf.ListValue) + private: + class _Internal; + + template <typename T> friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper; + typedef void InternalArenaConstructable_; + typedef void DestructorSkippable_; + struct Impl_ { + ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::Value > values_; + mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_; + }; + union { Impl_ _impl_; }; + friend struct ::TableStruct_google_2fprotobuf_2fstruct_2eproto; +}; +// =================================================================== + + +// =================================================================== + +#ifdef __GNUC__ + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wstrict-aliasing" +#endif // __GNUC__ +// ------------------------------------------------------------------- + +// Struct + +// map<string, .google.protobuf.Value> fields = 1; +inline int Struct::_internal_fields_size() const { + return _impl_.fields_.size(); +} +inline int Struct::fields_size() const { + return _internal_fields_size(); +} +inline void Struct::clear_fields() { + _impl_.fields_.Clear(); +} +inline const ::PROTOBUF_NAMESPACE_ID::Map< std::string, ::PROTOBUF_NAMESPACE_ID::Value >& +Struct::_internal_fields() const { + return _impl_.fields_.GetMap(); +} +inline const ::PROTOBUF_NAMESPACE_ID::Map< std::string, ::PROTOBUF_NAMESPACE_ID::Value >& +Struct::fields() const { + // @@protoc_insertion_point(field_map:google.protobuf.Struct.fields) + return _internal_fields(); +} +inline ::PROTOBUF_NAMESPACE_ID::Map< std::string, ::PROTOBUF_NAMESPACE_ID::Value >* +Struct::_internal_mutable_fields() { + return _impl_.fields_.MutableMap(); +} +inline ::PROTOBUF_NAMESPACE_ID::Map< std::string, ::PROTOBUF_NAMESPACE_ID::Value >* +Struct::mutable_fields() { + // @@protoc_insertion_point(field_mutable_map:google.protobuf.Struct.fields) + return _internal_mutable_fields(); +} + +// ------------------------------------------------------------------- + +// Value + +// .google.protobuf.NullValue null_value = 1; +inline bool Value::_internal_has_null_value() const { + return kind_case() == kNullValue; +} +inline bool Value::has_null_value() const { + return _internal_has_null_value(); +} +inline void Value::set_has_null_value() { + _impl_._oneof_case_[0] = kNullValue; +} +inline void Value::clear_null_value() { + if (_internal_has_null_value()) { + _impl_.kind_.null_value_ = 0; + clear_has_kind(); + } +} +inline ::PROTOBUF_NAMESPACE_ID::NullValue Value::_internal_null_value() const { + if (_internal_has_null_value()) { + return static_cast< ::PROTOBUF_NAMESPACE_ID::NullValue >(_impl_.kind_.null_value_); + } + return static_cast< ::PROTOBUF_NAMESPACE_ID::NullValue >(0); +} +inline ::PROTOBUF_NAMESPACE_ID::NullValue Value::null_value() const { + // @@protoc_insertion_point(field_get:google.protobuf.Value.null_value) + return _internal_null_value(); +} +inline void Value::_internal_set_null_value(::PROTOBUF_NAMESPACE_ID::NullValue value) { + if (!_internal_has_null_value()) { + clear_kind(); + set_has_null_value(); + } + _impl_.kind_.null_value_ = value; +} +inline void Value::set_null_value(::PROTOBUF_NAMESPACE_ID::NullValue value) { + _internal_set_null_value(value); + // @@protoc_insertion_point(field_set:google.protobuf.Value.null_value) +} + +// double number_value = 2; +inline bool Value::_internal_has_number_value() const { + return kind_case() == kNumberValue; +} +inline bool Value::has_number_value() const { + return _internal_has_number_value(); +} +inline void Value::set_has_number_value() { + _impl_._oneof_case_[0] = kNumberValue; +} +inline void Value::clear_number_value() { + if (_internal_has_number_value()) { + _impl_.kind_.number_value_ = 0; + clear_has_kind(); + } +} +inline double Value::_internal_number_value() const { + if (_internal_has_number_value()) { + return _impl_.kind_.number_value_; + } + return 0; +} +inline void Value::_internal_set_number_value(double value) { + if (!_internal_has_number_value()) { + clear_kind(); + set_has_number_value(); + } + _impl_.kind_.number_value_ = value; +} +inline double Value::number_value() const { + // @@protoc_insertion_point(field_get:google.protobuf.Value.number_value) + return _internal_number_value(); +} +inline void Value::set_number_value(double value) { + _internal_set_number_value(value); + // @@protoc_insertion_point(field_set:google.protobuf.Value.number_value) +} + +// string string_value = 3; +inline bool Value::_internal_has_string_value() const { + return kind_case() == kStringValue; +} +inline bool Value::has_string_value() const { + return _internal_has_string_value(); +} +inline void Value::set_has_string_value() { + _impl_._oneof_case_[0] = kStringValue; +} +inline void Value::clear_string_value() { + if (_internal_has_string_value()) { + _impl_.kind_.string_value_.Destroy(); + clear_has_kind(); + } +} +inline const std::string& Value::string_value() const { + // @@protoc_insertion_point(field_get:google.protobuf.Value.string_value) + return _internal_string_value(); +} +template <typename ArgT0, typename... ArgT> +inline void Value::set_string_value(ArgT0&& arg0, ArgT... args) { + if (!_internal_has_string_value()) { + clear_kind(); + set_has_string_value(); + _impl_.kind_.string_value_.InitDefault(); + } + _impl_.kind_.string_value_.Set( static_cast<ArgT0 &&>(arg0), args..., GetArenaForAllocation()); + // @@protoc_insertion_point(field_set:google.protobuf.Value.string_value) +} +inline std::string* Value::mutable_string_value() { + std::string* _s = _internal_mutable_string_value(); + // @@protoc_insertion_point(field_mutable:google.protobuf.Value.string_value) + return _s; +} +inline const std::string& Value::_internal_string_value() const { + if (_internal_has_string_value()) { + return _impl_.kind_.string_value_.Get(); + } + return ::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(); +} +inline void Value::_internal_set_string_value(const std::string& value) { + if (!_internal_has_string_value()) { + clear_kind(); + set_has_string_value(); + _impl_.kind_.string_value_.InitDefault(); + } + _impl_.kind_.string_value_.Set(value, GetArenaForAllocation()); +} +inline std::string* Value::_internal_mutable_string_value() { + if (!_internal_has_string_value()) { + clear_kind(); + set_has_string_value(); + _impl_.kind_.string_value_.InitDefault(); + } + return _impl_.kind_.string_value_.Mutable( GetArenaForAllocation()); +} +inline std::string* Value::release_string_value() { + // @@protoc_insertion_point(field_release:google.protobuf.Value.string_value) + if (_internal_has_string_value()) { + clear_has_kind(); + return _impl_.kind_.string_value_.Release(); + } else { + return nullptr; + } +} +inline void Value::set_allocated_string_value(std::string* string_value) { + if (has_kind()) { + clear_kind(); + } + if (string_value != nullptr) { + set_has_string_value(); + _impl_.kind_.string_value_.InitAllocated(string_value, GetArenaForAllocation()); + } + // @@protoc_insertion_point(field_set_allocated:google.protobuf.Value.string_value) +} + +// bool bool_value = 4; +inline bool Value::_internal_has_bool_value() const { + return kind_case() == kBoolValue; +} +inline bool Value::has_bool_value() const { + return _internal_has_bool_value(); +} +inline void Value::set_has_bool_value() { + _impl_._oneof_case_[0] = kBoolValue; +} +inline void Value::clear_bool_value() { + if (_internal_has_bool_value()) { + _impl_.kind_.bool_value_ = false; + clear_has_kind(); + } +} +inline bool Value::_internal_bool_value() const { + if (_internal_has_bool_value()) { + return _impl_.kind_.bool_value_; + } + return false; +} +inline void Value::_internal_set_bool_value(bool value) { + if (!_internal_has_bool_value()) { + clear_kind(); + set_has_bool_value(); + } + _impl_.kind_.bool_value_ = value; +} +inline bool Value::bool_value() const { + // @@protoc_insertion_point(field_get:google.protobuf.Value.bool_value) + return _internal_bool_value(); +} +inline void Value::set_bool_value(bool value) { + _internal_set_bool_value(value); + // @@protoc_insertion_point(field_set:google.protobuf.Value.bool_value) +} + +// .google.protobuf.Struct struct_value = 5; +inline bool Value::_internal_has_struct_value() const { + return kind_case() == kStructValue; +} +inline bool Value::has_struct_value() const { + return _internal_has_struct_value(); +} +inline void Value::set_has_struct_value() { + _impl_._oneof_case_[0] = kStructValue; +} +inline void Value::clear_struct_value() { + if (_internal_has_struct_value()) { + if (GetArenaForAllocation() == nullptr) { + delete _impl_.kind_.struct_value_; + } + clear_has_kind(); + } +} +inline ::PROTOBUF_NAMESPACE_ID::Struct* Value::release_struct_value() { + // @@protoc_insertion_point(field_release:google.protobuf.Value.struct_value) + if (_internal_has_struct_value()) { + clear_has_kind(); + ::PROTOBUF_NAMESPACE_ID::Struct* temp = _impl_.kind_.struct_value_; + if (GetArenaForAllocation() != nullptr) { + temp = ::PROTOBUF_NAMESPACE_ID::internal::DuplicateIfNonNull(temp); + } + _impl_.kind_.struct_value_ = nullptr; + return temp; + } else { + return nullptr; + } +} +inline const ::PROTOBUF_NAMESPACE_ID::Struct& Value::_internal_struct_value() const { + return _internal_has_struct_value() + ? *_impl_.kind_.struct_value_ + : reinterpret_cast< ::PROTOBUF_NAMESPACE_ID::Struct&>(::PROTOBUF_NAMESPACE_ID::_Struct_default_instance_); +} +inline const ::PROTOBUF_NAMESPACE_ID::Struct& Value::struct_value() const { + // @@protoc_insertion_point(field_get:google.protobuf.Value.struct_value) + return _internal_struct_value(); +} +inline ::PROTOBUF_NAMESPACE_ID::Struct* Value::unsafe_arena_release_struct_value() { + // @@protoc_insertion_point(field_unsafe_arena_release:google.protobuf.Value.struct_value) + if (_internal_has_struct_value()) { + clear_has_kind(); + ::PROTOBUF_NAMESPACE_ID::Struct* temp = _impl_.kind_.struct_value_; + _impl_.kind_.struct_value_ = nullptr; + return temp; + } else { + return nullptr; + } +} +inline void Value::unsafe_arena_set_allocated_struct_value(::PROTOBUF_NAMESPACE_ID::Struct* struct_value) { + clear_kind(); + if (struct_value) { + set_has_struct_value(); + _impl_.kind_.struct_value_ = struct_value; + } + // @@protoc_insertion_point(field_unsafe_arena_set_allocated:google.protobuf.Value.struct_value) +} +inline ::PROTOBUF_NAMESPACE_ID::Struct* Value::_internal_mutable_struct_value() { + if (!_internal_has_struct_value()) { + clear_kind(); + set_has_struct_value(); + _impl_.kind_.struct_value_ = CreateMaybeMessage< ::PROTOBUF_NAMESPACE_ID::Struct >(GetArenaForAllocation()); + } + return _impl_.kind_.struct_value_; +} +inline ::PROTOBUF_NAMESPACE_ID::Struct* Value::mutable_struct_value() { + ::PROTOBUF_NAMESPACE_ID::Struct* _msg = _internal_mutable_struct_value(); + // @@protoc_insertion_point(field_mutable:google.protobuf.Value.struct_value) + return _msg; +} + +// .google.protobuf.ListValue list_value = 6; +inline bool Value::_internal_has_list_value() const { + return kind_case() == kListValue; +} +inline bool Value::has_list_value() const { + return _internal_has_list_value(); +} +inline void Value::set_has_list_value() { + _impl_._oneof_case_[0] = kListValue; +} +inline void Value::clear_list_value() { + if (_internal_has_list_value()) { + if (GetArenaForAllocation() == nullptr) { + delete _impl_.kind_.list_value_; + } + clear_has_kind(); + } +} +inline ::PROTOBUF_NAMESPACE_ID::ListValue* Value::release_list_value() { + // @@protoc_insertion_point(field_release:google.protobuf.Value.list_value) + if (_internal_has_list_value()) { + clear_has_kind(); + ::PROTOBUF_NAMESPACE_ID::ListValue* temp = _impl_.kind_.list_value_; + if (GetArenaForAllocation() != nullptr) { + temp = ::PROTOBUF_NAMESPACE_ID::internal::DuplicateIfNonNull(temp); + } + _impl_.kind_.list_value_ = nullptr; + return temp; + } else { + return nullptr; + } +} +inline const ::PROTOBUF_NAMESPACE_ID::ListValue& Value::_internal_list_value() const { + return _internal_has_list_value() + ? *_impl_.kind_.list_value_ + : reinterpret_cast< ::PROTOBUF_NAMESPACE_ID::ListValue&>(::PROTOBUF_NAMESPACE_ID::_ListValue_default_instance_); +} +inline const ::PROTOBUF_NAMESPACE_ID::ListValue& Value::list_value() const { + // @@protoc_insertion_point(field_get:google.protobuf.Value.list_value) + return _internal_list_value(); +} +inline ::PROTOBUF_NAMESPACE_ID::ListValue* Value::unsafe_arena_release_list_value() { + // @@protoc_insertion_point(field_unsafe_arena_release:google.protobuf.Value.list_value) + if (_internal_has_list_value()) { + clear_has_kind(); + ::PROTOBUF_NAMESPACE_ID::ListValue* temp = _impl_.kind_.list_value_; + _impl_.kind_.list_value_ = nullptr; + return temp; + } else { + return nullptr; + } +} +inline void Value::unsafe_arena_set_allocated_list_value(::PROTOBUF_NAMESPACE_ID::ListValue* list_value) { + clear_kind(); + if (list_value) { + set_has_list_value(); + _impl_.kind_.list_value_ = list_value; + } + // @@protoc_insertion_point(field_unsafe_arena_set_allocated:google.protobuf.Value.list_value) +} +inline ::PROTOBUF_NAMESPACE_ID::ListValue* Value::_internal_mutable_list_value() { + if (!_internal_has_list_value()) { + clear_kind(); + set_has_list_value(); + _impl_.kind_.list_value_ = CreateMaybeMessage< ::PROTOBUF_NAMESPACE_ID::ListValue >(GetArenaForAllocation()); + } + return _impl_.kind_.list_value_; +} +inline ::PROTOBUF_NAMESPACE_ID::ListValue* Value::mutable_list_value() { + ::PROTOBUF_NAMESPACE_ID::ListValue* _msg = _internal_mutable_list_value(); + // @@protoc_insertion_point(field_mutable:google.protobuf.Value.list_value) + return _msg; +} + +inline bool Value::has_kind() const { + return kind_case() != KIND_NOT_SET; +} +inline void Value::clear_has_kind() { + _impl_._oneof_case_[0] = KIND_NOT_SET; +} +inline Value::KindCase Value::kind_case() const { + return Value::KindCase(_impl_._oneof_case_[0]); +} +// ------------------------------------------------------------------- + +// ListValue + +// repeated .google.protobuf.Value values = 1; +inline int ListValue::_internal_values_size() const { + return _impl_.values_.size(); +} +inline int ListValue::values_size() const { + return _internal_values_size(); +} +inline void ListValue::clear_values() { + _impl_.values_.Clear(); +} +inline ::PROTOBUF_NAMESPACE_ID::Value* ListValue::mutable_values(int index) { + // @@protoc_insertion_point(field_mutable:google.protobuf.ListValue.values) + return _impl_.values_.Mutable(index); +} +inline ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::Value >* +ListValue::mutable_values() { + // @@protoc_insertion_point(field_mutable_list:google.protobuf.ListValue.values) + return &_impl_.values_; +} +inline const ::PROTOBUF_NAMESPACE_ID::Value& ListValue::_internal_values(int index) const { + return _impl_.values_.Get(index); +} +inline const ::PROTOBUF_NAMESPACE_ID::Value& ListValue::values(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.ListValue.values) + return _internal_values(index); +} +inline ::PROTOBUF_NAMESPACE_ID::Value* ListValue::_internal_add_values() { + return _impl_.values_.Add(); +} +inline ::PROTOBUF_NAMESPACE_ID::Value* ListValue::add_values() { + ::PROTOBUF_NAMESPACE_ID::Value* _add = _internal_add_values(); + // @@protoc_insertion_point(field_add:google.protobuf.ListValue.values) + return _add; +} +inline const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::Value >& +ListValue::values() const { + // @@protoc_insertion_point(field_list:google.protobuf.ListValue.values) + return _impl_.values_; +} + +#ifdef __GNUC__ + #pragma GCC diagnostic pop +#endif // __GNUC__ +// ------------------------------------------------------------------- + +// ------------------------------------------------------------------- + +// ------------------------------------------------------------------- + + +// @@protoc_insertion_point(namespace_scope) + +PROTOBUF_NAMESPACE_CLOSE + +PROTOBUF_NAMESPACE_OPEN + +template <> struct is_proto_enum< ::PROTOBUF_NAMESPACE_ID::NullValue> : ::std::true_type {}; +template <> +inline const EnumDescriptor* GetEnumDescriptor< ::PROTOBUF_NAMESPACE_ID::NullValue>() { + return ::PROTOBUF_NAMESPACE_ID::NullValue_descriptor(); +} + +PROTOBUF_NAMESPACE_CLOSE + +// @@protoc_insertion_point(global_scope) + +#include <google/protobuf/port_undef.inc> +#endif // GOOGLE_PROTOBUF_INCLUDED_GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2fstruct_2eproto diff --git a/toolkit/components/protobuf/src/google/protobuf/struct.proto b/toolkit/components/protobuf/src/google/protobuf/struct.proto new file mode 100644 index 0000000000..0ac843ca08 --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/struct.proto @@ -0,0 +1,95 @@ +// 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. + +syntax = "proto3"; + +package google.protobuf; + +option csharp_namespace = "Google.Protobuf.WellKnownTypes"; +option cc_enable_arenas = true; +option go_package = "google.golang.org/protobuf/types/known/structpb"; +option java_package = "com.google.protobuf"; +option java_outer_classname = "StructProto"; +option java_multiple_files = true; +option objc_class_prefix = "GPB"; + +// `Struct` represents a structured data value, consisting of fields +// which map to dynamically typed values. In some languages, `Struct` +// might be supported by a native representation. For example, in +// scripting languages like JS a struct is represented as an +// object. The details of that representation are described together +// with the proto support for the language. +// +// The JSON representation for `Struct` is JSON object. +message Struct { + // Unordered map of dynamically typed values. + map<string, Value> fields = 1; +} + +// `Value` represents a dynamically typed value which can be either +// null, a number, a string, a boolean, a recursive struct value, or a +// list of values. A producer of value is expected to set one of these +// variants. Absence of any variant indicates an error. +// +// The JSON representation for `Value` is JSON value. +message Value { + // The kind of value. + oneof kind { + // Represents a null value. + NullValue null_value = 1; + // Represents a double value. + double number_value = 2; + // Represents a string value. + string string_value = 3; + // Represents a boolean value. + bool bool_value = 4; + // Represents a structured value. + Struct struct_value = 5; + // Represents a repeated `Value`. + ListValue list_value = 6; + } +} + +// `NullValue` is a singleton enumeration to represent the null value for the +// `Value` type union. +// +// The JSON representation for `NullValue` is JSON `null`. +enum NullValue { + // Null value. + NULL_VALUE = 0; +} + +// `ListValue` is a wrapper around a repeated field of values. +// +// The JSON representation for `ListValue` is JSON array. +message ListValue { + // Repeated field of dynamically typed values. + repeated Value values = 1; +} diff --git a/toolkit/components/protobuf/src/google/protobuf/stubs/bytestream.cc b/toolkit/components/protobuf/src/google/protobuf/stubs/bytestream.cc new file mode 100644 index 0000000000..980d6f6cfc --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/stubs/bytestream.cc @@ -0,0 +1,194 @@ +// 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. + +#include <google/protobuf/stubs/bytestream.h> + +#include <string.h> +#include <algorithm> + +#include <google/protobuf/stubs/logging.h> + +namespace google { +namespace protobuf { +namespace strings { + +void ByteSource::CopyTo(ByteSink* sink, size_t n) { + while (n > 0) { + StringPiece fragment = Peek(); + if (fragment.empty()) { + GOOGLE_LOG(DFATAL) << "ByteSource::CopyTo() overran input."; + break; + } + std::size_t fragment_size = std::min<std::size_t>(n, fragment.size()); + sink->Append(fragment.data(), fragment_size); + Skip(fragment_size); + n -= fragment_size; + } +} + +void ByteSink::Flush() {} + +void UncheckedArrayByteSink::Append(const char* data, size_t n) { + if (data != dest_) { + // Catch cases where the pointer returned by GetAppendBuffer() was modified. + GOOGLE_DCHECK(!(dest_ <= data && data < (dest_ + n))) + << "Append() data[] overlaps with dest_[]"; + memcpy(dest_, data, n); + } + dest_ += n; +} + +CheckedArrayByteSink::CheckedArrayByteSink(char* outbuf, size_t capacity) + : outbuf_(outbuf), capacity_(capacity), size_(0), overflowed_(false) { +} + +void CheckedArrayByteSink::Append(const char* bytes, size_t n) { + size_t available = capacity_ - size_; + if (n > available) { + n = available; + overflowed_ = true; + } + if (n > 0 && bytes != (outbuf_ + size_)) { + // Catch cases where the pointer returned by GetAppendBuffer() was modified. + GOOGLE_DCHECK(!(outbuf_ <= bytes && bytes < (outbuf_ + capacity_))) + << "Append() bytes[] overlaps with outbuf_[]"; + memcpy(outbuf_ + size_, bytes, n); + } + size_ += n; +} + +GrowingArrayByteSink::GrowingArrayByteSink(size_t estimated_size) + : capacity_(estimated_size), + buf_(new char[estimated_size]), + size_(0) { +} + +GrowingArrayByteSink::~GrowingArrayByteSink() { + delete[] buf_; // Just in case the user didn't call GetBuffer. +} + +void GrowingArrayByteSink::Append(const char* bytes, size_t n) { + size_t available = capacity_ - size_; + if (bytes != (buf_ + size_)) { + // Catch cases where the pointer returned by GetAppendBuffer() was modified. + // We need to test for this before calling Expand() which may reallocate. + GOOGLE_DCHECK(!(buf_ <= bytes && bytes < (buf_ + capacity_))) + << "Append() bytes[] overlaps with buf_[]"; + } + if (n > available) { + Expand(n - available); + } + if (n > 0 && bytes != (buf_ + size_)) { + memcpy(buf_ + size_, bytes, n); + } + size_ += n; +} + +char* GrowingArrayByteSink::GetBuffer(size_t* nbytes) { + ShrinkToFit(); + char* b = buf_; + *nbytes = size_; + buf_ = nullptr; + size_ = capacity_ = 0; + return b; +} + +void GrowingArrayByteSink::Expand(size_t amount) { // Expand by at least 50%. + size_t new_capacity = std::max(capacity_ + amount, (3 * capacity_) / 2); + char* bigger = new char[new_capacity]; + memcpy(bigger, buf_, size_); + delete[] buf_; + buf_ = bigger; + capacity_ = new_capacity; +} + +void GrowingArrayByteSink::ShrinkToFit() { + // Shrink only if the buffer is large and size_ is less than 3/4 + // of capacity_. + if (capacity_ > 256 && size_ < (3 * capacity_) / 4) { + char* just_enough = new char[size_]; + memcpy(just_enough, buf_, size_); + delete[] buf_; + buf_ = just_enough; + capacity_ = size_; + } +} + +void StringByteSink::Append(const char* data, size_t n) { + dest_->append(data, n); +} + +size_t ArrayByteSource::Available() const { + return input_.size(); +} + +StringPiece ArrayByteSource::Peek() { + return input_; +} + +void ArrayByteSource::Skip(size_t n) { + GOOGLE_DCHECK_LE(n, input_.size()); + input_.remove_prefix(n); +} + +LimitByteSource::LimitByteSource(ByteSource *source, size_t limit) + : source_(source), + limit_(limit) { +} + +size_t LimitByteSource::Available() const { + size_t available = source_->Available(); + if (available > limit_) { + available = limit_; + } + + return available; +} + +StringPiece LimitByteSource::Peek() { + StringPiece piece = source_->Peek(); + return StringPiece(piece.data(), std::min(piece.size(), limit_)); +} + +void LimitByteSource::Skip(size_t n) { + GOOGLE_DCHECK_LE(n, limit_); + source_->Skip(n); + limit_ -= n; +} + +void LimitByteSource::CopyTo(ByteSink *sink, size_t n) { + GOOGLE_DCHECK_LE(n, limit_); + source_->CopyTo(sink, n); + limit_ -= n; +} + +} // namespace strings +} // namespace protobuf +} // namespace google diff --git a/toolkit/components/protobuf/src/google/protobuf/stubs/bytestream.h b/toolkit/components/protobuf/src/google/protobuf/stubs/bytestream.h new file mode 100644 index 0000000000..c7a48dea54 --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/stubs/bytestream.h @@ -0,0 +1,351 @@ +// 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. + +// This file declares the ByteSink and ByteSource abstract interfaces. These +// interfaces represent objects that consume (ByteSink) or produce (ByteSource) +// a sequence of bytes. Using these abstract interfaces in your APIs can help +// make your code work with a variety of input and output types. +// +// This file also declares the following commonly used implementations of these +// interfaces. +// +// ByteSink: +// UncheckedArrayByteSink Writes to an array, without bounds checking +// CheckedArrayByteSink Writes to an array, with bounds checking +// GrowingArrayByteSink Allocates and writes to a growable buffer +// StringByteSink Writes to an STL string +// NullByteSink Consumes a never-ending stream of bytes +// +// ByteSource: +// ArrayByteSource Reads from an array or string/StringPiece +// LimitedByteSource Limits the number of bytes read from an + +#ifndef GOOGLE_PROTOBUF_STUBS_BYTESTREAM_H_ +#define GOOGLE_PROTOBUF_STUBS_BYTESTREAM_H_ + +#include <stddef.h> +#include <string> + +#include <google/protobuf/stubs/common.h> +#include <google/protobuf/stubs/stringpiece.h> + +#include <google/protobuf/port_def.inc> + +class CordByteSink; + +namespace google { +namespace protobuf { +namespace strings { + +// An abstract interface for an object that consumes a sequence of bytes. This +// interface offers a way to append data as well as a Flush() function. +// +// Example: +// +// string my_data; +// ... +// ByteSink* sink = ... +// sink->Append(my_data.data(), my_data.size()); +// sink->Flush(); +// +class PROTOBUF_EXPORT ByteSink { + public: + ByteSink() {} + virtual ~ByteSink() {} + + // Appends the "n" bytes starting at "bytes". + virtual void Append(const char* bytes, size_t n) = 0; + + // Flushes internal buffers. The default implementation does nothing. ByteSink + // subclasses may use internal buffers that require calling Flush() at the end + // of the stream. + virtual void Flush(); + + private: + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ByteSink); +}; + +// An abstract interface for an object that produces a fixed-size sequence of +// bytes. +// +// Example: +// +// ByteSource* source = ... +// while (source->Available() > 0) { +// StringPiece data = source->Peek(); +// ... do something with "data" ... +// source->Skip(data.length()); +// } +// +class PROTOBUF_EXPORT ByteSource { + public: + ByteSource() {} + virtual ~ByteSource() {} + + // Returns the number of bytes left to read from the source. Available() + // should decrease by N each time Skip(N) is called. Available() may not + // increase. Available() returning 0 indicates that the ByteSource is + // exhausted. + // + // Note: Size() may have been a more appropriate name as it's more + // indicative of the fixed-size nature of a ByteSource. + virtual size_t Available() const = 0; + + // Returns a StringPiece of the next contiguous region of the source. Does not + // reposition the source. The returned region is empty iff Available() == 0. + // + // The returned region is valid until the next call to Skip() or until this + // object is destroyed, whichever occurs first. + // + // The length of the returned StringPiece will be <= Available(). + virtual StringPiece Peek() = 0; + + // Skips the next n bytes. Invalidates any StringPiece returned by a previous + // call to Peek(). + // + // REQUIRES: Available() >= n + virtual void Skip(size_t n) = 0; + + // Writes the next n bytes in this ByteSource to the given ByteSink, and + // advances this ByteSource past the copied bytes. The default implementation + // of this method just copies the bytes normally, but subclasses might + // override CopyTo to optimize certain cases. + // + // REQUIRES: Available() >= n + virtual void CopyTo(ByteSink* sink, size_t n); + + private: + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ByteSource); +}; + +// +// Some commonly used implementations of ByteSink +// + +// Implementation of ByteSink that writes to an unsized byte array. No +// bounds-checking is performed--it is the caller's responsibility to ensure +// that the destination array is large enough. +// +// Example: +// +// char buf[10]; +// UncheckedArrayByteSink sink(buf); +// sink.Append("hi", 2); // OK +// sink.Append(data, 100); // WOOPS! Overflows buf[10]. +// +class PROTOBUF_EXPORT UncheckedArrayByteSink : public ByteSink { + public: + explicit UncheckedArrayByteSink(char* dest) : dest_(dest) {} + virtual void Append(const char* data, size_t n) override; + + // Returns the current output pointer so that a caller can see how many bytes + // were produced. + // + // Note: this method is not part of the ByteSink interface. + char* CurrentDestination() const { return dest_; } + + private: + char* dest_; + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(UncheckedArrayByteSink); +}; + +// Implementation of ByteSink that writes to a sized byte array. This sink will +// not write more than "capacity" bytes to outbuf. Once "capacity" bytes are +// appended, subsequent bytes will be ignored and Overflowed() will return true. +// Overflowed() does not cause a runtime error (i.e., it does not CHECK fail). +// +// Example: +// +// char buf[10]; +// CheckedArrayByteSink sink(buf, 10); +// sink.Append("hi", 2); // OK +// sink.Append(data, 100); // Will only write 8 more bytes +// +class PROTOBUF_EXPORT CheckedArrayByteSink : public ByteSink { + public: + CheckedArrayByteSink(char* outbuf, size_t capacity); + virtual void Append(const char* bytes, size_t n) override; + + // Returns the number of bytes actually written to the sink. + size_t NumberOfBytesWritten() const { return size_; } + + // Returns true if any bytes were discarded, i.e., if there was an + // attempt to write more than 'capacity' bytes. + bool Overflowed() const { return overflowed_; } + + private: + char* outbuf_; + const size_t capacity_; + size_t size_; + bool overflowed_; + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(CheckedArrayByteSink); +}; + +// Implementation of ByteSink that allocates an internal buffer (a char array) +// and expands it as needed to accommodate appended data (similar to a string), +// and allows the caller to take ownership of the internal buffer via the +// GetBuffer() method. The buffer returned from GetBuffer() must be deleted by +// the caller with delete[]. GetBuffer() also sets the internal buffer to be +// empty, and subsequent appends to the sink will create a new buffer. The +// destructor will free the internal buffer if GetBuffer() was not called. +// +// Example: +// +// GrowingArrayByteSink sink(10); +// sink.Append("hi", 2); +// sink.Append(data, n); +// const char* buf = sink.GetBuffer(); // Ownership transferred +// delete[] buf; +// +class PROTOBUF_EXPORT GrowingArrayByteSink : public strings::ByteSink { + public: + explicit GrowingArrayByteSink(size_t estimated_size); + virtual ~GrowingArrayByteSink(); + virtual void Append(const char* bytes, size_t n) override; + + // Returns the allocated buffer, and sets nbytes to its size. The caller takes + // ownership of the buffer and must delete it with delete[]. + char* GetBuffer(size_t* nbytes); + + private: + void Expand(size_t amount); + void ShrinkToFit(); + + size_t capacity_; + char* buf_; + size_t size_; + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(GrowingArrayByteSink); +}; + +// Implementation of ByteSink that appends to the given string. +// Existing contents of "dest" are not modified; new data is appended. +// +// Example: +// +// string dest = "Hello "; +// StringByteSink sink(&dest); +// sink.Append("World", 5); +// assert(dest == "Hello World"); +// +class PROTOBUF_EXPORT StringByteSink : public ByteSink { + public: + explicit StringByteSink(std::string* dest) : dest_(dest) {} + virtual void Append(const char* data, size_t n) override; + + private: + std::string* dest_; + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(StringByteSink); +}; + +// Implementation of ByteSink that discards all data. +// +// Example: +// +// NullByteSink sink; +// sink.Append(data, data.size()); // All data ignored. +// +class PROTOBUF_EXPORT NullByteSink : public ByteSink { + public: + NullByteSink() {} + void Append(const char* /*data*/, size_t /*n*/) override {} + + private: + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(NullByteSink); +}; + +// +// Some commonly used implementations of ByteSource +// + +// Implementation of ByteSource that reads from a StringPiece. +// +// Example: +// +// string data = "Hello"; +// ArrayByteSource source(data); +// assert(source.Available() == 5); +// assert(source.Peek() == "Hello"); +// +class PROTOBUF_EXPORT ArrayByteSource : public ByteSource { + public: + explicit ArrayByteSource(StringPiece s) : input_(s) {} + + virtual size_t Available() const override; + virtual StringPiece Peek() override; + virtual void Skip(size_t n) override; + + private: + StringPiece input_; + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ArrayByteSource); +}; + +// Implementation of ByteSource that wraps another ByteSource, limiting the +// number of bytes returned. +// +// The caller maintains ownership of the underlying source, and may not use the +// underlying source while using the LimitByteSource object. The underlying +// source's pointer is advanced by n bytes every time this LimitByteSource +// object is advanced by n. +// +// Example: +// +// string data = "Hello World"; +// ArrayByteSource abs(data); +// assert(abs.Available() == data.size()); +// +// LimitByteSource limit(abs, 5); +// assert(limit.Available() == 5); +// assert(limit.Peek() == "Hello"); +// +class PROTOBUF_EXPORT LimitByteSource : public ByteSource { + public: + // Returns at most "limit" bytes from "source". + LimitByteSource(ByteSource* source, size_t limit); + + virtual size_t Available() const override; + virtual StringPiece Peek() override; + virtual void Skip(size_t n) override; + + // We override CopyTo so that we can forward to the underlying source, in + // case it has an efficient implementation of CopyTo. + virtual void CopyTo(ByteSink* sink, size_t n) override; + + private: + ByteSource* source_; + size_t limit_; +}; + +} // namespace strings +} // namespace protobuf +} // namespace google + +#include <google/protobuf/port_undef.inc> + +#endif // GOOGLE_PROTOBUF_STUBS_BYTESTREAM_H_ diff --git a/toolkit/components/protobuf/src/google/protobuf/stubs/callback.h b/toolkit/components/protobuf/src/google/protobuf/stubs/callback.h new file mode 100644 index 0000000000..43d546d199 --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/stubs/callback.h @@ -0,0 +1,583 @@ +#ifndef GOOGLE_PROTOBUF_STUBS_CALLBACK_H_ +#define GOOGLE_PROTOBUF_STUBS_CALLBACK_H_ + +#include <type_traits> + +#include <google/protobuf/stubs/macros.h> + +#include <google/protobuf/port_def.inc> + +// =================================================================== +// emulates google3/base/callback.h + +namespace google { +namespace protobuf { + +// Abstract interface for a callback. When calling an RPC, you must provide +// a Closure to call when the procedure completes. See the Service interface +// in service.h. +// +// To automatically construct a Closure which calls a particular function or +// method with a particular set of parameters, use the NewCallback() function. +// Example: +// void FooDone(const FooResponse* response) { +// ... +// } +// +// void CallFoo() { +// ... +// // When done, call FooDone() and pass it a pointer to the response. +// Closure* callback = NewCallback(&FooDone, response); +// // Make the call. +// service->Foo(controller, request, response, callback); +// } +// +// Example that calls a method: +// class Handler { +// public: +// ... +// +// void FooDone(const FooResponse* response) { +// ... +// } +// +// void CallFoo() { +// ... +// // When done, call FooDone() and pass it a pointer to the response. +// Closure* callback = NewCallback(this, &Handler::FooDone, response); +// // Make the call. +// service->Foo(controller, request, response, callback); +// } +// }; +// +// Currently NewCallback() supports binding zero, one, or two arguments. +// +// Callbacks created with NewCallback() automatically delete themselves when +// executed. They should be used when a callback is to be called exactly +// once (usually the case with RPC callbacks). If a callback may be called +// a different number of times (including zero), create it with +// NewPermanentCallback() instead. You are then responsible for deleting the +// callback (using the "delete" keyword as normal). +// +// Note that NewCallback() is a bit touchy regarding argument types. Generally, +// the values you provide for the parameter bindings must exactly match the +// types accepted by the callback function. For example: +// void Foo(std::string s); +// NewCallback(&Foo, "foo"); // WON'T WORK: const char* != string +// NewCallback(&Foo, std::string("foo")); // WORKS +// Also note that the arguments cannot be references: +// void Foo(const std::string& s); +// std::string my_str; +// NewCallback(&Foo, my_str); // WON'T WORK: Can't use references. +// However, correctly-typed pointers will work just fine. +class PROTOBUF_EXPORT Closure { + public: + Closure() {} + virtual ~Closure(); + + virtual void Run() = 0; + + private: + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Closure); +}; + +template<typename R> +class ResultCallback { + public: + ResultCallback() {} + virtual ~ResultCallback() {} + + virtual R Run() = 0; + + private: + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ResultCallback); +}; + +template <typename R, typename A1> +class PROTOBUF_EXPORT ResultCallback1 { + public: + ResultCallback1() {} + virtual ~ResultCallback1() {} + + virtual R Run(A1) = 0; + + private: + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ResultCallback1); +}; + +template <typename R, typename A1, typename A2> +class PROTOBUF_EXPORT ResultCallback2 { + public: + ResultCallback2() {} + virtual ~ResultCallback2() {} + + virtual R Run(A1,A2) = 0; + + private: + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ResultCallback2); +}; + +namespace internal { + +class PROTOBUF_EXPORT FunctionClosure0 : public Closure { + public: + typedef void (*FunctionType)(); + + FunctionClosure0(FunctionType function, bool self_deleting) + : function_(function), self_deleting_(self_deleting) {} + ~FunctionClosure0(); + + void Run() override { + bool needs_delete = self_deleting_; // read in case callback deletes + function_(); + if (needs_delete) delete this; + } + + private: + FunctionType function_; + bool self_deleting_; +}; + +template <typename Class> +class MethodClosure0 : public Closure { + public: + typedef void (Class::*MethodType)(); + + MethodClosure0(Class* object, MethodType method, bool self_deleting) + : object_(object), method_(method), self_deleting_(self_deleting) {} + ~MethodClosure0() {} + + void Run() override { + bool needs_delete = self_deleting_; // read in case callback deletes + (object_->*method_)(); + if (needs_delete) delete this; + } + + private: + Class* object_; + MethodType method_; + bool self_deleting_; +}; + +template <typename Arg1> +class FunctionClosure1 : public Closure { + public: + typedef void (*FunctionType)(Arg1 arg1); + + FunctionClosure1(FunctionType function, bool self_deleting, + Arg1 arg1) + : function_(function), self_deleting_(self_deleting), + arg1_(arg1) {} + ~FunctionClosure1() {} + + void Run() override { + bool needs_delete = self_deleting_; // read in case callback deletes + function_(arg1_); + if (needs_delete) delete this; + } + + private: + FunctionType function_; + bool self_deleting_; + Arg1 arg1_; +}; + +template <typename Class, typename Arg1> +class MethodClosure1 : public Closure { + public: + typedef void (Class::*MethodType)(Arg1 arg1); + + MethodClosure1(Class* object, MethodType method, bool self_deleting, + Arg1 arg1) + : object_(object), method_(method), self_deleting_(self_deleting), + arg1_(arg1) {} + ~MethodClosure1() {} + + void Run() override { + bool needs_delete = self_deleting_; // read in case callback deletes + (object_->*method_)(arg1_); + if (needs_delete) delete this; + } + + private: + Class* object_; + MethodType method_; + bool self_deleting_; + Arg1 arg1_; +}; + +template <typename Arg1, typename Arg2> +class FunctionClosure2 : public Closure { + public: + typedef void (*FunctionType)(Arg1 arg1, Arg2 arg2); + + FunctionClosure2(FunctionType function, bool self_deleting, + Arg1 arg1, Arg2 arg2) + : function_(function), self_deleting_(self_deleting), + arg1_(arg1), arg2_(arg2) {} + ~FunctionClosure2() {} + + void Run() override { + bool needs_delete = self_deleting_; // read in case callback deletes + function_(arg1_, arg2_); + if (needs_delete) delete this; + } + + private: + FunctionType function_; + bool self_deleting_; + Arg1 arg1_; + Arg2 arg2_; +}; + +template <typename Class, typename Arg1, typename Arg2> +class MethodClosure2 : public Closure { + public: + typedef void (Class::*MethodType)(Arg1 arg1, Arg2 arg2); + + MethodClosure2(Class* object, MethodType method, bool self_deleting, + Arg1 arg1, Arg2 arg2) + : object_(object), method_(method), self_deleting_(self_deleting), + arg1_(arg1), arg2_(arg2) {} + ~MethodClosure2() {} + + void Run() override { + bool needs_delete = self_deleting_; // read in case callback deletes + (object_->*method_)(arg1_, arg2_); + if (needs_delete) delete this; + } + + private: + Class* object_; + MethodType method_; + bool self_deleting_; + Arg1 arg1_; + Arg2 arg2_; +}; + +template<typename R> +class FunctionResultCallback_0_0 : public ResultCallback<R> { + public: + typedef R (*FunctionType)(); + + FunctionResultCallback_0_0(FunctionType function, bool self_deleting) + : function_(function), self_deleting_(self_deleting) {} + ~FunctionResultCallback_0_0() {} + + R Run() override { + bool needs_delete = self_deleting_; // read in case callback deletes + R result = function_(); + if (needs_delete) delete this; + return result; + } + + private: + FunctionType function_; + bool self_deleting_; +}; + +template<typename R, typename P1> +class FunctionResultCallback_1_0 : public ResultCallback<R> { + public: + typedef R (*FunctionType)(P1); + + FunctionResultCallback_1_0(FunctionType function, bool self_deleting, + P1 p1) + : function_(function), self_deleting_(self_deleting), p1_(p1) {} + ~FunctionResultCallback_1_0() {} + + R Run() override { + bool needs_delete = self_deleting_; // read in case callback deletes + R result = function_(p1_); + if (needs_delete) delete this; + return result; + } + + private: + FunctionType function_; + bool self_deleting_; + P1 p1_; +}; + +template<typename R, typename Arg1> +class FunctionResultCallback_0_1 : public ResultCallback1<R, Arg1> { + public: + typedef R (*FunctionType)(Arg1 arg1); + + FunctionResultCallback_0_1(FunctionType function, bool self_deleting) + : function_(function), self_deleting_(self_deleting) {} + ~FunctionResultCallback_0_1() {} + + R Run(Arg1 a1) override { + bool needs_delete = self_deleting_; // read in case callback deletes + R result = function_(a1); + if (needs_delete) delete this; + return result; + } + + private: + FunctionType function_; + bool self_deleting_; +}; + +template<typename R, typename P1, typename A1> +class FunctionResultCallback_1_1 : public ResultCallback1<R, A1> { + public: + typedef R (*FunctionType)(P1, A1); + + FunctionResultCallback_1_1(FunctionType function, bool self_deleting, + P1 p1) + : function_(function), self_deleting_(self_deleting), p1_(p1) {} + ~FunctionResultCallback_1_1() {} + + R Run(A1 a1) override { + bool needs_delete = self_deleting_; // read in case callback deletes + R result = function_(p1_, a1); + if (needs_delete) delete this; + return result; + } + + private: + FunctionType function_; + bool self_deleting_; + P1 p1_; +}; + +template <typename T> +struct InternalConstRef { + typedef typename std::remove_reference<T>::type base_type; + typedef const base_type& type; +}; + +template<typename R, typename T> +class MethodResultCallback_0_0 : public ResultCallback<R> { + public: + typedef R (T::*MethodType)(); + MethodResultCallback_0_0(T* object, MethodType method, bool self_deleting) + : object_(object), + method_(method), + self_deleting_(self_deleting) {} + ~MethodResultCallback_0_0() {} + + R Run() { + bool needs_delete = self_deleting_; + R result = (object_->*method_)(); + if (needs_delete) delete this; + return result; + } + + private: + T* object_; + MethodType method_; + bool self_deleting_; +}; + +template <typename R, typename T, typename P1, typename P2, typename P3, + typename P4, typename P5, typename P6, typename A1, typename A2> +class MethodResultCallback_6_2 : public ResultCallback2<R, A1, A2> { + public: + typedef R (T::*MethodType)(P1, P2, P3, P4, P5, P6, A1, A2); + MethodResultCallback_6_2(T* object, MethodType method, bool self_deleting, + P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6) + : object_(object), + method_(method), + self_deleting_(self_deleting), + p1_(p1), + p2_(p2), + p3_(p3), + p4_(p4), + p5_(p5), + p6_(p6) {} + ~MethodResultCallback_6_2() {} + + R Run(A1 a1, A2 a2) override { + bool needs_delete = self_deleting_; + R result = (object_->*method_)(p1_, p2_, p3_, p4_, p5_, p6_, a1, a2); + if (needs_delete) delete this; + return result; + } + + private: + T* object_; + MethodType method_; + bool self_deleting_; + typename std::remove_reference<P1>::type p1_; + typename std::remove_reference<P2>::type p2_; + typename std::remove_reference<P3>::type p3_; + typename std::remove_reference<P4>::type p4_; + typename std::remove_reference<P5>::type p5_; + typename std::remove_reference<P6>::type p6_; +}; + +} // namespace internal + +// See Closure. +inline Closure* NewCallback(void (*function)()) { + return new internal::FunctionClosure0(function, true); +} + +// See Closure. +inline Closure* NewPermanentCallback(void (*function)()) { + return new internal::FunctionClosure0(function, false); +} + +// See Closure. +template <typename Class> +inline Closure* NewCallback(Class* object, void (Class::*method)()) { + return new internal::MethodClosure0<Class>(object, method, true); +} + +// See Closure. +template <typename Class> +inline Closure* NewPermanentCallback(Class* object, void (Class::*method)()) { + return new internal::MethodClosure0<Class>(object, method, false); +} + +// See Closure. +template <typename Arg1> +inline Closure* NewCallback(void (*function)(Arg1), + Arg1 arg1) { + return new internal::FunctionClosure1<Arg1>(function, true, arg1); +} + +// See Closure. +template <typename Arg1> +inline Closure* NewPermanentCallback(void (*function)(Arg1), + Arg1 arg1) { + return new internal::FunctionClosure1<Arg1>(function, false, arg1); +} + +// See Closure. +template <typename Class, typename Arg1> +inline Closure* NewCallback(Class* object, void (Class::*method)(Arg1), + Arg1 arg1) { + return new internal::MethodClosure1<Class, Arg1>(object, method, true, arg1); +} + +// See Closure. +template <typename Class, typename Arg1> +inline Closure* NewPermanentCallback(Class* object, void (Class::*method)(Arg1), + Arg1 arg1) { + return new internal::MethodClosure1<Class, Arg1>(object, method, false, arg1); +} + +// See Closure. +template <typename Arg1, typename Arg2> +inline Closure* NewCallback(void (*function)(Arg1, Arg2), + Arg1 arg1, Arg2 arg2) { + return new internal::FunctionClosure2<Arg1, Arg2>( + function, true, arg1, arg2); +} + +// See Closure. +template <typename Arg1, typename Arg2> +inline Closure* NewPermanentCallback(void (*function)(Arg1, Arg2), + Arg1 arg1, Arg2 arg2) { + return new internal::FunctionClosure2<Arg1, Arg2>( + function, false, arg1, arg2); +} + +// See Closure. +template <typename Class, typename Arg1, typename Arg2> +inline Closure* NewCallback(Class* object, void (Class::*method)(Arg1, Arg2), + Arg1 arg1, Arg2 arg2) { + return new internal::MethodClosure2<Class, Arg1, Arg2>( + object, method, true, arg1, arg2); +} + +// See Closure. +template <typename Class, typename Arg1, typename Arg2> +inline Closure* NewPermanentCallback( + Class* object, void (Class::*method)(Arg1, Arg2), + Arg1 arg1, Arg2 arg2) { + return new internal::MethodClosure2<Class, Arg1, Arg2>( + object, method, false, arg1, arg2); +} + +// See ResultCallback +template<typename R> +inline ResultCallback<R>* NewCallback(R (*function)()) { + return new internal::FunctionResultCallback_0_0<R>(function, true); +} + +// See ResultCallback +template<typename R> +inline ResultCallback<R>* NewPermanentCallback(R (*function)()) { + return new internal::FunctionResultCallback_0_0<R>(function, false); +} + +// See ResultCallback +template<typename R, typename P1> +inline ResultCallback<R>* NewCallback(R (*function)(P1), P1 p1) { + return new internal::FunctionResultCallback_1_0<R, P1>( + function, true, p1); +} + +// See ResultCallback +template<typename R, typename P1> +inline ResultCallback<R>* NewPermanentCallback( + R (*function)(P1), P1 p1) { + return new internal::FunctionResultCallback_1_0<R, P1>( + function, false, p1); +} + +// See ResultCallback1 +template<typename R, typename A1> +inline ResultCallback1<R, A1>* NewCallback(R (*function)(A1)) { + return new internal::FunctionResultCallback_0_1<R, A1>(function, true); +} + +// See ResultCallback1 +template<typename R, typename A1> +inline ResultCallback1<R, A1>* NewPermanentCallback(R (*function)(A1)) { + return new internal::FunctionResultCallback_0_1<R, A1>(function, false); +} + +// See ResultCallback1 +template<typename R, typename P1, typename A1> +inline ResultCallback1<R, A1>* NewCallback(R (*function)(P1, A1), P1 p1) { + return new internal::FunctionResultCallback_1_1<R, P1, A1>( + function, true, p1); +} + +// See ResultCallback1 +template<typename R, typename P1, typename A1> +inline ResultCallback1<R, A1>* NewPermanentCallback( + R (*function)(P1, A1), P1 p1) { + return new internal::FunctionResultCallback_1_1<R, P1, A1>( + function, false, p1); +} + +// See MethodResultCallback_0_0 +template <typename R, typename T1, typename T2> +inline ResultCallback<R>* NewPermanentCallback( + T1* object, R (T2::*function)()) { + return new internal::MethodResultCallback_0_0<R, T1>(object, function, false); +} + +// See MethodResultCallback_6_2 +template <typename R, typename T, typename P1, typename P2, typename P3, + typename P4, typename P5, typename P6, typename A1, typename A2> +inline ResultCallback2<R, A1, A2>* NewPermanentCallback( + T* object, R (T::*function)(P1, P2, P3, P4, P5, P6, A1, A2), + typename internal::InternalConstRef<P1>::type p1, + typename internal::InternalConstRef<P2>::type p2, + typename internal::InternalConstRef<P3>::type p3, + typename internal::InternalConstRef<P4>::type p4, + typename internal::InternalConstRef<P5>::type p5, + typename internal::InternalConstRef<P6>::type p6) { + return new internal::MethodResultCallback_6_2<R, T, P1, P2, P3, P4, P5, P6, + A1, A2>(object, function, false, + p1, p2, p3, p4, p5, p6); +} + +// A function which does nothing. Useful for creating no-op callbacks, e.g.: +// Closure* nothing = NewCallback(&DoNothing); +void PROTOBUF_EXPORT DoNothing(); + +} // namespace protobuf +} // namespace google + +#include <google/protobuf/port_undef.inc> + +#endif // GOOGLE_PROTOBUF_STUBS_CALLBACK_H_ diff --git a/toolkit/components/protobuf/src/google/protobuf/stubs/casts.h b/toolkit/components/protobuf/src/google/protobuf/stubs/casts.h new file mode 100644 index 0000000000..ad29dac1f8 --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/stubs/casts.h @@ -0,0 +1,138 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2014 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. + +#ifndef GOOGLE_PROTOBUF_CASTS_H__ +#define GOOGLE_PROTOBUF_CASTS_H__ + +#include <google/protobuf/stubs/common.h> + +#include <google/protobuf/port_def.inc> +#include <type_traits> + +namespace google { +namespace protobuf { +namespace internal { + +// Use implicit_cast as a safe version of static_cast or const_cast +// for upcasting in the type hierarchy (i.e. casting a pointer to Foo +// to a pointer to SuperclassOfFoo or casting a pointer to Foo to +// a const pointer to Foo). +// When you use implicit_cast, the compiler checks that the cast is safe. +// Such explicit implicit_casts are necessary in surprisingly many +// situations where C++ demands an exact type match instead of an +// argument type convertible to a target type. +// +// The From type can be inferred, so the preferred syntax for using +// implicit_cast is the same as for static_cast etc.: +// +// implicit_cast<ToType>(expr) +// +// implicit_cast would have been part of the C++ standard library, +// but the proposal was submitted too late. It will probably make +// its way into the language in the future. +template<typename To, typename From> +inline To implicit_cast(From const &f) { + return f; +} + +// When you upcast (that is, cast a pointer from type Foo to type +// SuperclassOfFoo), it's fine to use implicit_cast<>, since upcasts +// always succeed. When you downcast (that is, cast a pointer from +// type Foo to type SubclassOfFoo), static_cast<> isn't safe, because +// how do you know the pointer is really of type SubclassOfFoo? It +// could be a bare Foo, or of type DifferentSubclassOfFoo. Thus, +// when you downcast, you should use this macro. In debug mode, we +// use dynamic_cast<> to double-check the downcast is legal (we die +// if it's not). In normal mode, we do the efficient static_cast<> +// instead. Thus, it's important to test in debug mode to make sure +// the cast is legal! +// This is the only place in the code we should use dynamic_cast<>. +// In particular, you SHOULDN'T be using dynamic_cast<> in order to +// do RTTI (eg code like this: +// if (dynamic_cast<Subclass1>(foo)) HandleASubclass1Object(foo); +// if (dynamic_cast<Subclass2>(foo)) HandleASubclass2Object(foo); +// You should design the code some other way not to need this. + +template<typename To, typename From> // use like this: down_cast<T*>(foo); +inline To down_cast(From* f) { // so we only accept pointers + // Ensures that To is a sub-type of From *. This test is here only + // for compile-time type checking, and has no overhead in an + // optimized build at run-time, as it will be optimized away + // completely. + if (false) { + implicit_cast<From*, To>(0); + } + +#if !defined(NDEBUG) && PROTOBUF_RTTI + assert(f == nullptr || dynamic_cast<To>(f) != nullptr); // RTTI: debug mode only! +#endif + return static_cast<To>(f); +} + +template<typename To, typename From> // use like this: down_cast<T&>(foo); +inline To down_cast(From& f) { + typedef typename std::remove_reference<To>::type* ToAsPointer; + // Ensures that To is a sub-type of From *. This test is here only + // for compile-time type checking, and has no overhead in an + // optimized build at run-time, as it will be optimized away + // completely. + if (false) { + implicit_cast<From*, ToAsPointer>(0); + } + +#if !defined(NDEBUG) && PROTOBUF_RTTI + // RTTI: debug mode only! + assert(dynamic_cast<ToAsPointer>(&f) != nullptr); +#endif + return *static_cast<ToAsPointer>(&f); +} + +template<typename To, typename From> +inline To bit_cast(const From& from) { + static_assert(sizeof(From) == sizeof(To), "bit_cast_with_different_sizes"); + To dest; + memcpy(&dest, &from, sizeof(dest)); + return dest; +} + +} // namespace internal + +// We made these internal so that they would show up as such in the docs, +// but we don't want to stick "internal::" in front of them everywhere. +using internal::implicit_cast; +using internal::down_cast; +using internal::bit_cast; + +} // namespace protobuf +} // namespace google + +#include <google/protobuf/port_undef.inc> + +#endif // GOOGLE_PROTOBUF_CASTS_H__ diff --git a/toolkit/components/protobuf/src/google/protobuf/stubs/common.cc b/toolkit/components/protobuf/src/google/protobuf/stubs/common.cc new file mode 100644 index 0000000000..e0a807ffbb --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/stubs/common.cc @@ -0,0 +1,324 @@ +// 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. + +// Author: kenton@google.com (Kenton Varda) + +#include <google/protobuf/stubs/common.h> + +#include <atomic> +#include <errno.h> +#include <sstream> +#include <stdio.h> +#include <vector> + +#ifdef _WIN32 +#ifndef WIN32_LEAN_AND_MEAN +#define WIN32_LEAN_AND_MEAN // We only need minimal includes +#endif +#include <windows.h> +#define snprintf _snprintf // see comment in strutil.cc +#endif +#if defined(__ANDROID__) +#include <android/log.h> +#endif + +#include <google/protobuf/stubs/callback.h> +#include <google/protobuf/stubs/logging.h> +#include <google/protobuf/stubs/once.h> +#include <google/protobuf/stubs/status.h> +#include <google/protobuf/stubs/stringpiece.h> +#include <google/protobuf/stubs/strutil.h> +#include <google/protobuf/stubs/int128.h> + +#include <google/protobuf/port_def.inc> + +namespace google { +namespace protobuf { + +namespace internal { + +void VerifyVersion(int headerVersion, + int minLibraryVersion, + const char* filename) { + if (GOOGLE_PROTOBUF_VERSION < minLibraryVersion) { + // Library is too old for headers. + GOOGLE_LOG(FATAL) + << "This program requires version " << VersionString(minLibraryVersion) + << " of the Protocol Buffer runtime library, but the installed version " + "is " << VersionString(GOOGLE_PROTOBUF_VERSION) << ". Please update " + "your library. If you compiled the program yourself, make sure that " + "your headers are from the same version of Protocol Buffers as your " + "link-time library. (Version verification failed in \"" + << filename << "\".)"; + } + if (headerVersion < kMinHeaderVersionForLibrary) { + // Headers are too old for library. + GOOGLE_LOG(FATAL) + << "This program was compiled against version " + << VersionString(headerVersion) << " of the Protocol Buffer runtime " + "library, which is not compatible with the installed version (" + << VersionString(GOOGLE_PROTOBUF_VERSION) << "). Contact the program " + "author for an update. If you compiled the program yourself, make " + "sure that your headers are from the same version of Protocol Buffers " + "as your link-time library. (Version verification failed in \"" + << filename << "\".)"; + } +} + +std::string VersionString(int version) { + int major = version / 1000000; + int minor = (version / 1000) % 1000; + int micro = version % 1000; + + // 128 bytes should always be enough, but we use snprintf() anyway to be + // safe. + char buffer[128]; + snprintf(buffer, sizeof(buffer), "%d.%d.%d", major, minor, micro); + + // Guard against broken MSVC snprintf(). + buffer[sizeof(buffer)-1] = '\0'; + + return buffer; +} + +} // namespace internal + +// =================================================================== +// emulates google3/base/logging.cc + +// If the minimum logging level is not set, we default to logging messages for +// all levels. +#ifndef GOOGLE_PROTOBUF_MIN_LOG_LEVEL +#define GOOGLE_PROTOBUF_MIN_LOG_LEVEL LOGLEVEL_INFO +#endif + +namespace internal { + +#if defined(__ANDROID__) +inline void DefaultLogHandler(LogLevel level, const char* filename, int line, + const std::string& message) { + if (level < GOOGLE_PROTOBUF_MIN_LOG_LEVEL) { + return; + } + static const char* level_names[] = {"INFO", "WARNING", "ERROR", "FATAL"}; + + static const int android_log_levels[] = { + ANDROID_LOG_INFO, // LOG(INFO), + ANDROID_LOG_WARN, // LOG(WARNING) + ANDROID_LOG_ERROR, // LOG(ERROR) + ANDROID_LOG_FATAL, // LOG(FATAL) + }; + + // Bound the logging level. + const int android_log_level = android_log_levels[level]; + ::std::ostringstream ostr; + ostr << "[libprotobuf " << level_names[level] << " " << filename << ":" + << line << "] " << message.c_str(); + + // Output the log string the Android log at the appropriate level. + __android_log_write(android_log_level, "libprotobuf-native", + ostr.str().c_str()); + // Also output to std::cerr. + fprintf(stderr, "%s", ostr.str().c_str()); + fflush(stderr); + + // Indicate termination if needed. + if (android_log_level == ANDROID_LOG_FATAL) { + __android_log_write(ANDROID_LOG_FATAL, "libprotobuf-native", + "terminating.\n"); + } +} + +#else +void DefaultLogHandler(LogLevel level, const char* filename, int line, + const std::string& message) { + if (level < GOOGLE_PROTOBUF_MIN_LOG_LEVEL) { + return; + } + static const char* level_names[] = { "INFO", "WARNING", "ERROR", "FATAL" }; + + // We use fprintf() instead of cerr because we want this to work at static + // initialization time. + fprintf(stderr, "[libprotobuf %s %s:%d] %s\n", + level_names[level], filename, line, message.c_str()); + fflush(stderr); // Needed on MSVC. +} +#endif + +void NullLogHandler(LogLevel /* level */, const char* /* filename */, + int /* line */, const std::string& /* message */) { + // Nothing. +} + +static LogHandler* log_handler_ = &DefaultLogHandler; +static std::atomic<int> log_silencer_count_ = ATOMIC_VAR_INIT(0); + +LogMessage& LogMessage::operator<<(const std::string& value) { + message_ += value; + return *this; +} + +LogMessage& LogMessage::operator<<(const char* value) { + message_ += value; + return *this; +} + +LogMessage& LogMessage::operator<<(const StringPiece& value) { + message_ += value.ToString(); + return *this; +} + +LogMessage& LogMessage::operator<<(const util::Status& status) { + message_ += status.ToString(); + return *this; +} + +LogMessage& LogMessage::operator<<(const uint128& value) { + std::ostringstream str; + str << value; + message_ += str.str(); + return *this; +} + +LogMessage& LogMessage::operator<<(char value) { + return *this << StringPiece(&value, 1); +} + +LogMessage& LogMessage::operator<<(void* value) { + StrAppend(&message_, strings::Hex(reinterpret_cast<uintptr_t>(value))); + return *this; +} + +#undef DECLARE_STREAM_OPERATOR +#define DECLARE_STREAM_OPERATOR(TYPE) \ + LogMessage& LogMessage::operator<<(TYPE value) { \ + StrAppend(&message_, value); \ + return *this; \ + } + +DECLARE_STREAM_OPERATOR(int) +DECLARE_STREAM_OPERATOR(unsigned int) +DECLARE_STREAM_OPERATOR(long) // NOLINT(runtime/int) +DECLARE_STREAM_OPERATOR(unsigned long) // NOLINT(runtime/int) +DECLARE_STREAM_OPERATOR(double) +DECLARE_STREAM_OPERATOR(long long) // NOLINT(runtime/int) +DECLARE_STREAM_OPERATOR(unsigned long long) // NOLINT(runtime/int) +#undef DECLARE_STREAM_OPERATOR + +LogMessage::LogMessage(LogLevel level, const char* filename, int line) + : level_(level), filename_(filename), line_(line) {} +LogMessage::~LogMessage() {} + +void LogMessage::Finish() { + bool suppress = false; + + if (level_ != LOGLEVEL_FATAL) { + suppress = log_silencer_count_ > 0; + } + + if (!suppress) { + log_handler_(level_, filename_, line_, message_); + } + + if (level_ == LOGLEVEL_FATAL) { +#if PROTOBUF_USE_EXCEPTIONS + throw FatalException(filename_, line_, message_); +#else + abort(); +#endif + } +} + +void LogFinisher::operator=(LogMessage& other) { + other.Finish(); +} + +} // namespace internal + +LogHandler* SetLogHandler(LogHandler* new_func) { + LogHandler* old = internal::log_handler_; + if (old == &internal::NullLogHandler) { + old = nullptr; + } + if (new_func == nullptr) { + internal::log_handler_ = &internal::NullLogHandler; + } else { + internal::log_handler_ = new_func; + } + return old; +} + +LogSilencer::LogSilencer() { + ++internal::log_silencer_count_; +}; + +LogSilencer::~LogSilencer() { + --internal::log_silencer_count_; +}; + +// =================================================================== +// emulates google3/base/callback.cc + +Closure::~Closure() {} + +namespace internal { FunctionClosure0::~FunctionClosure0() {} } + +void DoNothing() {} + +// =================================================================== +// emulates google3/util/endian/endian.h +// +// TODO(xiaofeng): PROTOBUF_LITTLE_ENDIAN is unfortunately defined in +// google/protobuf/io/coded_stream.h and therefore can not be used here. +// Maybe move that macro definition here in the future. +uint32_t ghtonl(uint32_t x) { + union { + uint32_t result; + uint8_t result_array[4]; + }; + result_array[0] = static_cast<uint8_t>(x >> 24); + result_array[1] = static_cast<uint8_t>((x >> 16) & 0xFF); + result_array[2] = static_cast<uint8_t>((x >> 8) & 0xFF); + result_array[3] = static_cast<uint8_t>(x & 0xFF); + return result; +} + +#if PROTOBUF_USE_EXCEPTIONS +FatalException::~FatalException() throw() {} + +const char* FatalException::what() const throw() { + return message_.c_str(); +} +#endif + +} // namespace protobuf +} // namespace google + +#include <google/protobuf/port_undef.inc> diff --git a/toolkit/components/protobuf/src/google/protobuf/stubs/common.h b/toolkit/components/protobuf/src/google/protobuf/stubs/common.h new file mode 100644 index 0000000000..58739784db --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/stubs/common.h @@ -0,0 +1,196 @@ +// 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. + +// Author: kenton@google.com (Kenton Varda) and others +// +// Contains basic types and utilities used by the rest of the library. + +#ifndef GOOGLE_PROTOBUF_COMMON_H__ +#define GOOGLE_PROTOBUF_COMMON_H__ + +#include <algorithm> +#include <map> +#include <memory> +#include <set> +#include <string> +#include <vector> + +#include <google/protobuf/stubs/macros.h> +#include <google/protobuf/stubs/platform_macros.h> +#include <google/protobuf/stubs/port.h> +#include <google/protobuf/stubs/stringpiece.h> + +#ifndef PROTOBUF_USE_EXCEPTIONS +#if defined(_MSC_VER) && defined(_CPPUNWIND) + #define PROTOBUF_USE_EXCEPTIONS 1 +#elif defined(__EXCEPTIONS) + #define PROTOBUF_USE_EXCEPTIONS 1 +#else + #define PROTOBUF_USE_EXCEPTIONS 0 +#endif +#endif + +#if PROTOBUF_USE_EXCEPTIONS +#include <exception> +#endif +#if defined(__APPLE__) +#include <TargetConditionals.h> // for TARGET_OS_IPHONE +#endif + +#if defined(__ANDROID__) || defined(GOOGLE_PROTOBUF_OS_ANDROID) || (defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE) || defined(GOOGLE_PROTOBUF_OS_IPHONE) +#include <pthread.h> +#endif + +#include <google/protobuf/port_def.inc> + +namespace std {} + +namespace google { +namespace protobuf { +namespace internal { + +// Some of these constants are macros rather than const ints so that they can +// be used in #if directives. + +// The current version, represented as a single integer to make comparison +// easier: major * 10^6 + minor * 10^3 + micro +#define GOOGLE_PROTOBUF_VERSION 3021006 + +// A suffix string for alpha, beta or rc releases. Empty for stable releases. +#define GOOGLE_PROTOBUF_VERSION_SUFFIX "" + +// The minimum header version which works with the current version of +// the library. This constant should only be used by protoc's C++ code +// generator. +static const int kMinHeaderVersionForLibrary = 3021000; + +// The minimum protoc version which works with the current version of the +// headers. +#define GOOGLE_PROTOBUF_MIN_PROTOC_VERSION 3021000 + +// The minimum header version which works with the current version of +// protoc. This constant should only be used in VerifyVersion(). +static const int kMinHeaderVersionForProtoc = 3021000; + +// Verifies that the headers and libraries are compatible. Use the macro +// below to call this. +void PROTOBUF_EXPORT VerifyVersion(int headerVersion, int minLibraryVersion, + const char* filename); + +// Converts a numeric version number to a string. +std::string PROTOBUF_EXPORT VersionString(int version); + +} // namespace internal + +// Place this macro in your main() function (or somewhere before you attempt +// to use the protobuf library) to verify that the version you link against +// matches the headers you compiled against. If a version mismatch is +// detected, the process will abort. +#define GOOGLE_PROTOBUF_VERIFY_VERSION \ + ::google::protobuf::internal::VerifyVersion( \ + GOOGLE_PROTOBUF_VERSION, GOOGLE_PROTOBUF_MIN_LIBRARY_VERSION, \ + __FILE__) + + +// =================================================================== +// from google3/util/utf8/public/unilib.h + +namespace internal { + +// Checks if the buffer contains structurally-valid UTF-8. Implemented in +// structurally_valid.cc. +PROTOBUF_EXPORT bool IsStructurallyValidUTF8(const char* buf, int len); + +inline bool IsStructurallyValidUTF8(StringPiece str) { + return IsStructurallyValidUTF8(str.data(), static_cast<int>(str.length())); +} + +// Returns initial number of bytes of structurally valid UTF-8. +PROTOBUF_EXPORT int UTF8SpnStructurallyValid(StringPiece str); + +// Coerce UTF-8 byte string in src_str to be +// a structurally-valid equal-length string by selectively +// overwriting illegal bytes with replace_char (typically ' ' or '?'). +// replace_char must be legal printable 7-bit Ascii 0x20..0x7e. +// src_str is read-only. +// +// Returns pointer to output buffer, src_str.data() if no changes were made, +// or idst if some bytes were changed. idst is allocated by the caller +// and must be at least as big as src_str +// +// Optimized for: all structurally valid and no byte copying is done. +// +PROTOBUF_EXPORT char* UTF8CoerceToStructurallyValid(StringPiece str, char* dst, + char replace_char); + +} // namespace internal + +// This lives in message_lite.h now, but we leave this here for any users that +// #include common.h and not message_lite.h. +PROTOBUF_EXPORT void ShutdownProtobufLibrary(); + +namespace internal { + +// Strongly references the given variable such that the linker will be forced +// to pull in this variable's translation unit. +template <typename T> +void StrongReference(const T& var) { + auto volatile unused = &var; + (void)&unused; // Use address to avoid an extra load of "unused". +} + +} // namespace internal + +#if PROTOBUF_USE_EXCEPTIONS +class FatalException : public std::exception { + public: + FatalException(const char* filename, int line, const std::string& message) + : filename_(filename), line_(line), message_(message) {} + virtual ~FatalException() throw(); + + const char* what() const throw() override; + + const char* filename() const { return filename_; } + int line() const { return line_; } + const std::string& message() const { return message_; } + + private: + const char* filename_; + const int line_; + const std::string message_; +}; +#endif + +} // namespace protobuf +} // namespace google + +#include <google/protobuf/port_undef.inc> + +#endif // GOOGLE_PROTOBUF_COMMON_H__ diff --git a/toolkit/components/protobuf/src/google/protobuf/stubs/hash.h b/toolkit/components/protobuf/src/google/protobuf/stubs/hash.h new file mode 100644 index 0000000000..a7ec068074 --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/stubs/hash.h @@ -0,0 +1,114 @@ +// 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. + +// Author: kenton@google.com (Kenton Varda) + +#ifndef GOOGLE_PROTOBUF_STUBS_HASH_H__ +#define GOOGLE_PROTOBUF_STUBS_HASH_H__ + +#include <cstring> +#include <string> +#include <unordered_map> +#include <unordered_set> + +# define GOOGLE_PROTOBUF_HASH_NAMESPACE_DECLARATION_START \ + namespace google { \ + namespace protobuf { +# define GOOGLE_PROTOBUF_HASH_NAMESPACE_DECLARATION_END }} + +namespace google { +namespace protobuf { + +template <typename Key> +struct hash : public std::hash<Key> {}; + +template <typename Key> +struct hash<const Key*> { + inline size_t operator()(const Key* key) const { + return reinterpret_cast<size_t>(key); + } +}; + +// Unlike the old SGI version, the TR1 "hash" does not special-case char*. So, +// we go ahead and provide our own implementation. +template <> +struct hash<const char*> { + inline size_t operator()(const char* str) const { + size_t result = 0; + for (; *str != '\0'; str++) { + result = 5 * result + static_cast<size_t>(*str); + } + return result; + } +}; + +template<> +struct hash<bool> { + size_t operator()(bool x) const { + return static_cast<size_t>(x); + } +}; + +template <> +struct hash<std::string> { + inline size_t operator()(const std::string& key) const { + return hash<const char*>()(key.c_str()); + } + + static const size_t bucket_size = 4; + static const size_t min_buckets = 8; + inline bool operator()(const std::string& a, const std::string& b) const { + return a < b; + } +}; + +template <typename First, typename Second> +struct hash<std::pair<First, Second> > { + inline size_t operator()(const std::pair<First, Second>& key) const { + size_t first_hash = hash<First>()(key.first); + size_t second_hash = hash<Second>()(key.second); + + // FIXME(kenton): What is the best way to compute this hash? I have + // no idea! This seems a bit better than an XOR. + return first_hash * ((1 << 16) - 1) + second_hash; + } + + static const size_t bucket_size = 4; + static const size_t min_buckets = 8; + inline bool operator()(const std::pair<First, Second>& a, + const std::pair<First, Second>& b) const { + return a < b; + } +}; + +} // namespace protobuf +} // namespace google + +#endif // GOOGLE_PROTOBUF_STUBS_HASH_H__ diff --git a/toolkit/components/protobuf/src/google/protobuf/stubs/int128.cc b/toolkit/components/protobuf/src/google/protobuf/stubs/int128.cc new file mode 100644 index 0000000000..a151cfb554 --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/stubs/int128.cc @@ -0,0 +1,193 @@ +// 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. + +#include <google/protobuf/stubs/int128.h> + +#include <iomanip> +#include <ostream> // NOLINT(readability/streams) +#include <sstream> + +#include <google/protobuf/stubs/logging.h> + +#include <google/protobuf/port_def.inc> + +namespace google { +namespace protobuf { + +const uint128_pod kuint128max = {uint64_t{0xFFFFFFFFFFFFFFFFu}, + uint64_t{0xFFFFFFFFFFFFFFFFu}}; + +// Returns the 0-based position of the last set bit (i.e., most significant bit) +// in the given uint64. The argument may not be 0. +// +// For example: +// Given: 5 (decimal) == 101 (binary) +// Returns: 2 +#define STEP(T, n, pos, sh) \ + do { \ + if ((n) >= (static_cast<T>(1) << (sh))) { \ + (n) = (n) >> (sh); \ + (pos) |= (sh); \ + } \ + } while (0) +static inline int Fls64(uint64_t n) { + GOOGLE_DCHECK_NE(0, n); + int pos = 0; + STEP(uint64_t, n, pos, 0x20); + uint32_t n32 = n; + STEP(uint32_t, n32, pos, 0x10); + STEP(uint32_t, n32, pos, 0x08); + STEP(uint32_t, n32, pos, 0x04); + return pos + ((uint64_t{0x3333333322221100u} >> (n32 << 2)) & 0x3); +} +#undef STEP + +// Like Fls64() above, but returns the 0-based position of the last set bit +// (i.e., most significant bit) in the given uint128. The argument may not be 0. +static inline int Fls128(uint128 n) { + if (uint64_t hi = Uint128High64(n)) { + return Fls64(hi) + 64; + } + return Fls64(Uint128Low64(n)); +} + +void uint128::DivModImpl(uint128 dividend, uint128 divisor, + uint128* quotient_ret, uint128* remainder_ret) { + if (divisor == 0) { + GOOGLE_LOG(FATAL) << "Division or mod by zero: dividend.hi=" << dividend.hi_ + << ", lo=" << dividend.lo_; + } else if (dividend < divisor) { + *quotient_ret = 0; + *remainder_ret = dividend; + return; + } else { + int dividend_bit_length = Fls128(dividend); + int divisor_bit_length = Fls128(divisor); + int difference = dividend_bit_length - divisor_bit_length; + uint128 quotient = 0; + while (difference >= 0) { + quotient <<= 1; + uint128 shifted_divisor = divisor << difference; + if (shifted_divisor <= dividend) { + dividend -= shifted_divisor; + quotient += 1; + } + difference -= 1; + } + //record the final quotient and remainder + *quotient_ret = quotient; + *remainder_ret = dividend; + } +} + + +uint128& uint128::operator/=(const uint128& divisor) { + uint128 quotient = 0; + uint128 remainder = 0; + DivModImpl(*this, divisor, "ient, &remainder); + *this = quotient; + return *this; +} +uint128& uint128::operator%=(const uint128& divisor) { + uint128 quotient = 0; + uint128 remainder = 0; + DivModImpl(*this, divisor, "ient, &remainder); + *this = remainder; + return *this; +} + +std::ostream& operator<<(std::ostream& o, const uint128& b) { + std::ios_base::fmtflags flags = o.flags(); + + // Select a divisor which is the largest power of the base < 2^64. + uint128 div; + std::streamsize div_base_log; + switch (flags & std::ios::basefield) { + case std::ios::hex: + div = + static_cast<uint64_t>(uint64_t{0x1000000000000000u}); // 16^15 + div_base_log = 15; + break; + case std::ios::oct: + div = static_cast<uint64_t>( + uint64_t{01000000000000000000000u}); // 8^21 + div_base_log = 21; + break; + default: // std::ios::dec + div = static_cast<uint64_t>( + uint64_t{10000000000000000000u}); // 10^19 + div_base_log = 19; + break; + } + + // Now piece together the uint128 representation from three chunks of + // the original value, each less than "div" and therefore representable + // as a uint64. + std::ostringstream os; + std::ios_base::fmtflags copy_mask = + std::ios::basefield | std::ios::showbase | std::ios::uppercase; + os.setf(flags & copy_mask, copy_mask); + uint128 high = b; + uint128 low; + uint128::DivModImpl(high, div, &high, &low); + uint128 mid; + uint128::DivModImpl(high, div, &high, &mid); + if (high.lo_ != 0) { + os << high.lo_; + os << std::noshowbase << std::setfill('0') << std::setw(div_base_log); + os << mid.lo_; + os << std::setw(div_base_log); + } else if (mid.lo_ != 0) { + os << mid.lo_; + os << std::noshowbase << std::setfill('0') << std::setw(div_base_log); + } + os << low.lo_; + std::string rep = os.str(); + + // Add the requisite padding. + std::streamsize width = o.width(0); + auto repSize = static_cast<std::streamsize>(rep.size()); + if (width > repSize) { + if ((flags & std::ios::adjustfield) == std::ios::left) { + rep.append(width - repSize, o.fill()); + } else { + rep.insert(static_cast<std::string::size_type>(0), width - repSize, + o.fill()); + } + } + + // Stream the final representation in a single "<<" call. + return o << rep; +} + +} // namespace protobuf +} // namespace google + +#include <google/protobuf/port_undef.inc> // NOLINT diff --git a/toolkit/components/protobuf/src/google/protobuf/stubs/int128.h b/toolkit/components/protobuf/src/google/protobuf/stubs/int128.h new file mode 100644 index 0000000000..92d7bdffa4 --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/stubs/int128.h @@ -0,0 +1,387 @@ +// 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. +#ifndef GOOGLE_PROTOBUF_STUBS_INT128_H_ +#define GOOGLE_PROTOBUF_STUBS_INT128_H_ + +#include <google/protobuf/stubs/common.h> + +#include <iosfwd> + +#include <google/protobuf/port_def.inc> + +namespace google { +namespace protobuf { + +struct uint128_pod; + +// TODO(xiaofeng): Define GOOGLE_PROTOBUF_HAS_CONSTEXPR when constexpr is +// available. +#ifdef GOOGLE_PROTOBUF_HAS_CONSTEXPR +# define UINT128_CONSTEXPR constexpr +#else +# define UINT128_CONSTEXPR +#endif + +// An unsigned 128-bit integer type. Thread-compatible. +class PROTOBUF_EXPORT uint128 { + public: + UINT128_CONSTEXPR uint128(); // Sets to 0, but don't trust on this behavior. + UINT128_CONSTEXPR uint128(uint64_t top, uint64_t bottom); +#ifndef SWIG + UINT128_CONSTEXPR uint128(int bottom); + UINT128_CONSTEXPR uint128(uint32_t bottom); // Top 96 bits = 0 +#endif + UINT128_CONSTEXPR uint128(uint64_t bottom); // hi_ = 0 + UINT128_CONSTEXPR uint128(const uint128_pod &val); + + // Trivial copy constructor, assignment operator and destructor. + + void Initialize(uint64_t top, uint64_t bottom); + + // Arithmetic operators. + uint128& operator+=(const uint128& b); + uint128& operator-=(const uint128& b); + uint128& operator*=(const uint128& b); + // Long division/modulo for uint128. + uint128& operator/=(const uint128& b); + uint128& operator%=(const uint128& b); + uint128 operator++(int); + uint128 operator--(int); + uint128& operator<<=(int); + uint128& operator>>=(int); + uint128& operator&=(const uint128& b); + uint128& operator|=(const uint128& b); + uint128& operator^=(const uint128& b); + uint128& operator++(); + uint128& operator--(); + + friend uint64_t Uint128Low64(const uint128& v); + friend uint64_t Uint128High64(const uint128& v); + + // We add "std::" to avoid including all of port.h. + PROTOBUF_EXPORT friend std::ostream& operator<<(std::ostream& o, + const uint128& b); + + private: + static void DivModImpl(uint128 dividend, uint128 divisor, + uint128* quotient_ret, uint128* remainder_ret); + + // Little-endian memory order optimizations can benefit from + // having lo_ first, hi_ last. + // See util/endian/endian.h and Load128/Store128 for storing a uint128. + uint64_t lo_; + uint64_t hi_; + + // Not implemented, just declared for catching automatic type conversions. + uint128(uint8_t); + uint128(uint16_t); + uint128(float v); + uint128(double v); +}; + +// This is a POD form of uint128 which can be used for static variables which +// need to be operated on as uint128. +struct uint128_pod { + // Note: The ordering of fields is different than 'class uint128' but the + // same as its 2-arg constructor. This enables more obvious initialization + // of static instances, which is the primary reason for this struct in the + // first place. This does not seem to defeat any optimizations wrt + // operations involving this struct. + uint64_t hi; + uint64_t lo; +}; + +PROTOBUF_EXPORT extern const uint128_pod kuint128max; + +// allow uint128 to be logged +PROTOBUF_EXPORT extern std::ostream& operator<<(std::ostream& o, + const uint128& b); + +// Methods to access low and high pieces of 128-bit value. +// Defined externally from uint128 to facilitate conversion +// to native 128-bit types when compilers support them. +inline uint64_t Uint128Low64(const uint128& v) { return v.lo_; } +inline uint64_t Uint128High64(const uint128& v) { return v.hi_; } + +// TODO: perhaps it would be nice to have int128, a signed 128-bit type? + +// -------------------------------------------------------------------------- +// Implementation details follow +// -------------------------------------------------------------------------- +inline bool operator==(const uint128& lhs, const uint128& rhs) { + return (Uint128Low64(lhs) == Uint128Low64(rhs) && + Uint128High64(lhs) == Uint128High64(rhs)); +} +inline bool operator!=(const uint128& lhs, const uint128& rhs) { + return !(lhs == rhs); +} + +inline UINT128_CONSTEXPR uint128::uint128() : lo_(0), hi_(0) {} +inline UINT128_CONSTEXPR uint128::uint128(uint64_t top, uint64_t bottom) + : lo_(bottom), hi_(top) {} +inline UINT128_CONSTEXPR uint128::uint128(const uint128_pod& v) + : lo_(v.lo), hi_(v.hi) {} +inline UINT128_CONSTEXPR uint128::uint128(uint64_t bottom) + : lo_(bottom), hi_(0) {} +#ifndef SWIG +inline UINT128_CONSTEXPR uint128::uint128(uint32_t bottom) + : lo_(bottom), hi_(0) {} +inline UINT128_CONSTEXPR uint128::uint128(int bottom) + : lo_(bottom), hi_(static_cast<int64_t>((bottom < 0) ? -1 : 0)) {} +#endif + +#undef UINT128_CONSTEXPR + +inline void uint128::Initialize(uint64_t top, uint64_t bottom) { + hi_ = top; + lo_ = bottom; +} + +// Comparison operators. + +#define CMP128(op) \ +inline bool operator op(const uint128& lhs, const uint128& rhs) { \ + return (Uint128High64(lhs) == Uint128High64(rhs)) ? \ + (Uint128Low64(lhs) op Uint128Low64(rhs)) : \ + (Uint128High64(lhs) op Uint128High64(rhs)); \ +} + +CMP128(<) +CMP128(>) +CMP128(>=) +CMP128(<=) + +#undef CMP128 + +// Unary operators + +inline uint128 operator-(const uint128& val) { + const uint64_t hi_flip = ~Uint128High64(val); + const uint64_t lo_flip = ~Uint128Low64(val); + const uint64_t lo_add = lo_flip + 1; + if (lo_add < lo_flip) { + return uint128(hi_flip + 1, lo_add); + } + return uint128(hi_flip, lo_add); +} + +inline bool operator!(const uint128& val) { + return !Uint128High64(val) && !Uint128Low64(val); +} + +// Logical operators. + +inline uint128 operator~(const uint128& val) { + return uint128(~Uint128High64(val), ~Uint128Low64(val)); +} + +#define LOGIC128(op) \ +inline uint128 operator op(const uint128& lhs, const uint128& rhs) { \ + return uint128(Uint128High64(lhs) op Uint128High64(rhs), \ + Uint128Low64(lhs) op Uint128Low64(rhs)); \ +} + +LOGIC128(|) +LOGIC128(&) +LOGIC128(^) + +#undef LOGIC128 + +#define LOGICASSIGN128(op) \ +inline uint128& uint128::operator op(const uint128& other) { \ + hi_ op other.hi_; \ + lo_ op other.lo_; \ + return *this; \ +} + +LOGICASSIGN128(|=) +LOGICASSIGN128(&=) +LOGICASSIGN128(^=) + +#undef LOGICASSIGN128 + +// Shift operators. + +inline uint128 operator<<(const uint128& val, int amount) { + // uint64 shifts of >= 64 are undefined, so we will need some special-casing. + if (amount < 64) { + if (amount == 0) { + return val; + } + uint64_t new_hi = (Uint128High64(val) << amount) | + (Uint128Low64(val) >> (64 - amount)); + uint64_t new_lo = Uint128Low64(val) << amount; + return uint128(new_hi, new_lo); + } else if (amount < 128) { + return uint128(Uint128Low64(val) << (amount - 64), 0); + } else { + return uint128(0, 0); + } +} + +inline uint128 operator>>(const uint128& val, int amount) { + // uint64 shifts of >= 64 are undefined, so we will need some special-casing. + if (amount < 64) { + if (amount == 0) { + return val; + } + uint64_t new_hi = Uint128High64(val) >> amount; + uint64_t new_lo = (Uint128Low64(val) >> amount) | + (Uint128High64(val) << (64 - amount)); + return uint128(new_hi, new_lo); + } else if (amount < 128) { + return uint128(0, Uint128High64(val) >> (amount - 64)); + } else { + return uint128(0, 0); + } +} + +inline uint128& uint128::operator<<=(int amount) { + // uint64 shifts of >= 64 are undefined, so we will need some special-casing. + if (amount < 64) { + if (amount != 0) { + hi_ = (hi_ << amount) | (lo_ >> (64 - amount)); + lo_ = lo_ << amount; + } + } else if (amount < 128) { + hi_ = lo_ << (amount - 64); + lo_ = 0; + } else { + hi_ = 0; + lo_ = 0; + } + return *this; +} + +inline uint128& uint128::operator>>=(int amount) { + // uint64 shifts of >= 64 are undefined, so we will need some special-casing. + if (amount < 64) { + if (amount != 0) { + lo_ = (lo_ >> amount) | (hi_ << (64 - amount)); + hi_ = hi_ >> amount; + } + } else if (amount < 128) { + lo_ = hi_ >> (amount - 64); + hi_ = 0; + } else { + lo_ = 0; + hi_ = 0; + } + return *this; +} + +inline uint128 operator+(const uint128& lhs, const uint128& rhs) { + return uint128(lhs) += rhs; +} + +inline uint128 operator-(const uint128& lhs, const uint128& rhs) { + return uint128(lhs) -= rhs; +} + +inline uint128 operator*(const uint128& lhs, const uint128& rhs) { + return uint128(lhs) *= rhs; +} + +inline uint128 operator/(const uint128& lhs, const uint128& rhs) { + return uint128(lhs) /= rhs; +} + +inline uint128 operator%(const uint128& lhs, const uint128& rhs) { + return uint128(lhs) %= rhs; +} + +inline uint128& uint128::operator+=(const uint128& b) { + hi_ += b.hi_; + uint64_t lolo = lo_ + b.lo_; + if (lolo < lo_) + ++hi_; + lo_ = lolo; + return *this; +} + +inline uint128& uint128::operator-=(const uint128& b) { + hi_ -= b.hi_; + if (b.lo_ > lo_) + --hi_; + lo_ -= b.lo_; + return *this; +} + +inline uint128& uint128::operator*=(const uint128& b) { + uint64_t a96 = hi_ >> 32; + uint64_t a64 = hi_ & 0xffffffffu; + uint64_t a32 = lo_ >> 32; + uint64_t a00 = lo_ & 0xffffffffu; + uint64_t b96 = b.hi_ >> 32; + uint64_t b64 = b.hi_ & 0xffffffffu; + uint64_t b32 = b.lo_ >> 32; + uint64_t b00 = b.lo_ & 0xffffffffu; + // multiply [a96 .. a00] x [b96 .. b00] + // terms higher than c96 disappear off the high side + // terms c96 and c64 are safe to ignore carry bit + uint64_t c96 = a96 * b00 + a64 * b32 + a32 * b64 + a00 * b96; + uint64_t c64 = a64 * b00 + a32 * b32 + a00 * b64; + this->hi_ = (c96 << 32) + c64; + this->lo_ = 0; + // add terms after this one at a time to capture carry + *this += uint128(a32 * b00) << 32; + *this += uint128(a00 * b32) << 32; + *this += a00 * b00; + return *this; +} + +inline uint128 uint128::operator++(int) { + uint128 tmp(*this); + *this += 1; + return tmp; +} + +inline uint128 uint128::operator--(int) { + uint128 tmp(*this); + *this -= 1; + return tmp; +} + +inline uint128& uint128::operator++() { + *this += 1; + return *this; +} + +inline uint128& uint128::operator--() { + *this -= 1; + return *this; +} + +} // namespace protobuf +} // namespace google + +#include <google/protobuf/port_undef.inc> + +#endif // GOOGLE_PROTOBUF_STUBS_INT128_H_ diff --git a/toolkit/components/protobuf/src/google/protobuf/stubs/logging.h b/toolkit/components/protobuf/src/google/protobuf/stubs/logging.h new file mode 100644 index 0000000000..8ecc2fa0f1 --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/stubs/logging.h @@ -0,0 +1,239 @@ +// 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. + +#ifndef GOOGLE_PROTOBUF_STUBS_LOGGING_H_ +#define GOOGLE_PROTOBUF_STUBS_LOGGING_H_ + +#include <google/protobuf/stubs/macros.h> +#include <google/protobuf/stubs/port.h> +#include <google/protobuf/stubs/status.h> +#include <google/protobuf/stubs/stringpiece.h> + +#include <google/protobuf/port_def.inc> + +// =================================================================== +// emulates google3/base/logging.h + +namespace google { +namespace protobuf { + +enum LogLevel { + LOGLEVEL_INFO, // Informational. This is never actually used by + // libprotobuf. + LOGLEVEL_WARNING, // Warns about issues that, although not technically a + // problem now, could cause problems in the future. For + // example, a // warning will be printed when parsing a + // message that is near the message size limit. + LOGLEVEL_ERROR, // An error occurred which should never happen during + // normal use. + LOGLEVEL_FATAL, // An error occurred from which the library cannot + // recover. This usually indicates a programming error + // in the code which calls the library, especially when + // compiled in debug mode. + +#ifdef NDEBUG + LOGLEVEL_DFATAL = LOGLEVEL_ERROR +#else + LOGLEVEL_DFATAL = LOGLEVEL_FATAL +#endif +}; + +class uint128; +namespace internal { + +class LogFinisher; + +class PROTOBUF_EXPORT LogMessage { + public: + LogMessage(LogLevel level, const char* filename, int line); + ~LogMessage(); + + LogMessage& operator<<(const std::string& value); + LogMessage& operator<<(const char* value); + LogMessage& operator<<(char value); + LogMessage& operator<<(int value); + LogMessage& operator<<(uint value); + LogMessage& operator<<(long value); + LogMessage& operator<<(unsigned long value); + LogMessage& operator<<(long long value); + LogMessage& operator<<(unsigned long long value); + LogMessage& operator<<(double value); + LogMessage& operator<<(void* value); + LogMessage& operator<<(const StringPiece& value); + LogMessage& operator<<(const util::Status& status); + LogMessage& operator<<(const uint128& value); + + private: + friend class LogFinisher; + void Finish(); + + LogLevel level_; + const char* filename_; + int line_; + std::string message_; +}; + +// Used to make the entire "LOG(BLAH) << etc." expression have a void return +// type and print a newline after each message. +class PROTOBUF_EXPORT LogFinisher { + public: + void operator=(LogMessage& other); +}; + +template<typename T> +bool IsOk(T status) { return status.ok(); } +template<> +inline bool IsOk(bool status) { return status; } + +} // namespace internal + +// Undef everything in case we're being mixed with some other Google library +// which already defined them itself. Presumably all Google libraries will +// support the same syntax for these so it should not be a big deal if they +// end up using our definitions instead. +#undef GOOGLE_LOG +#undef GOOGLE_LOG_IF + +#undef GOOGLE_CHECK +#undef GOOGLE_CHECK_OK +#undef GOOGLE_CHECK_EQ +#undef GOOGLE_CHECK_NE +#undef GOOGLE_CHECK_LT +#undef GOOGLE_CHECK_LE +#undef GOOGLE_CHECK_GT +#undef GOOGLE_CHECK_GE +#undef GOOGLE_CHECK_NOTNULL + +#undef GOOGLE_DLOG +#undef GOOGLE_DCHECK +#undef GOOGLE_DCHECK_OK +#undef GOOGLE_DCHECK_EQ +#undef GOOGLE_DCHECK_NE +#undef GOOGLE_DCHECK_LT +#undef GOOGLE_DCHECK_LE +#undef GOOGLE_DCHECK_GT +#undef GOOGLE_DCHECK_GE + +#define GOOGLE_LOG(LEVEL) \ + ::google::protobuf::internal::LogFinisher() = \ + ::google::protobuf::internal::LogMessage( \ + ::google::protobuf::LOGLEVEL_##LEVEL, __FILE__, __LINE__) +#define GOOGLE_LOG_IF(LEVEL, CONDITION) \ + !(CONDITION) ? (void)0 : GOOGLE_LOG(LEVEL) + +#define GOOGLE_CHECK(EXPRESSION) \ + GOOGLE_LOG_IF(FATAL, !(EXPRESSION)) << "CHECK failed: " #EXPRESSION ": " +#define GOOGLE_CHECK_OK(A) GOOGLE_CHECK(::google::protobuf::internal::IsOk(A)) +#define GOOGLE_CHECK_EQ(A, B) GOOGLE_CHECK((A) == (B)) +#define GOOGLE_CHECK_NE(A, B) GOOGLE_CHECK((A) != (B)) +#define GOOGLE_CHECK_LT(A, B) GOOGLE_CHECK((A) < (B)) +#define GOOGLE_CHECK_LE(A, B) GOOGLE_CHECK((A) <= (B)) +#define GOOGLE_CHECK_GT(A, B) GOOGLE_CHECK((A) > (B)) +#define GOOGLE_CHECK_GE(A, B) GOOGLE_CHECK((A) >= (B)) + +namespace internal { +template<typename T> +T* CheckNotNull(const char* /* file */, int /* line */, + const char* name, T* val) { + if (val == nullptr) { + GOOGLE_LOG(FATAL) << name; + } + return val; +} +} // namespace internal +#define GOOGLE_CHECK_NOTNULL(A) \ + ::google::protobuf::internal::CheckNotNull( \ + __FILE__, __LINE__, "'" #A "' must not be nullptr", (A)) + +#ifdef NDEBUG + +#define GOOGLE_DLOG(LEVEL) GOOGLE_LOG_IF(LEVEL, false) + +#define GOOGLE_DCHECK(EXPRESSION) while(false) GOOGLE_CHECK(EXPRESSION) +#define GOOGLE_DCHECK_OK(E) GOOGLE_DCHECK(::google::protobuf::internal::IsOk(E)) +#define GOOGLE_DCHECK_EQ(A, B) GOOGLE_DCHECK((A) == (B)) +#define GOOGLE_DCHECK_NE(A, B) GOOGLE_DCHECK((A) != (B)) +#define GOOGLE_DCHECK_LT(A, B) GOOGLE_DCHECK((A) < (B)) +#define GOOGLE_DCHECK_LE(A, B) GOOGLE_DCHECK((A) <= (B)) +#define GOOGLE_DCHECK_GT(A, B) GOOGLE_DCHECK((A) > (B)) +#define GOOGLE_DCHECK_GE(A, B) GOOGLE_DCHECK((A) >= (B)) + +#else // NDEBUG + +#define GOOGLE_DLOG GOOGLE_LOG + +#define GOOGLE_DCHECK GOOGLE_CHECK +#define GOOGLE_DCHECK_OK GOOGLE_CHECK_OK +#define GOOGLE_DCHECK_EQ GOOGLE_CHECK_EQ +#define GOOGLE_DCHECK_NE GOOGLE_CHECK_NE +#define GOOGLE_DCHECK_LT GOOGLE_CHECK_LT +#define GOOGLE_DCHECK_LE GOOGLE_CHECK_LE +#define GOOGLE_DCHECK_GT GOOGLE_CHECK_GT +#define GOOGLE_DCHECK_GE GOOGLE_CHECK_GE + +#endif // !NDEBUG + +typedef void LogHandler(LogLevel level, const char* filename, int line, + const std::string& message); + +// The protobuf library sometimes writes warning and error messages to +// stderr. These messages are primarily useful for developers, but may +// also help end users figure out a problem. If you would prefer that +// these messages be sent somewhere other than stderr, call SetLogHandler() +// to set your own handler. This returns the old handler. Set the handler +// to nullptr to ignore log messages (but see also LogSilencer, below). +// +// Obviously, SetLogHandler is not thread-safe. You should only call it +// at initialization time, and probably not from library code. If you +// simply want to suppress log messages temporarily (e.g. because you +// have some code that tends to trigger them frequently and you know +// the warnings are not important to you), use the LogSilencer class +// below. +PROTOBUF_EXPORT LogHandler* SetLogHandler(LogHandler* new_func); + +// Create a LogSilencer if you want to temporarily suppress all log +// messages. As long as any LogSilencer objects exist, non-fatal +// log messages will be discarded (the current LogHandler will *not* +// be called). Constructing a LogSilencer is thread-safe. You may +// accidentally suppress log messages occurring in another thread, but +// since messages are generally for debugging purposes only, this isn't +// a big deal. If you want to intercept log messages, use SetLogHandler(). +class PROTOBUF_EXPORT LogSilencer { + public: + LogSilencer(); + ~LogSilencer(); +}; + +} // namespace protobuf +} // namespace google + +#include <google/protobuf/port_undef.inc> + +#endif // GOOGLE_PROTOBUF_STUBS_LOGGING_H_ diff --git a/toolkit/components/protobuf/src/google/protobuf/stubs/macros.h b/toolkit/components/protobuf/src/google/protobuf/stubs/macros.h new file mode 100644 index 0000000000..ae9a8b987f --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/stubs/macros.h @@ -0,0 +1,93 @@ +// 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. + +#ifndef GOOGLE_PROTOBUF_MACROS_H__ +#define GOOGLE_PROTOBUF_MACROS_H__ + +namespace google { +namespace protobuf { + +#undef GOOGLE_DISALLOW_EVIL_CONSTRUCTORS +#define GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(TypeName) \ + TypeName(const TypeName&) = delete; \ + void operator=(const TypeName&) = delete + +#undef GOOGLE_DISALLOW_IMPLICIT_CONSTRUCTORS +#define GOOGLE_DISALLOW_IMPLICIT_CONSTRUCTORS(TypeName) \ + TypeName() = delete; \ + TypeName(const TypeName&) = delete; \ + void operator=(const TypeName&) = delete + +// =================================================================== +// from google3/base/basictypes.h + +// The GOOGLE_ARRAYSIZE(arr) macro returns the # of elements in an array arr. +// The expression is a compile-time constant, and therefore can be +// used in defining new arrays, for example. +// +// GOOGLE_ARRAYSIZE catches a few type errors. If you see a compiler error +// +// "warning: division by zero in ..." +// +// when using GOOGLE_ARRAYSIZE, you are (wrongfully) giving it a pointer. +// You should only use GOOGLE_ARRAYSIZE on statically allocated arrays. +// +// The following comments are on the implementation details, and can +// be ignored by the users. +// +// ARRAYSIZE(arr) works by inspecting sizeof(arr) (the # of bytes in +// the array) and sizeof(*(arr)) (the # of bytes in one array +// element). If the former is divisible by the latter, perhaps arr is +// indeed an array, in which case the division result is the # of +// elements in the array. Otherwise, arr cannot possibly be an array, +// and we generate a compiler error to prevent the code from +// compiling. +// +// Since the size of bool is implementation-defined, we need to cast +// !(sizeof(a) & sizeof(*(a))) to size_t in order to ensure the final +// result has type size_t. +// +// This macro is not perfect as it wrongfully accepts certain +// pointers, namely where the pointer size is divisible by the pointee +// size. Since all our code has to go through a 32-bit compiler, +// where a pointer is 4 bytes, this means all pointers to a type whose +// size is 3 or greater than 4 will be (righteously) rejected. +// +// Kudos to Jorg Brown for this simple and elegant implementation. + +#undef GOOGLE_ARRAYSIZE +#define GOOGLE_ARRAYSIZE(a) \ + ((sizeof(a) / sizeof(*(a))) / \ + static_cast<size_t>(!(sizeof(a) % sizeof(*(a))))) + +} // namespace protobuf +} // namespace google + +#endif // GOOGLE_PROTOBUF_MACROS_H__ diff --git a/toolkit/components/protobuf/src/google/protobuf/stubs/map_util.h b/toolkit/components/protobuf/src/google/protobuf/stubs/map_util.h new file mode 100644 index 0000000000..24e098ad1b --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/stubs/map_util.h @@ -0,0 +1,769 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2014 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. + +// from google3/util/gtl/map_util.h +// Author: Anton Carver + +#ifndef GOOGLE_PROTOBUF_STUBS_MAP_UTIL_H__ +#define GOOGLE_PROTOBUF_STUBS_MAP_UTIL_H__ + +#include <stddef.h> +#include <iterator> +#include <string> +#include <utility> +#include <vector> + +#include <google/protobuf/stubs/common.h> + +namespace google { +namespace protobuf { +namespace internal { +// Local implementation of RemoveConst to avoid including base/type_traits.h. +template <class T> struct RemoveConst { typedef T type; }; +template <class T> struct RemoveConst<const T> : RemoveConst<T> {}; +} // namespace internal + +// +// Find*() +// + +// Returns a const reference to the value associated with the given key if it +// exists. Crashes otherwise. +// +// This is intended as a replacement for operator[] as an rvalue (for reading) +// when the key is guaranteed to exist. +// +// operator[] for lookup is discouraged for several reasons: +// * It has a side-effect of inserting missing keys +// * It is not thread-safe (even when it is not inserting, it can still +// choose to resize the underlying storage) +// * It invalidates iterators (when it chooses to resize) +// * It default constructs a value object even if it doesn't need to +// +// This version assumes the key is printable, and includes it in the fatal log +// message. +template <class Collection> +const typename Collection::value_type::second_type& +FindOrDie(const Collection& collection, + const typename Collection::value_type::first_type& key) { + typename Collection::const_iterator it = collection.find(key); + GOOGLE_CHECK(it != collection.end()) << "Map key not found: " << key; + return it->second; +} + +// Same as above, but returns a non-const reference. +template <class Collection> +typename Collection::value_type::second_type& +FindOrDie(Collection& collection, // NOLINT + const typename Collection::value_type::first_type& key) { + typename Collection::iterator it = collection.find(key); + GOOGLE_CHECK(it != collection.end()) << "Map key not found: " << key; + return it->second; +} + +// Same as FindOrDie above, but doesn't log the key on failure. +template <class Collection> +const typename Collection::value_type::second_type& +FindOrDieNoPrint(const Collection& collection, + const typename Collection::value_type::first_type& key) { + typename Collection::const_iterator it = collection.find(key); + GOOGLE_CHECK(it != collection.end()) << "Map key not found"; + return it->second; +} + +// Same as above, but returns a non-const reference. +template <class Collection> +typename Collection::value_type::second_type& +FindOrDieNoPrint(Collection& collection, // NOLINT + const typename Collection::value_type::first_type& key) { + typename Collection::iterator it = collection.find(key); + GOOGLE_CHECK(it != collection.end()) << "Map key not found"; + return it->second; +} + +// Returns a const reference to the value associated with the given key if it +// exists, otherwise returns a const reference to the provided default value. +// +// WARNING: If a temporary object is passed as the default "value," +// this function will return a reference to that temporary object, +// which will be destroyed at the end of the statement. A common +// example: if you have a map with string values, and you pass a char* +// as the default "value," either use the returned value immediately +// or store it in a string (not string&). +// Details: http://go/findwithdefault +template <class Collection> +const typename Collection::value_type::second_type& +FindWithDefault(const Collection& collection, + const typename Collection::value_type::first_type& key, + const typename Collection::value_type::second_type& value) { + typename Collection::const_iterator it = collection.find(key); + if (it == collection.end()) { + return value; + } + return it->second; +} + +// Returns a pointer to the const value associated with the given key if it +// exists, or nullptr otherwise. +template <class Collection> +const typename Collection::value_type::second_type* +FindOrNull(const Collection& collection, + const typename Collection::value_type::first_type& key) { + typename Collection::const_iterator it = collection.find(key); + if (it == collection.end()) { + return 0; + } + return &it->second; +} + +// Same as above but returns a pointer to the non-const value. +template <class Collection> +typename Collection::value_type::second_type* +FindOrNull(Collection& collection, // NOLINT + const typename Collection::value_type::first_type& key) { + typename Collection::iterator it = collection.find(key); + if (it == collection.end()) { + return 0; + } + return &it->second; +} + +// Returns the pointer value associated with the given key. If none is found, +// nullptr is returned. The function is designed to be used with a map of keys to +// pointers. +// +// This function does not distinguish between a missing key and a key mapped +// to nullptr. +template <class Collection> +typename Collection::value_type::second_type +FindPtrOrNull(const Collection& collection, + const typename Collection::value_type::first_type& key) { + typename Collection::const_iterator it = collection.find(key); + if (it == collection.end()) { + return typename Collection::value_type::second_type(); + } + return it->second; +} + +// Same as above, except takes non-const reference to collection. +// +// This function is needed for containers that propagate constness to the +// pointee, such as boost::ptr_map. +template <class Collection> +typename Collection::value_type::second_type +FindPtrOrNull(Collection& collection, // NOLINT + const typename Collection::value_type::first_type& key) { + typename Collection::iterator it = collection.find(key); + if (it == collection.end()) { + return typename Collection::value_type::second_type(); + } + return it->second; +} + +// Finds the pointer value associated with the given key in a map whose values +// are linked_ptrs. Returns nullptr if key is not found. +template <class Collection> +typename Collection::value_type::second_type::element_type* +FindLinkedPtrOrNull(const Collection& collection, + const typename Collection::value_type::first_type& key) { + typename Collection::const_iterator it = collection.find(key); + if (it == collection.end()) { + return 0; + } + // Since linked_ptr::get() is a const member returning a non const, + // we do not need a version of this function taking a non const collection. + return it->second.get(); +} + +// Same as above, but dies if the key is not found. +template <class Collection> +typename Collection::value_type::second_type::element_type& +FindLinkedPtrOrDie(const Collection& collection, + const typename Collection::value_type::first_type& key) { + typename Collection::const_iterator it = collection.find(key); + GOOGLE_CHECK(it != collection.end()) << "key not found: " << key; + // Since linked_ptr::operator*() is a const member returning a non const, + // we do not need a version of this function taking a non const collection. + return *it->second; +} + +// Finds the value associated with the given key and copies it to *value (if not +// nullptr). Returns false if the key was not found, true otherwise. +template <class Collection, class Key, class Value> +bool FindCopy(const Collection& collection, + const Key& key, + Value* const value) { + typename Collection::const_iterator it = collection.find(key); + if (it == collection.end()) { + return false; + } + if (value) { + *value = it->second; + } + return true; +} + +// +// Contains*() +// + +// Returns true if and only if the given collection contains the given key. +template <class Collection, class Key> +bool ContainsKey(const Collection& collection, const Key& key) { + return collection.find(key) != collection.end(); +} + +// Returns true if and only if the given collection contains the given key-value +// pair. +template <class Collection, class Key, class Value> +bool ContainsKeyValuePair(const Collection& collection, + const Key& key, + const Value& value) { + typedef typename Collection::const_iterator const_iterator; + std::pair<const_iterator, const_iterator> range = collection.equal_range(key); + for (const_iterator it = range.first; it != range.second; ++it) { + if (it->second == value) { + return true; + } + } + return false; +} + +// +// Insert*() +// + +// Inserts the given key-value pair into the collection. Returns true if and +// only if the key from the given pair didn't previously exist. Otherwise, the +// value in the map is replaced with the value from the given pair. +template <class Collection> +bool InsertOrUpdate(Collection* const collection, + const typename Collection::value_type& vt) { + std::pair<typename Collection::iterator, bool> ret = collection->insert(vt); + if (!ret.second) { + // update + ret.first->second = vt.second; + return false; + } + return true; +} + +// Same as above, except that the key and value are passed separately. +template <class Collection> +bool InsertOrUpdate(Collection* const collection, + const typename Collection::value_type::first_type& key, + const typename Collection::value_type::second_type& value) { + return InsertOrUpdate( + collection, typename Collection::value_type(key, value)); +} + +// Inserts/updates all the key-value pairs from the range defined by the +// iterators "first" and "last" into the given collection. +template <class Collection, class InputIterator> +void InsertOrUpdateMany(Collection* const collection, + InputIterator first, InputIterator last) { + for (; first != last; ++first) { + InsertOrUpdate(collection, *first); + } +} + +// Change the value associated with a particular key in a map or hash_map +// of the form map<Key, Value*> which owns the objects pointed to by the +// value pointers. If there was an existing value for the key, it is deleted. +// True indicates an insert took place, false indicates an update + delete. +template <class Collection> +bool InsertAndDeleteExisting( + Collection* const collection, + const typename Collection::value_type::first_type& key, + const typename Collection::value_type::second_type& value) { + std::pair<typename Collection::iterator, bool> ret = + collection->insert(typename Collection::value_type(key, value)); + if (!ret.second) { + delete ret.first->second; + ret.first->second = value; + return false; + } + return true; +} + +// Inserts the given key and value into the given collection if and only if the +// given key did NOT already exist in the collection. If the key previously +// existed in the collection, the value is not changed. Returns true if the +// key-value pair was inserted; returns false if the key was already present. +template <class Collection> +bool InsertIfNotPresent(Collection* const collection, + const typename Collection::value_type& vt) { + return collection->insert(vt).second; +} + +// Same as above except the key and value are passed separately. +template <class Collection> +bool InsertIfNotPresent( + Collection* const collection, + const typename Collection::value_type::first_type& key, + const typename Collection::value_type::second_type& value) { + return InsertIfNotPresent( + collection, typename Collection::value_type(key, value)); +} + +// Same as above except dies if the key already exists in the collection. +template <class Collection> +void InsertOrDie(Collection* const collection, + const typename Collection::value_type& value) { + GOOGLE_CHECK(InsertIfNotPresent(collection, value)) + << "duplicate value: " << value; +} + +// Same as above except doesn't log the value on error. +template <class Collection> +void InsertOrDieNoPrint(Collection* const collection, + const typename Collection::value_type& value) { + GOOGLE_CHECK(InsertIfNotPresent(collection, value)) << "duplicate value."; +} + +// Inserts the key-value pair into the collection. Dies if key was already +// present. +template <class Collection> +void InsertOrDie(Collection* const collection, + const typename Collection::value_type::first_type& key, + const typename Collection::value_type::second_type& data) { + GOOGLE_CHECK(InsertIfNotPresent(collection, key, data)) + << "duplicate key: " << key; +} + +// Same as above except doesn't log the key on error. +template <class Collection> +void InsertOrDieNoPrint( + Collection* const collection, + const typename Collection::value_type::first_type& key, + const typename Collection::value_type::second_type& data) { + GOOGLE_CHECK(InsertIfNotPresent(collection, key, data)) << "duplicate key."; +} + +// Inserts a new key and default-initialized value. Dies if the key was already +// present. Returns a reference to the value. Example usage: +// +// map<int, SomeProto> m; +// SomeProto& proto = InsertKeyOrDie(&m, 3); +// proto.set_field("foo"); +template <class Collection> +typename Collection::value_type::second_type& InsertKeyOrDie( + Collection* const collection, + const typename Collection::value_type::first_type& key) { + typedef typename Collection::value_type value_type; + std::pair<typename Collection::iterator, bool> res = + collection->insert(value_type(key, typename value_type::second_type())); + GOOGLE_CHECK(res.second) << "duplicate key: " << key; + return res.first->second; +} + +// +// Lookup*() +// + +// Looks up a given key and value pair in a collection and inserts the key-value +// pair if it's not already present. Returns a reference to the value associated +// with the key. +template <class Collection> +typename Collection::value_type::second_type& +LookupOrInsert(Collection* const collection, + const typename Collection::value_type& vt) { + return collection->insert(vt).first->second; +} + +// Same as above except the key-value are passed separately. +template <class Collection> +typename Collection::value_type::second_type& +LookupOrInsert(Collection* const collection, + const typename Collection::value_type::first_type& key, + const typename Collection::value_type::second_type& value) { + return LookupOrInsert( + collection, typename Collection::value_type(key, value)); +} + +// Counts the number of equivalent elements in the given "sequence", and stores +// the results in "count_map" with element as the key and count as the value. +// +// Example: +// vector<string> v = {"a", "b", "c", "a", "b"}; +// map<string, int> m; +// AddTokenCounts(v, 1, &m); +// assert(m["a"] == 2); +// assert(m["b"] == 2); +// assert(m["c"] == 1); +template <typename Sequence, typename Collection> +void AddTokenCounts( + const Sequence& sequence, + const typename Collection::value_type::second_type& increment, + Collection* const count_map) { + for (typename Sequence::const_iterator it = sequence.begin(); + it != sequence.end(); ++it) { + typename Collection::value_type::second_type& value = + LookupOrInsert(count_map, *it, + typename Collection::value_type::second_type()); + value += increment; + } +} + +// Returns a reference to the value associated with key. If not found, a value +// is default constructed on the heap and added to the map. +// +// This function is useful for containers of the form map<Key, Value*>, where +// inserting a new key, value pair involves constructing a new heap-allocated +// Value, and storing a pointer to that in the collection. +template <class Collection> +typename Collection::value_type::second_type& +LookupOrInsertNew(Collection* const collection, + const typename Collection::value_type::first_type& key) { + typedef typename std::iterator_traits< + typename Collection::value_type::second_type>::value_type Element; + std::pair<typename Collection::iterator, bool> ret = + collection->insert(typename Collection::value_type( + key, + static_cast<typename Collection::value_type::second_type>(nullptr))); + if (ret.second) { + ret.first->second = new Element(); + } + return ret.first->second; +} + +// Same as above but constructs the value using the single-argument constructor +// and the given "arg". +template <class Collection, class Arg> +typename Collection::value_type::second_type& +LookupOrInsertNew(Collection* const collection, + const typename Collection::value_type::first_type& key, + const Arg& arg) { + typedef typename std::iterator_traits< + typename Collection::value_type::second_type>::value_type Element; + std::pair<typename Collection::iterator, bool> ret = + collection->insert(typename Collection::value_type( + key, + static_cast<typename Collection::value_type::second_type>(nullptr))); + if (ret.second) { + ret.first->second = new Element(arg); + } + return ret.first->second; +} + +// Lookup of linked/shared pointers is used in two scenarios: +// +// Use LookupOrInsertNewLinkedPtr if the container owns the elements. +// In this case it is fine working with the raw pointer as long as it is +// guaranteed that no other thread can delete/update an accessed element. +// A mutex will need to lock the container operation as well as the use +// of the returned elements. Finding an element may be performed using +// FindLinkedPtr*(). +// +// Use LookupOrInsertNewSharedPtr if the container does not own the elements +// for their whole lifetime. This is typically the case when a reader allows +// parallel updates to the container. In this case a Mutex only needs to lock +// container operations, but all element operations must be performed on the +// shared pointer. Finding an element must be performed using FindPtr*() and +// cannot be done with FindLinkedPtr*() even though it compiles. + +// Lookup a key in a map or hash_map whose values are linked_ptrs. If it is +// missing, set collection[key].reset(new Value::element_type) and return that. +// Value::element_type must be default constructable. +template <class Collection> +typename Collection::value_type::second_type::element_type* +LookupOrInsertNewLinkedPtr( + Collection* const collection, + const typename Collection::value_type::first_type& key) { + typedef typename Collection::value_type::second_type Value; + std::pair<typename Collection::iterator, bool> ret = + collection->insert(typename Collection::value_type(key, Value())); + if (ret.second) { + ret.first->second.reset(new typename Value::element_type); + } + return ret.first->second.get(); +} + +// A variant of LookupOrInsertNewLinkedPtr where the value is constructed using +// a single-parameter constructor. Note: the constructor argument is computed +// even if it will not be used, so only values cheap to compute should be passed +// here. On the other hand it does not matter how expensive the construction of +// the actual stored value is, as that only occurs if necessary. +template <class Collection, class Arg> +typename Collection::value_type::second_type::element_type* +LookupOrInsertNewLinkedPtr( + Collection* const collection, + const typename Collection::value_type::first_type& key, + const Arg& arg) { + typedef typename Collection::value_type::second_type Value; + std::pair<typename Collection::iterator, bool> ret = + collection->insert(typename Collection::value_type(key, Value())); + if (ret.second) { + ret.first->second.reset(new typename Value::element_type(arg)); + } + return ret.first->second.get(); +} + +// Lookup a key in a map or hash_map whose values are shared_ptrs. If it is +// missing, set collection[key].reset(new Value::element_type). Unlike +// LookupOrInsertNewLinkedPtr, this function returns the shared_ptr instead of +// the raw pointer. Value::element_type must be default constructable. +template <class Collection> +typename Collection::value_type::second_type& +LookupOrInsertNewSharedPtr( + Collection* const collection, + const typename Collection::value_type::first_type& key) { + typedef typename Collection::value_type::second_type SharedPtr; + typedef typename Collection::value_type::second_type::element_type Element; + std::pair<typename Collection::iterator, bool> ret = + collection->insert(typename Collection::value_type(key, SharedPtr())); + if (ret.second) { + ret.first->second.reset(new Element()); + } + return ret.first->second; +} + +// A variant of LookupOrInsertNewSharedPtr where the value is constructed using +// a single-parameter constructor. Note: the constructor argument is computed +// even if it will not be used, so only values cheap to compute should be passed +// here. On the other hand it does not matter how expensive the construction of +// the actual stored value is, as that only occurs if necessary. +template <class Collection, class Arg> +typename Collection::value_type::second_type& +LookupOrInsertNewSharedPtr( + Collection* const collection, + const typename Collection::value_type::first_type& key, + const Arg& arg) { + typedef typename Collection::value_type::second_type SharedPtr; + typedef typename Collection::value_type::second_type::element_type Element; + std::pair<typename Collection::iterator, bool> ret = + collection->insert(typename Collection::value_type(key, SharedPtr())); + if (ret.second) { + ret.first->second.reset(new Element(arg)); + } + return ret.first->second; +} + +// +// Misc Utility Functions +// + +// Updates the value associated with the given key. If the key was not already +// present, then the key-value pair are inserted and "previous" is unchanged. If +// the key was already present, the value is updated and "*previous" will +// contain a copy of the old value. +// +// InsertOrReturnExisting has complementary behavior that returns the +// address of an already existing value, rather than updating it. +template <class Collection> +bool UpdateReturnCopy(Collection* const collection, + const typename Collection::value_type::first_type& key, + const typename Collection::value_type::second_type& value, + typename Collection::value_type::second_type* previous) { + std::pair<typename Collection::iterator, bool> ret = + collection->insert(typename Collection::value_type(key, value)); + if (!ret.second) { + // update + if (previous) { + *previous = ret.first->second; + } + ret.first->second = value; + return true; + } + return false; +} + +// Same as above except that the key and value are passed as a pair. +template <class Collection> +bool UpdateReturnCopy(Collection* const collection, + const typename Collection::value_type& vt, + typename Collection::value_type::second_type* previous) { + std::pair<typename Collection::iterator, bool> ret = collection->insert(vt); + if (!ret.second) { + // update + if (previous) { + *previous = ret.first->second; + } + ret.first->second = vt.second; + return true; + } + return false; +} + +// Tries to insert the given key-value pair into the collection. Returns nullptr if +// the insert succeeds. Otherwise, returns a pointer to the existing value. +// +// This complements UpdateReturnCopy in that it allows to update only after +// verifying the old value and still insert quickly without having to look up +// twice. Unlike UpdateReturnCopy this also does not come with the issue of an +// undefined previous* in case new data was inserted. +template <class Collection> +typename Collection::value_type::second_type* InsertOrReturnExisting( + Collection* const collection, const typename Collection::value_type& vt) { + std::pair<typename Collection::iterator, bool> ret = collection->insert(vt); + if (ret.second) { + return nullptr; // Inserted, no existing previous value. + } else { + return &ret.first->second; // Return address of already existing value. + } +} + +// Same as above, except for explicit key and data. +template <class Collection> +typename Collection::value_type::second_type* InsertOrReturnExisting( + Collection* const collection, + const typename Collection::value_type::first_type& key, + const typename Collection::value_type::second_type& data) { + return InsertOrReturnExisting(collection, + typename Collection::value_type(key, data)); +} + +// Erases the collection item identified by the given key, and returns the value +// associated with that key. It is assumed that the value (i.e., the +// mapped_type) is a pointer. Returns nullptr if the key was not found in the +// collection. +// +// Examples: +// map<string, MyType*> my_map; +// +// One line cleanup: +// delete EraseKeyReturnValuePtr(&my_map, "abc"); +// +// Use returned value: +// std::unique_ptr<MyType> value_ptr( +// EraseKeyReturnValuePtr(&my_map, "abc")); +// if (value_ptr.get()) +// value_ptr->DoSomething(); +// +template <class Collection> +typename Collection::value_type::second_type EraseKeyReturnValuePtr( + Collection* const collection, + const typename Collection::value_type::first_type& key) { + typename Collection::iterator it = collection->find(key); + if (it == collection->end()) { + return nullptr; + } + typename Collection::value_type::second_type v = it->second; + collection->erase(it); + return v; +} + +// Inserts all the keys from map_container into key_container, which must +// support insert(MapContainer::key_type). +// +// Note: any initial contents of the key_container are not cleared. +template <class MapContainer, class KeyContainer> +void InsertKeysFromMap(const MapContainer& map_container, + KeyContainer* key_container) { + GOOGLE_CHECK(key_container != nullptr); + for (typename MapContainer::const_iterator it = map_container.begin(); + it != map_container.end(); ++it) { + key_container->insert(it->first); + } +} + +// Appends all the keys from map_container into key_container, which must +// support push_back(MapContainer::key_type). +// +// Note: any initial contents of the key_container are not cleared. +template <class MapContainer, class KeyContainer> +void AppendKeysFromMap(const MapContainer& map_container, + KeyContainer* key_container) { + GOOGLE_CHECK(key_container != nullptr); + for (typename MapContainer::const_iterator it = map_container.begin(); + it != map_container.end(); ++it) { + key_container->push_back(it->first); + } +} + +// A more specialized overload of AppendKeysFromMap to optimize reallocations +// for the common case in which we're appending keys to a vector and hence can +// (and sometimes should) call reserve() first. +// +// (It would be possible to play SFINAE games to call reserve() for any +// container that supports it, but this seems to get us 99% of what we need +// without the complexity of a SFINAE-based solution.) +template <class MapContainer, class KeyType> +void AppendKeysFromMap(const MapContainer& map_container, + std::vector<KeyType>* key_container) { + GOOGLE_CHECK(key_container != nullptr); + // We now have the opportunity to call reserve(). Calling reserve() every + // time is a bad idea for some use cases: libstdc++'s implementation of + // vector<>::reserve() resizes the vector's backing store to exactly the + // given size (unless it's already at least that big). Because of this, + // the use case that involves appending a lot of small maps (total size + // N) one by one to a vector would be O(N^2). But never calling reserve() + // loses the opportunity to improve the use case of adding from a large + // map to an empty vector (this improves performance by up to 33%). A + // number of heuristics are possible; see the discussion in + // cl/34081696. Here we use the simplest one. + if (key_container->empty()) { + key_container->reserve(map_container.size()); + } + for (typename MapContainer::const_iterator it = map_container.begin(); + it != map_container.end(); ++it) { + key_container->push_back(it->first); + } +} + +// Inserts all the values from map_container into value_container, which must +// support push_back(MapContainer::mapped_type). +// +// Note: any initial contents of the value_container are not cleared. +template <class MapContainer, class ValueContainer> +void AppendValuesFromMap(const MapContainer& map_container, + ValueContainer* value_container) { + GOOGLE_CHECK(value_container != nullptr); + for (typename MapContainer::const_iterator it = map_container.begin(); + it != map_container.end(); ++it) { + value_container->push_back(it->second); + } +} + +// A more specialized overload of AppendValuesFromMap to optimize reallocations +// for the common case in which we're appending values to a vector and hence +// can (and sometimes should) call reserve() first. +// +// (It would be possible to play SFINAE games to call reserve() for any +// container that supports it, but this seems to get us 99% of what we need +// without the complexity of a SFINAE-based solution.) +template <class MapContainer, class ValueType> +void AppendValuesFromMap(const MapContainer& map_container, + std::vector<ValueType>* value_container) { + GOOGLE_CHECK(value_container != nullptr); + // See AppendKeysFromMap for why this is done. + if (value_container->empty()) { + value_container->reserve(map_container.size()); + } + for (typename MapContainer::const_iterator it = map_container.begin(); + it != map_container.end(); ++it) { + value_container->push_back(it->second); + } +} + +} // namespace protobuf +} // namespace google + +#endif // GOOGLE_PROTOBUF_STUBS_MAP_UTIL_H__ diff --git a/toolkit/components/protobuf/src/google/protobuf/stubs/mathutil.h b/toolkit/components/protobuf/src/google/protobuf/stubs/mathutil.h new file mode 100644 index 0000000000..1d16bcedb2 --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/stubs/mathutil.h @@ -0,0 +1,162 @@ +// 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. +#ifndef GOOGLE_PROTOBUF_STUBS_MATHUTIL_H_ +#define GOOGLE_PROTOBUF_STUBS_MATHUTIL_H_ + +#include <cmath> +#include <float.h> +#include <limits> + +#include <google/protobuf/stubs/common.h> +#include <google/protobuf/stubs/logging.h> + +namespace google { +namespace protobuf { +namespace internal { + +// Like std::make_unsigned_t except floating point types map to themselves. +template <typename T> +using MakeUnsignedT = + typename std::conditional<std::is_integral<T>::value, std::make_unsigned<T>, + std::common_type<T>>::type::type; + +// Like std::isnan() except a template function that is defined for all numeric +// types. +template <typename T, + typename std::enable_if<std::is_integral<T>::value, int>::type = 0> +bool IsNan(T /*val*/) { + return false; +} + +template <typename T, typename std::enable_if<std::is_floating_point<T>::value, + int>::type = 0> +bool IsNan(T val) { + return std::isnan(val); +} + +template<typename T> +bool AlmostEquals(T a, T b) { + return a == b; +} +template<> +inline bool AlmostEquals(float a, float b) { + return fabs(a - b) < 32 * FLT_EPSILON; +} + +template<> +inline bool AlmostEquals(double a, double b) { + return fabs(a - b) < 32 * DBL_EPSILON; +} + +} // namespace internal + +class MathUtil { + public: + template <typename T> + static T Sign(T value) { + if (value == T(0) || internal::IsNan(value)) { + return value; + } + return value > T(0) ? 1 : -1; + } + + template <typename T> + static bool AlmostEquals(T a, T b) { + return internal::AlmostEquals(a, b); + } + + // Largest of two values. + // Works correctly for special floating point values. + // Note: 0.0 and -0.0 are not differentiated by Max (Max(0.0, -0.0) is -0.0), + // which should be OK because, although they (can) have different + // bit representation, they are observably the same when examined + // with arithmetic and (in)equality operators. + template <typename T> + static T Max(const T x, const T y) { + return internal::IsNan(x) || x > y ? x : y; + } + + // Absolute value of x + // Works correctly for unsigned types and + // for special floating point values. + // Note: 0.0 and -0.0 are not differentiated by Abs (Abs(0.0) is -0.0), + // which should be OK: see the comment for Max above. + template<typename T> + static T Abs(const T x) { + return x > T(0) ? x : -x; + } + + // Absolute value of the difference between two numbers. + // Works correctly for signed types and special floating point values. + template <typename T> + static typename internal::MakeUnsignedT<T> AbsDiff(const T x, const T y) { + // Carries out arithmetic as unsigned to avoid overflow. + typedef typename internal::MakeUnsignedT<T> R; + return x > y ? R(x) - R(y) : R(y) - R(x); + } + + // If two (usually floating point) numbers are within a certain + // fraction of their magnitude or within a certain absolute margin of error. + // This is the same as the following but faster: + // WithinFraction(x, y, fraction) || WithinMargin(x, y, margin) + // E.g. WithinFraction(0.0, 1e-10, 1e-5) is false but + // WithinFractionOrMargin(0.0, 1e-10, 1e-5, 1e-5) is true. + template<typename T> + static bool WithinFractionOrMargin(const T x, const T y, + const T fraction, const T margin); +}; + +template<typename T> +bool MathUtil::WithinFractionOrMargin(const T x, const T y, + const T fraction, const T margin) { + // Not just "0 <= fraction" to fool the compiler for unsigned types. + GOOGLE_DCHECK((T(0) < fraction || T(0) == fraction) && + fraction < T(1) && + margin >= T(0)); + + // Template specialization will convert the if() condition to a constant, + // which will cause the compiler to generate code for either the "if" part + // or the "then" part. In this way we avoid a compiler warning + // about a potential integer overflow in crosstool v12 (gcc 4.3.1). + if (std::numeric_limits<T>::is_integer) { + return x == y; + } else { + if (!std::isfinite(x) || !std::isfinite(y)) { + return false; + } + T relative_margin = static_cast<T>(fraction * Max(Abs(x), Abs(y))); + return AbsDiff(x, y) <= Max(margin, relative_margin); + } +} + +} // namespace protobuf +} // namespace google + +#endif // GOOGLE_PROTOBUF_STUBS_MATHUTIL_H_ diff --git a/toolkit/components/protobuf/src/google/protobuf/stubs/mutex.h b/toolkit/components/protobuf/src/google/protobuf/stubs/mutex.h new file mode 100644 index 0000000000..c4599913be --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/stubs/mutex.h @@ -0,0 +1,218 @@ +// Copyright (c) 2006, Google Inc. +// All rights reserved. +// +// 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. + +#ifndef GOOGLE_PROTOBUF_STUBS_MUTEX_H_ +#define GOOGLE_PROTOBUF_STUBS_MUTEX_H_ + +#include <mutex> + +#ifdef GOOGLE_PROTOBUF_SUPPORT_WINDOWS_XP + +#include <windows.h> + +// GetMessage conflicts with GeneratedMessageReflection::GetMessage(). +#ifdef GetMessage +#undef GetMessage +#endif + +#endif + +#include <google/protobuf/stubs/macros.h> + +// Define thread-safety annotations for use below, if we are building with +// Clang. +#if defined(__clang__) && !defined(SWIG) +#define GOOGLE_PROTOBUF_ACQUIRE(...) \ + __attribute__((acquire_capability(__VA_ARGS__))) +#define GOOGLE_PROTOBUF_RELEASE(...) \ + __attribute__((release_capability(__VA_ARGS__))) +#define GOOGLE_PROTOBUF_SCOPED_CAPABILITY __attribute__((scoped_lockable)) +#define GOOGLE_PROTOBUF_CAPABILITY(x) __attribute__((capability(x))) +#else +#define GOOGLE_PROTOBUF_ACQUIRE(...) +#define GOOGLE_PROTOBUF_RELEASE(...) +#define GOOGLE_PROTOBUF_SCOPED_CAPABILITY +#define GOOGLE_PROTOBUF_CAPABILITY(x) +#endif + +#include <google/protobuf/port_def.inc> + +// =================================================================== +// emulates google3/base/mutex.h +namespace google { +namespace protobuf { +namespace internal { + +#define GOOGLE_PROTOBUF_LINKER_INITIALIZED + +#ifdef GOOGLE_PROTOBUF_SUPPORT_WINDOWS_XP + +// This class is a lightweight replacement for std::mutex on Windows platforms. +// std::mutex does not work on Windows XP SP2 with the latest VC++ libraries, +// because it utilizes the Concurrency Runtime that is only supported on Windows +// XP SP3 and above. +class PROTOBUF_EXPORT CriticalSectionLock { + public: + CriticalSectionLock() { InitializeCriticalSection(&critical_section_); } + ~CriticalSectionLock() { DeleteCriticalSection(&critical_section_); } + void lock() { EnterCriticalSection(&critical_section_); } + void unlock() { LeaveCriticalSection(&critical_section_); } + + private: + CRITICAL_SECTION critical_section_; + + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(CriticalSectionLock); +}; + +#endif + +// In MSVC std::mutex does not have a constexpr constructor. +// This wrapper makes the constructor constexpr. +template <typename T> +class CallOnceInitializedMutex { + public: + constexpr CallOnceInitializedMutex() : flag_{}, buf_{} {} + ~CallOnceInitializedMutex() { get().~T(); } + + void lock() { get().lock(); } + void unlock() { get().unlock(); } + + private: + T& get() { + std::call_once(flag_, [&] { ::new (static_cast<void*>(&buf_)) T(); }); + return reinterpret_cast<T&>(buf_); + } + + std::once_flag flag_; + alignas(T) char buf_[sizeof(T)]; +}; + +// Mutex is a natural type to wrap. As both google and other organization have +// specialized mutexes. gRPC also provides an injection mechanism for custom +// mutexes. +class GOOGLE_PROTOBUF_CAPABILITY("mutex") PROTOBUF_EXPORT WrappedMutex { + public: +#if defined(__QNX__) + constexpr WrappedMutex() = default; +#else + constexpr WrappedMutex() {} +#endif + void Lock() GOOGLE_PROTOBUF_ACQUIRE() { mu_.lock(); } + void Unlock() GOOGLE_PROTOBUF_RELEASE() { mu_.unlock(); } + // Crash if this Mutex is not held exclusively by this thread. + // May fail to crash when it should; will never crash when it should not. + void AssertHeld() const {} + + private: +#if defined(GOOGLE_PROTOBUF_SUPPORT_WINDOWS_XP) + CallOnceInitializedMutex<CriticalSectionLock> mu_{}; +#elif defined(_WIN32) + CallOnceInitializedMutex<std::mutex> mu_{}; +#else + std::mutex mu_{}; +#endif +}; + +using Mutex = WrappedMutex; + +// MutexLock(mu) acquires mu when constructed and releases it when destroyed. +class GOOGLE_PROTOBUF_SCOPED_CAPABILITY PROTOBUF_EXPORT MutexLock { + public: + explicit MutexLock(Mutex* mu) GOOGLE_PROTOBUF_ACQUIRE(mu) : mu_(mu) { + this->mu_->Lock(); + } + ~MutexLock() GOOGLE_PROTOBUF_RELEASE() { this->mu_->Unlock(); } + + private: + Mutex *const mu_; + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MutexLock); +}; + +// TODO(kenton): Implement these? Hard to implement portably. +typedef MutexLock ReaderMutexLock; +typedef MutexLock WriterMutexLock; + +// MutexLockMaybe is like MutexLock, but is a no-op when mu is nullptr. +class PROTOBUF_EXPORT MutexLockMaybe { + public: + explicit MutexLockMaybe(Mutex *mu) : + mu_(mu) { if (this->mu_ != nullptr) { this->mu_->Lock(); } } + ~MutexLockMaybe() { if (this->mu_ != nullptr) { this->mu_->Unlock(); } } + private: + Mutex *const mu_; + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MutexLockMaybe); +}; + +#if defined(GOOGLE_PROTOBUF_NO_THREADLOCAL) +template<typename T> +class ThreadLocalStorage { + public: + ThreadLocalStorage() { + pthread_key_create(&key_, &ThreadLocalStorage::Delete); + } + ~ThreadLocalStorage() { + pthread_key_delete(key_); + } + T* Get() { + T* result = static_cast<T*>(pthread_getspecific(key_)); + if (result == nullptr) { + result = new T(); + pthread_setspecific(key_, result); + } + return result; + } + private: + static void Delete(void* value) { + delete static_cast<T*>(value); + } + pthread_key_t key_; + + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ThreadLocalStorage); +}; +#endif + +} // namespace internal + +// We made these internal so that they would show up as such in the docs, +// but we don't want to stick "internal::" in front of them everywhere. +using internal::Mutex; +using internal::MutexLock; +using internal::ReaderMutexLock; +using internal::WriterMutexLock; +using internal::MutexLockMaybe; + +} // namespace protobuf +} // namespace google + +#undef GOOGLE_PROTOBUF_ACQUIRE +#undef GOOGLE_PROTOBUF_RELEASE + +#include <google/protobuf/port_undef.inc> + +#endif // GOOGLE_PROTOBUF_STUBS_MUTEX_H_ diff --git a/toolkit/components/protobuf/src/google/protobuf/stubs/once.h b/toolkit/components/protobuf/src/google/protobuf/stubs/once.h new file mode 100644 index 0000000000..070d36d193 --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/stubs/once.h @@ -0,0 +1,55 @@ +// 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. + +#ifndef GOOGLE_PROTOBUF_STUBS_ONCE_H__ +#define GOOGLE_PROTOBUF_STUBS_ONCE_H__ + +#include <mutex> +#include <utility> + +#include <google/protobuf/port_def.inc> + +namespace google { +namespace protobuf { +namespace internal { + +using once_flag = std::once_flag; +template <typename... Args> +void call_once(Args&&... args ) { + std::call_once(std::forward<Args>(args)...); +} + +} // namespace internal +} // namespace protobuf +} // namespace google + +#include <google/protobuf/port_undef.inc> + +#endif // GOOGLE_PROTOBUF_STUBS_ONCE_H__ diff --git a/toolkit/components/protobuf/src/google/protobuf/stubs/platform_macros.h b/toolkit/components/protobuf/src/google/protobuf/stubs/platform_macros.h new file mode 100644 index 0000000000..24799600dc --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/stubs/platform_macros.h @@ -0,0 +1,138 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2012 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. + +#ifndef GOOGLE_PROTOBUF_PLATFORM_MACROS_H_ +#define GOOGLE_PROTOBUF_PLATFORM_MACROS_H_ + +#define GOOGLE_PROTOBUF_PLATFORM_ERROR \ +#error "Host platform was not detected as supported by protobuf" + +// Processor architecture detection. For more info on what's defined, see: +// http://msdn.microsoft.com/en-us/library/b0084kay.aspx +// http://www.agner.org/optimize/calling_conventions.pdf +// or with gcc, run: "echo | gcc -E -dM -" +#if defined(_M_X64) || defined(__x86_64__) +#define GOOGLE_PROTOBUF_ARCH_X64 1 +#define GOOGLE_PROTOBUF_ARCH_64_BIT 1 +#elif defined(_M_IX86) || defined(__i386__) +#define GOOGLE_PROTOBUF_ARCH_IA32 1 +#define GOOGLE_PROTOBUF_ARCH_32_BIT 1 +#elif defined(__QNX__) +#define GOOGLE_PROTOBUF_ARCH_ARM_QNX 1 +#if defined(__aarch64__) +#define GOOGLE_PROTOBUF_ARCH_64_BIT 1 +#else +#define GOOGLE_PROTOBUF_ARCH_32_BIT 1 +#endif +#elif defined(_M_ARM) || defined(__ARMEL__) +#define GOOGLE_PROTOBUF_ARCH_ARM 1 +#define GOOGLE_PROTOBUF_ARCH_32_BIT 1 +#elif defined(_M_ARM64) +#define GOOGLE_PROTOBUF_ARCH_ARM 1 +#define GOOGLE_PROTOBUF_ARCH_64_BIT 1 +#elif defined(__aarch64__) +#define GOOGLE_PROTOBUF_ARCH_AARCH64 1 +#define GOOGLE_PROTOBUF_ARCH_64_BIT 1 +#elif defined(__mips__) +#if defined(__LP64__) +#define GOOGLE_PROTOBUF_ARCH_MIPS64 1 +#define GOOGLE_PROTOBUF_ARCH_64_BIT 1 +#else +#define GOOGLE_PROTOBUF_ARCH_MIPS 1 +#define GOOGLE_PROTOBUF_ARCH_32_BIT 1 +#endif +#elif defined(__pnacl__) +#define GOOGLE_PROTOBUF_ARCH_32_BIT 1 +#elif defined(sparc) +#define GOOGLE_PROTOBUF_ARCH_SPARC 1 +#if defined(__sparc_v9__) || defined(__sparcv9) || defined(__arch64__) +#define GOOGLE_PROTOBUF_ARCH_64_BIT 1 +#else +#define GOOGLE_PROTOBUF_ARCH_32_BIT 1 +#endif +#elif defined(_POWER) || defined(__powerpc64__) || defined(__PPC64__) +#define GOOGLE_PROTOBUF_ARCH_POWER 1 +#define GOOGLE_PROTOBUF_ARCH_64_BIT 1 +#elif defined(__PPC__) +#define GOOGLE_PROTOBUF_ARCH_PPC 1 +#define GOOGLE_PROTOBUF_ARCH_32_BIT 1 +#elif defined(__GNUC__) +# if (((__GNUC__ == 4) && (__GNUC_MINOR__ >= 7)) || (__GNUC__ > 4)) +// We fallback to the generic Clang/GCC >= 4.7 implementation in atomicops.h +# elif defined(__clang__) +# if !__has_extension(c_atomic) +GOOGLE_PROTOBUF_PLATFORM_ERROR +# endif +// We fallback to the generic Clang/GCC >= 4.7 implementation in atomicops.h +# endif +# if __LP64__ +# define GOOGLE_PROTOBUF_ARCH_64_BIT 1 +# else +# define GOOGLE_PROTOBUF_ARCH_32_BIT 1 +# endif +#else +GOOGLE_PROTOBUF_PLATFORM_ERROR +#endif + +#if defined(__APPLE__) +#define GOOGLE_PROTOBUF_OS_APPLE +#include <Availability.h> +#include <TargetConditionals.h> +#if TARGET_OS_IPHONE +#define GOOGLE_PROTOBUF_OS_IPHONE +#endif +#elif defined(__EMSCRIPTEN__) +#define GOOGLE_PROTOBUF_OS_EMSCRIPTEN +#elif defined(__native_client__) +#define GOOGLE_PROTOBUF_OS_NACL +#elif defined(sun) +#define GOOGLE_PROTOBUF_OS_SOLARIS +#elif defined(_AIX) +#define GOOGLE_PROTOBUF_OS_AIX +#elif defined(__ANDROID__) +#define GOOGLE_PROTOBUF_OS_ANDROID +#endif + +#undef GOOGLE_PROTOBUF_PLATFORM_ERROR + +#if defined(GOOGLE_PROTOBUF_OS_ANDROID) || defined(GOOGLE_PROTOBUF_OS_IPHONE) || defined(__OpenBSD__) +// Android ndk does not support the __thread keyword very well yet. Here +// we use pthread_key_create()/pthread_getspecific()/... methods for +// TLS support on android. +// iOS and OpenBSD also do not support the __thread keyword. +#define GOOGLE_PROTOBUF_NO_THREADLOCAL +#endif + +#if defined(__MAC_OS_X_VERSION_MIN_REQUIRED) && __MAC_OS_X_VERSION_MIN_REQUIRED < 1070 +// __thread keyword requires at least 10.7 +#define GOOGLE_PROTOBUF_NO_THREADLOCAL +#endif + +#endif // GOOGLE_PROTOBUF_PLATFORM_MACROS_H_ diff --git a/toolkit/components/protobuf/src/google/protobuf/stubs/port.h b/toolkit/components/protobuf/src/google/protobuf/stubs/port.h new file mode 100644 index 0000000000..b074cb1630 --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/stubs/port.h @@ -0,0 +1,413 @@ +// 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. + +#ifndef GOOGLE_PROTOBUF_STUBS_PORT_H_ +#define GOOGLE_PROTOBUF_STUBS_PORT_H_ + +#include <assert.h> +#include <cstdint> +#include <stdlib.h> +#include <cstddef> +#include <string> +#include <string.h> + +#include <google/protobuf/stubs/platform_macros.h> + +#include <google/protobuf/port_def.inc> + +#undef PROTOBUF_LITTLE_ENDIAN +#ifdef _WIN32 + // Assuming windows is always little-endian. + // TODO(xiaofeng): The PROTOBUF_LITTLE_ENDIAN is not only used for + // optimization but also for correctness. We should define an + // different macro to test the big-endian code path in coded_stream. + #if !defined(PROTOBUF_DISABLE_LITTLE_ENDIAN_OPT_FOR_TEST) + #define PROTOBUF_LITTLE_ENDIAN 1 + #endif +#if defined(_MSC_VER) && _MSC_VER >= 1300 && !defined(__INTEL_COMPILER) +// If MSVC has "/RTCc" set, it will complain about truncating casts at +// runtime. This file contains some intentional truncating casts. +#pragma runtime_checks("c", off) +#endif +#else +#ifdef __APPLE__ +#include <machine/endian.h> // __BYTE_ORDER +#elif defined(__FreeBSD__) +#include <sys/endian.h> // __BYTE_ORDER +#elif (defined(sun) || defined(__sun)) && (defined(__SVR4) || defined(__svr4__)) +#include <sys/isa_defs.h> // __BYTE_ORDER +#elif defined(_AIX) || defined(__TOS_AIX__) +#include <sys/machine.h> // BYTE_ORDER +#else +#if !defined(__QNX__) +#include <endian.h> // __BYTE_ORDER +#endif +#endif +#if ((defined(__LITTLE_ENDIAN__) && !defined(__BIG_ENDIAN__)) || \ + (defined(__BYTE_ORDER) && __BYTE_ORDER == __LITTLE_ENDIAN) || \ + (defined(BYTE_ORDER) && BYTE_ORDER == LITTLE_ENDIAN)) && \ + !defined(PROTOBUF_DISABLE_LITTLE_ENDIAN_OPT_FOR_TEST) +#define PROTOBUF_LITTLE_ENDIAN 1 +#endif +#endif + +// These #includes are for the byte swap functions declared later on. +#ifdef _MSC_VER +#include <stdlib.h> // NOLINT(build/include) +#include <intrin.h> +#elif defined(__APPLE__) +#include <libkern/OSByteOrder.h> +#elif defined(__linux__) || defined(__ANDROID__) || defined(__CYGWIN__) +#include <byteswap.h> // IWYU pragma: export +#endif + +// Legacy: some users reference these (internal-only) macros even though we +// don't need them any more. +#if defined(_MSC_VER) && defined(PROTOBUF_USE_DLLS) + #ifdef LIBPROTOBUF_EXPORTS + #define LIBPROTOBUF_EXPORT __declspec(dllexport) + #else + #define LIBPROTOBUF_EXPORT __declspec(dllimport) + #endif + #ifdef LIBPROTOC_EXPORTS + #define LIBPROTOC_EXPORT __declspec(dllexport) + #else + #define LIBPROTOC_EXPORT __declspec(dllimport) + #endif +#else + #define LIBPROTOBUF_EXPORT + #define LIBPROTOC_EXPORT +#endif + +#define PROTOBUF_RUNTIME_DEPRECATED(message) PROTOBUF_DEPRECATED_MSG(message) +#define GOOGLE_PROTOBUF_RUNTIME_DEPRECATED(message) \ + PROTOBUF_DEPRECATED_MSG(message) + +// =================================================================== +// from google3/base/port.h + +#if (defined(__GXX_EXPERIMENTAL_CXX0X__) || __cplusplus >= 201103L || \ + (defined(_MSC_VER) && _MSC_VER >= 1900)) +// Define this to 1 if the code is compiled in C++11 mode; leave it +// undefined otherwise. Do NOT define it to 0 -- that causes +// '#ifdef LANG_CXX11' to behave differently from '#if LANG_CXX11'. +#define LANG_CXX11 1 +#else +#error "Protobuf requires at least C++11." +#endif + +namespace google { +namespace protobuf { + +using ConstStringParam = const std::string &; + +typedef unsigned int uint; + +typedef int8_t int8; +typedef int16_t int16; +typedef int32_t int32; +typedef int64_t int64; + +typedef uint8_t uint8; +typedef uint16_t uint16; +typedef uint32_t uint32; +typedef uint64_t uint64; + +static const int32 kint32max = 0x7FFFFFFF; +static const int32 kint32min = -kint32max - 1; +static const int64 kint64max = int64_t{0x7FFFFFFFFFFFFFFF}; +static const int64 kint64min = -kint64max - 1; +static const uint32 kuint32max = 0xFFFFFFFFu; +static const uint64 kuint64max = uint64_t{0xFFFFFFFFFFFFFFFFu}; + +#if defined(ADDRESS_SANITIZER) || defined(THREAD_SANITIZER) ||\ + defined(MEMORY_SANITIZER) + +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus +uint16_t __sanitizer_unaligned_load16(const void *p); +uint32_t __sanitizer_unaligned_load32(const void *p); +uint64_t __sanitizer_unaligned_load64(const void *p); +void __sanitizer_unaligned_store16(void *p, uint16_t v); +void __sanitizer_unaligned_store32(void *p, uint32_t v); +void __sanitizer_unaligned_store64(void *p, uint64_t v); +#ifdef __cplusplus +} // extern "C" +#endif // __cplusplus + +inline uint16_t GOOGLE_UNALIGNED_LOAD16(const void *p) { + return __sanitizer_unaligned_load16(p); +} + +inline uint32_t GOOGLE_UNALIGNED_LOAD32(const void *p) { + return __sanitizer_unaligned_load32(p); +} + +inline uint64_t GOOGLE_UNALIGNED_LOAD64(const void *p) { + return __sanitizer_unaligned_load64(p); +} + +inline void GOOGLE_UNALIGNED_STORE16(void *p, uint16_t v) { + __sanitizer_unaligned_store16(p, v); +} + +inline void GOOGLE_UNALIGNED_STORE32(void *p, uint32_t v) { + __sanitizer_unaligned_store32(p, v); +} + +inline void GOOGLE_UNALIGNED_STORE64(void *p, uint64_t v) { + __sanitizer_unaligned_store64(p, v); +} + +#elif defined(GOOGLE_PROTOBUF_USE_UNALIGNED) && GOOGLE_PROTOBUF_USE_UNALIGNED + +#define GOOGLE_UNALIGNED_LOAD16(_p) (*reinterpret_cast<const uint16_t *>(_p)) +#define GOOGLE_UNALIGNED_LOAD32(_p) (*reinterpret_cast<const uint32_t *>(_p)) +#define GOOGLE_UNALIGNED_LOAD64(_p) (*reinterpret_cast<const uint64_t *>(_p)) + +#define GOOGLE_UNALIGNED_STORE16(_p, _val) (*reinterpret_cast<uint16_t *>(_p) = (_val)) +#define GOOGLE_UNALIGNED_STORE32(_p, _val) (*reinterpret_cast<uint32_t *>(_p) = (_val)) +#define GOOGLE_UNALIGNED_STORE64(_p, _val) (*reinterpret_cast<uint64_t *>(_p) = (_val)) + +#else +inline uint16_t GOOGLE_UNALIGNED_LOAD16(const void *p) { + uint16_t t; + memcpy(&t, p, sizeof t); + return t; +} + +inline uint32_t GOOGLE_UNALIGNED_LOAD32(const void *p) { + uint32_t t; + memcpy(&t, p, sizeof t); + return t; +} + +inline uint64_t GOOGLE_UNALIGNED_LOAD64(const void *p) { + uint64_t t; + memcpy(&t, p, sizeof t); + return t; +} + +inline void GOOGLE_UNALIGNED_STORE16(void *p, uint16_t v) { + memcpy(p, &v, sizeof v); +} + +inline void GOOGLE_UNALIGNED_STORE32(void *p, uint32_t v) { + memcpy(p, &v, sizeof v); +} + +inline void GOOGLE_UNALIGNED_STORE64(void *p, uint64_t v) { + memcpy(p, &v, sizeof v); +} +#endif + +#if defined(GOOGLE_PROTOBUF_OS_NACL) \ + || (defined(__ANDROID__) && defined(__clang__) \ + && (__clang_major__ == 3 && __clang_minor__ == 8) \ + && (__clang_patchlevel__ < 275480)) +# define GOOGLE_PROTOBUF_USE_PORTABLE_LOG2 +#endif + +// The following guarantees declaration of the byte swap functions. +#ifdef _MSC_VER +#define bswap_16(x) _byteswap_ushort(x) +#define bswap_32(x) _byteswap_ulong(x) +#define bswap_64(x) _byteswap_uint64(x) + +#elif defined(__APPLE__) +// Mac OS X / Darwin features +#define bswap_16(x) OSSwapInt16(x) +#define bswap_32(x) OSSwapInt32(x) +#define bswap_64(x) OSSwapInt64(x) + +#elif !defined(__linux__) && !defined(__ANDROID__) && !defined(__CYGWIN__) + +#ifndef bswap_16 +static inline uint16_t bswap_16(uint16_t x) { + return static_cast<uint16_t>(((x & 0xFF) << 8) | ((x & 0xFF00) >> 8)); +} +#define bswap_16(x) bswap_16(x) +#endif + +#ifndef bswap_32 +static inline uint32_t bswap_32(uint32_t x) { + return (((x & 0xFF) << 24) | + ((x & 0xFF00) << 8) | + ((x & 0xFF0000) >> 8) | + ((x & 0xFF000000) >> 24)); +} +#define bswap_32(x) bswap_32(x) +#endif + +#ifndef bswap_64 +static inline uint64_t bswap_64(uint64_t x) { + return (((x & uint64_t{0xFFu}) << 56) | ((x & uint64_t{0xFF00u}) << 40) | + ((x & uint64_t{0xFF0000u}) << 24) | + ((x & uint64_t{0xFF000000u}) << 8) | + ((x & uint64_t{0xFF00000000u}) >> 8) | + ((x & uint64_t{0xFF0000000000u}) >> 24) | + ((x & uint64_t{0xFF000000000000u}) >> 40) | + ((x & uint64_t{0xFF00000000000000u}) >> 56)); +} +#define bswap_64(x) bswap_64(x) +#endif + +#endif + +// =================================================================== +// from google3/util/bits/bits.h + +class Bits { + public: + static uint32_t Log2FloorNonZero(uint32_t n) { +#if defined(__GNUC__) + return 31 ^ static_cast<uint32_t>(__builtin_clz(n)); +#elif defined(_MSC_VER) + unsigned long where; + _BitScanReverse(&where, n); + return where; +#else + return Log2FloorNonZero_Portable(n); +#endif + } + + static uint32_t Log2FloorNonZero64(uint64_t n) { + // Older versions of clang run into an instruction-selection failure when + // it encounters __builtin_clzll: + // https://bugs.chromium.org/p/nativeclient/issues/detail?id=4395 + // This includes arm-nacl-clang and clang in older Android NDK versions. + // To work around this, when we build with those we use the portable + // implementation instead. +#if defined(__GNUC__) && !defined(GOOGLE_PROTOBUF_USE_PORTABLE_LOG2) + return 63 ^ static_cast<uint32_t>(__builtin_clzll(n)); +#elif defined(_MSC_VER) && defined(_M_X64) + unsigned long where; + _BitScanReverse64(&where, n); + return where; +#else + return Log2FloorNonZero64_Portable(n); +#endif + } + private: + static int Log2FloorNonZero_Portable(uint32_t n) { + if (n == 0) + return -1; + int log = 0; + uint32_t value = n; + for (int i = 4; i >= 0; --i) { + int shift = (1 << i); + uint32_t x = value >> shift; + if (x != 0) { + value = x; + log += shift; + } + } + assert(value == 1); + return log; + } + + static int Log2FloorNonZero64_Portable(uint64_t n) { + const uint32_t topbits = static_cast<uint32_t>(n >> 32); + if (topbits == 0) { + // Top bits are zero, so scan in bottom bits + return static_cast<int>(Log2FloorNonZero(static_cast<uint32_t>(n))); + } else { + return 32 + static_cast<int>(Log2FloorNonZero(topbits)); + } + } +}; + +// =================================================================== +// from google3/util/endian/endian.h +PROTOBUF_EXPORT uint32_t ghtonl(uint32_t x); + +class BigEndian { + public: +#ifdef PROTOBUF_LITTLE_ENDIAN + + static uint16_t FromHost16(uint16_t x) { return bswap_16(x); } + static uint16_t ToHost16(uint16_t x) { return bswap_16(x); } + + static uint32_t FromHost32(uint32_t x) { return bswap_32(x); } + static uint32_t ToHost32(uint32_t x) { return bswap_32(x); } + + static uint64_t FromHost64(uint64_t x) { return bswap_64(x); } + static uint64_t ToHost64(uint64_t x) { return bswap_64(x); } + + static bool IsLittleEndian() { return true; } + +#else + + static uint16_t FromHost16(uint16_t x) { return x; } + static uint16_t ToHost16(uint16_t x) { return x; } + + static uint32_t FromHost32(uint32_t x) { return x; } + static uint32_t ToHost32(uint32_t x) { return x; } + + static uint64_t FromHost64(uint64_t x) { return x; } + static uint64_t ToHost64(uint64_t x) { return x; } + + static bool IsLittleEndian() { return false; } + +#endif /* ENDIAN */ + + // Functions to do unaligned loads and stores in big-endian order. + static uint16_t Load16(const void *p) { + return ToHost16(GOOGLE_UNALIGNED_LOAD16(p)); + } + + static void Store16(void *p, uint16_t v) { + GOOGLE_UNALIGNED_STORE16(p, FromHost16(v)); + } + + static uint32_t Load32(const void *p) { + return ToHost32(GOOGLE_UNALIGNED_LOAD32(p)); + } + + static void Store32(void *p, uint32_t v) { + GOOGLE_UNALIGNED_STORE32(p, FromHost32(v)); + } + + static uint64_t Load64(const void *p) { + return ToHost64(GOOGLE_UNALIGNED_LOAD64(p)); + } + + static void Store64(void *p, uint64_t v) { + GOOGLE_UNALIGNED_STORE64(p, FromHost64(v)); + } +}; + +} // namespace protobuf +} // namespace google + +#include <google/protobuf/port_undef.inc> + +#endif // GOOGLE_PROTOBUF_STUBS_PORT_H_ diff --git a/toolkit/components/protobuf/src/google/protobuf/stubs/status.cc b/toolkit/components/protobuf/src/google/protobuf/stubs/status.cc new file mode 100644 index 0000000000..f5c0fa48f1 --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/stubs/status.cc @@ -0,0 +1,262 @@ +// 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. +#include <google/protobuf/stubs/status.h> + +#include <ostream> +#include <stdio.h> +#include <string> +#include <utility> + +namespace google { +namespace protobuf { +namespace util { +namespace status_internal { +namespace { + +inline std::string StatusCodeToString(StatusCode code) { + switch (code) { + case StatusCode::kOk: + return "OK"; + case StatusCode::kCancelled: + return "CANCELLED"; + case StatusCode::kUnknown: + return "UNKNOWN"; + case StatusCode::kInvalidArgument: + return "INVALID_ARGUMENT"; + case StatusCode::kDeadlineExceeded: + return "DEADLINE_EXCEEDED"; + case StatusCode::kNotFound: + return "NOT_FOUND"; + case StatusCode::kAlreadyExists: + return "ALREADY_EXISTS"; + case StatusCode::kPermissionDenied: + return "PERMISSION_DENIED"; + case StatusCode::kUnauthenticated: + return "UNAUTHENTICATED"; + case StatusCode::kResourceExhausted: + return "RESOURCE_EXHAUSTED"; + case StatusCode::kFailedPrecondition: + return "FAILED_PRECONDITION"; + case StatusCode::kAborted: + return "ABORTED"; + case StatusCode::kOutOfRange: + return "OUT_OF_RANGE"; + case StatusCode::kUnimplemented: + return "UNIMPLEMENTED"; + case StatusCode::kInternal: + return "INTERNAL"; + case StatusCode::kUnavailable: + return "UNAVAILABLE"; + case StatusCode::kDataLoss: + return "DATA_LOSS"; + } + + // No default clause, clang will abort if a code is missing from + // above switch. + return "UNKNOWN"; +} + +} // namespace + +Status::Status() : error_code_(StatusCode::kOk) {} + +Status::Status(StatusCode error_code, StringPiece error_message) + : error_code_(error_code) { + if (error_code != StatusCode::kOk) { + error_message_ = error_message.ToString(); + } +} + +Status::Status(const Status& other) + : error_code_(other.error_code_), error_message_(other.error_message_) { +} + +Status& Status::operator=(const Status& other) { + error_code_ = other.error_code_; + error_message_ = other.error_message_; + return *this; +} + +bool Status::operator==(const Status& x) const { + return error_code_ == x.error_code_ && + error_message_ == x.error_message_; +} + +std::string Status::ToString() const { + if (error_code_ == StatusCode::kOk) { + return "OK"; + } else { + if (error_message_.empty()) { + return StatusCodeToString(error_code_); + } else { + return StatusCodeToString(error_code_) + ":" + error_message_; + } + } +} + +Status OkStatus() { return Status(); } + +std::ostream& operator<<(std::ostream& os, const Status& x) { + os << x.ToString(); + return os; +} + +bool IsAborted(const Status& status) { + return status.code() == StatusCode::kAborted; +} + +bool IsAlreadyExists(const Status& status) { + return status.code() == StatusCode::kAlreadyExists; +} + +bool IsCancelled(const Status& status) { + return status.code() == StatusCode::kCancelled; +} + +bool IsDataLoss(const Status& status) { + return status.code() == StatusCode::kDataLoss; +} + +bool IsDeadlineExceeded(const Status& status) { + return status.code() == StatusCode::kDeadlineExceeded; +} + +bool IsFailedPrecondition(const Status& status) { + return status.code() == StatusCode::kFailedPrecondition; +} + +bool IsInternal(const Status& status) { + return status.code() == StatusCode::kInternal; +} + +bool IsInvalidArgument(const Status& status) { + return status.code() == StatusCode::kInvalidArgument; +} + +bool IsNotFound(const Status& status) { + return status.code() == StatusCode::kNotFound; +} + +bool IsOutOfRange(const Status& status) { + return status.code() == StatusCode::kOutOfRange; +} + +bool IsPermissionDenied(const Status& status) { + return status.code() == StatusCode::kPermissionDenied; +} + +bool IsResourceExhausted(const Status& status) { + return status.code() == StatusCode::kResourceExhausted; +} + +bool IsUnauthenticated(const Status& status) { + return status.code() == StatusCode::kUnauthenticated; +} + +bool IsUnavailable(const Status& status) { + return status.code() == StatusCode::kUnavailable; +} + +bool IsUnimplemented(const Status& status) { + return status.code() == StatusCode::kUnimplemented; +} + +bool IsUnknown(const Status& status) { + return status.code() == StatusCode::kUnknown; +} + +Status AbortedError(StringPiece message) { + return Status(StatusCode::kAborted, message); +} + +Status AlreadyExistsError(StringPiece message) { + return Status(StatusCode::kAlreadyExists, message); +} + +Status CancelledError(StringPiece message) { + return Status(StatusCode::kCancelled, message); +} + +Status DataLossError(StringPiece message) { + return Status(StatusCode::kDataLoss, message); +} + +Status DeadlineExceededError(StringPiece message) { + return Status(StatusCode::kDeadlineExceeded, message); +} + +Status FailedPreconditionError(StringPiece message) { + return Status(StatusCode::kFailedPrecondition, message); +} + +Status InternalError(StringPiece message) { + return Status(StatusCode::kInternal, message); +} + +Status InvalidArgumentError(StringPiece message) { + return Status(StatusCode::kInvalidArgument, message); +} + +Status NotFoundError(StringPiece message) { + return Status(StatusCode::kNotFound, message); +} + +Status OutOfRangeError(StringPiece message) { + return Status(StatusCode::kOutOfRange, message); +} + +Status PermissionDeniedError(StringPiece message) { + return Status(StatusCode::kPermissionDenied, message); +} + +Status ResourceExhaustedError(StringPiece message) { + return Status(StatusCode::kResourceExhausted, message); +} + +Status UnauthenticatedError(StringPiece message) { + return Status(StatusCode::kUnauthenticated, message); +} + +Status UnavailableError(StringPiece message) { + return Status(StatusCode::kUnavailable, message); +} + +Status UnimplementedError(StringPiece message) { + return Status(StatusCode::kUnimplemented, message); +} + +Status UnknownError(StringPiece message) { + return Status(StatusCode::kUnknown, message); +} + +} // namespace status_internal +} // namespace util +} // namespace protobuf +} // namespace google diff --git a/toolkit/components/protobuf/src/google/protobuf/stubs/status.h b/toolkit/components/protobuf/src/google/protobuf/stubs/status.h new file mode 100644 index 0000000000..c858cf6239 --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/stubs/status.h @@ -0,0 +1,196 @@ +// 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. + +#ifndef GOOGLE_PROTOBUF_STUBS_STATUS_H_ +#define GOOGLE_PROTOBUF_STUBS_STATUS_H_ + +#include <string> + +#include <google/protobuf/stubs/stringpiece.h> + +#include <google/protobuf/port_def.inc> + +namespace google { +namespace protobuf { +namespace util { +namespace status_internal { + +// These values must match error codes defined in google/rpc/code.proto. +enum class StatusCode : int { + kOk = 0, + kCancelled = 1, + kUnknown = 2, + kInvalidArgument = 3, + kDeadlineExceeded = 4, + kNotFound = 5, + kAlreadyExists = 6, + kPermissionDenied = 7, + kUnauthenticated = 16, + kResourceExhausted = 8, + kFailedPrecondition = 9, + kAborted = 10, + kOutOfRange = 11, + kUnimplemented = 12, + kInternal = 13, + kUnavailable = 14, + kDataLoss = 15, +}; + +class PROTOBUF_EXPORT Status { + public: + // Creates a "successful" status. + Status(); + + // Create a status in the canonical error space with the specified + // code, and error message. If "code == 0", error_message is + // ignored and a Status object identical to Status::kOk is + // constructed. + Status(StatusCode error_code, StringPiece error_message); + Status(const Status&); + Status& operator=(const Status& x); + ~Status() {} + + // Accessor + bool ok() const { return error_code_ == StatusCode::kOk; } + StatusCode code() const { return error_code_; } + StringPiece message() const { + return error_message_; + } + + bool operator==(const Status& x) const; + bool operator!=(const Status& x) const { + return !operator==(x); + } + + // Return a combination of the error code name and message. + std::string ToString() const; + + private: + StatusCode error_code_; + std::string error_message_; +}; + +// Returns an OK status, equivalent to a default constructed instance. Prefer +// usage of `OkStatus()` when constructing such an OK status. +PROTOBUF_EXPORT Status OkStatus(); + +// Prints a human-readable representation of 'x' to 'os'. +PROTOBUF_EXPORT std::ostream& operator<<(std::ostream& os, const Status& x); + +// These convenience functions return `true` if a given status matches the +// `StatusCode` error code of its associated function. +PROTOBUF_EXPORT bool IsAborted(const Status& status); +PROTOBUF_EXPORT bool IsAlreadyExists(const Status& status); +PROTOBUF_EXPORT bool IsCancelled(const Status& status); +PROTOBUF_EXPORT bool IsDataLoss(const Status& status); +PROTOBUF_EXPORT bool IsDeadlineExceeded(const Status& status); +PROTOBUF_EXPORT bool IsFailedPrecondition(const Status& status); +PROTOBUF_EXPORT bool IsInternal(const Status& status); +PROTOBUF_EXPORT bool IsInvalidArgument(const Status& status); +PROTOBUF_EXPORT bool IsNotFound(const Status& status); +PROTOBUF_EXPORT bool IsOutOfRange(const Status& status); +PROTOBUF_EXPORT bool IsPermissionDenied(const Status& status); +PROTOBUF_EXPORT bool IsResourceExhausted(const Status& status); +PROTOBUF_EXPORT bool IsUnauthenticated(const Status& status); +PROTOBUF_EXPORT bool IsUnavailable(const Status& status); +PROTOBUF_EXPORT bool IsUnimplemented(const Status& status); +PROTOBUF_EXPORT bool IsUnknown(const Status& status); + +// These convenience functions create an `Status` object with an error code as +// indicated by the associated function name, using the error message passed in +// `message`. +// +// These functions are intentionally named `*Error` rather than `*Status` to +// match the names from Abseil: +// https://github.com/abseil/abseil-cpp/blob/2e9532cc6c701a8323d0cffb468999ab804095ab/absl/status/status.h#L716 +PROTOBUF_EXPORT Status AbortedError(StringPiece message); +PROTOBUF_EXPORT Status AlreadyExistsError(StringPiece message); +PROTOBUF_EXPORT Status CancelledError(StringPiece message); +PROTOBUF_EXPORT Status DataLossError(StringPiece message); +PROTOBUF_EXPORT Status DeadlineExceededError(StringPiece message); +PROTOBUF_EXPORT Status FailedPreconditionError(StringPiece message); +PROTOBUF_EXPORT Status InternalError(StringPiece message); +PROTOBUF_EXPORT Status InvalidArgumentError(StringPiece message); +PROTOBUF_EXPORT Status NotFoundError(StringPiece message); +PROTOBUF_EXPORT Status OutOfRangeError(StringPiece message); +PROTOBUF_EXPORT Status PermissionDeniedError(StringPiece message); +PROTOBUF_EXPORT Status ResourceExhaustedError(StringPiece message); +PROTOBUF_EXPORT Status UnauthenticatedError(StringPiece message); +PROTOBUF_EXPORT Status UnavailableError(StringPiece message); +PROTOBUF_EXPORT Status UnimplementedError(StringPiece message); +PROTOBUF_EXPORT Status UnknownError(StringPiece message); + +} // namespace status_internal + +using ::google::protobuf::util::status_internal::Status; +using ::google::protobuf::util::status_internal::StatusCode; + +using ::google::protobuf::util::status_internal::IsAborted; +using ::google::protobuf::util::status_internal::IsAlreadyExists; +using ::google::protobuf::util::status_internal::IsCancelled; +using ::google::protobuf::util::status_internal::IsDataLoss; +using ::google::protobuf::util::status_internal::IsDeadlineExceeded; +using ::google::protobuf::util::status_internal::IsFailedPrecondition; +using ::google::protobuf::util::status_internal::IsInternal; +using ::google::protobuf::util::status_internal::IsInvalidArgument; +using ::google::protobuf::util::status_internal::IsNotFound; +using ::google::protobuf::util::status_internal::IsOutOfRange; +using ::google::protobuf::util::status_internal::IsPermissionDenied; +using ::google::protobuf::util::status_internal::IsResourceExhausted; +using ::google::protobuf::util::status_internal::IsUnauthenticated; +using ::google::protobuf::util::status_internal::IsUnavailable; +using ::google::protobuf::util::status_internal::IsUnimplemented; +using ::google::protobuf::util::status_internal::IsUnknown; + +using ::google::protobuf::util::status_internal::AbortedError; +using ::google::protobuf::util::status_internal::AlreadyExistsError; +using ::google::protobuf::util::status_internal::CancelledError; +using ::google::protobuf::util::status_internal::DataLossError; +using ::google::protobuf::util::status_internal::DeadlineExceededError; +using ::google::protobuf::util::status_internal::FailedPreconditionError; +using ::google::protobuf::util::status_internal::InternalError; +using ::google::protobuf::util::status_internal::InvalidArgumentError; +using ::google::protobuf::util::status_internal::NotFoundError; +using ::google::protobuf::util::status_internal::OkStatus; +using ::google::protobuf::util::status_internal::OutOfRangeError; +using ::google::protobuf::util::status_internal::PermissionDeniedError; +using ::google::protobuf::util::status_internal::ResourceExhaustedError; +using ::google::protobuf::util::status_internal::UnauthenticatedError; +using ::google::protobuf::util::status_internal::UnavailableError; +using ::google::protobuf::util::status_internal::UnimplementedError; +using ::google::protobuf::util::status_internal::UnknownError; + +} // namespace util +} // namespace protobuf +} // namespace google + +#include <google/protobuf/port_undef.inc> + +#endif // GOOGLE_PROTOBUF_STUBS_STATUS_H_ diff --git a/toolkit/components/protobuf/src/google/protobuf/stubs/status_macros.h b/toolkit/components/protobuf/src/google/protobuf/stubs/status_macros.h new file mode 100644 index 0000000000..407ff4c280 --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/stubs/status_macros.h @@ -0,0 +1,89 @@ +// 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. + +// From: util/task/contrib/status_macros/status_macros.h + +#ifndef GOOGLE_PROTOBUF_STUBS_STATUS_MACROS_H_ +#define GOOGLE_PROTOBUF_STUBS_STATUS_MACROS_H_ + +#include <google/protobuf/stubs/common.h> +#include <google/protobuf/stubs/status.h> +#include <google/protobuf/stubs/statusor.h> + +namespace google { +namespace protobuf { +namespace util { + +// Run a command that returns a util::Status. If the called code returns an +// error status, return that status up out of this method too. +// +// Example: +// RETURN_IF_ERROR(DoThings(4)); +#define RETURN_IF_ERROR(expr) \ + do { \ + /* Using _status below to avoid capture problems if expr is "status". */ \ + const PROTOBUF_NAMESPACE_ID::util::Status _status = (expr); \ + if (PROTOBUF_PREDICT_FALSE(!_status.ok())) return _status; \ + } while (0) + +// Internal helper for concatenating macro values. +#define STATUS_MACROS_CONCAT_NAME_INNER(x, y) x##y +#define STATUS_MACROS_CONCAT_NAME(x, y) STATUS_MACROS_CONCAT_NAME_INNER(x, y) + +template<typename T> +Status DoAssignOrReturn(T& lhs, StatusOr<T> result) { + if (result.ok()) { + lhs = result.value(); + } + return result.status(); +} + +#define ASSIGN_OR_RETURN_IMPL(status, lhs, rexpr) \ + Status status = DoAssignOrReturn(lhs, (rexpr)); \ + if (PROTOBUF_PREDICT_FALSE(!status.ok())) return status; + +// Executes an expression that returns a util::StatusOr, extracting its value +// into the variable defined by lhs (or returning on error). +// +// Example: Assigning to an existing value +// ValueType value; +// ASSIGN_OR_RETURN(value, MaybeGetValue(arg)); +// +// WARNING: ASSIGN_OR_RETURN expands into multiple statements; it cannot be used +// in a single statement (e.g. as the body of an if statement without {})! +#define ASSIGN_OR_RETURN(lhs, rexpr) \ + ASSIGN_OR_RETURN_IMPL( \ + STATUS_MACROS_CONCAT_NAME(_status_or_value, __COUNTER__), lhs, rexpr); + +} // namespace util +} // namespace protobuf +} // namespace google + +#endif // GOOGLE_PROTOBUF_STUBS_STATUS_H_ diff --git a/toolkit/components/protobuf/src/google/protobuf/stubs/statusor.cc b/toolkit/components/protobuf/src/google/protobuf/stubs/statusor.cc new file mode 100644 index 0000000000..9c0a1782a8 --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/stubs/statusor.cc @@ -0,0 +1,48 @@ +// 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. + +#include <google/protobuf/stubs/statusor.h> + +#include <google/protobuf/stubs/logging.h> + +namespace google { +namespace protobuf { +namespace util { +namespace statusor_internal { + +void StatusOrHelper::Crash(const Status& status) { + GOOGLE_LOG(FATAL) << "Attempting to fetch value instead of handling error " + << status.ToString(); +} + +} // namespace statusor_internal +} // namespace util +} // namespace protobuf +} // namespace google diff --git a/toolkit/components/protobuf/src/google/protobuf/stubs/statusor.h b/toolkit/components/protobuf/src/google/protobuf/stubs/statusor.h new file mode 100644 index 0000000000..20e603ea04 --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/stubs/statusor.h @@ -0,0 +1,253 @@ +// 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. + +// StatusOr<T> is the union of a Status object and a T +// object. StatusOr models the concept of an object that is either a +// usable value, or an error Status explaining why such a value is +// not present. To this end, StatusOr<T> does not allow its Status +// value to be OkStatus(). Further, StatusOr<T*> does not allow the +// contained pointer to be nullptr. +// +// The primary use-case for StatusOr<T> is as the return value of a +// function which may fail. +// +// Example client usage for a StatusOr<T>, where T is not a pointer: +// +// StatusOr<float> result = DoBigCalculationThatCouldFail(); +// if (result.ok()) { +// float answer = result.value(); +// printf("Big calculation yielded: %f", answer); +// } else { +// LOG(ERROR) << result.status(); +// } +// +// Example client usage for a StatusOr<T*>: +// +// StatusOr<Foo*> result = FooFactory::MakeNewFoo(arg); +// if (result.ok()) { +// std::unique_ptr<Foo> foo(result.value()); +// foo->DoSomethingCool(); +// } else { +// LOG(ERROR) << result.status(); +// } +// +// Example factory implementation returning StatusOr<T*>: +// +// StatusOr<Foo*> FooFactory::MakeNewFoo(int arg) { +// if (arg <= 0) { +// return InvalidArgumentError("Arg must be positive"); +// } else { +// return new Foo(arg); +// } +// } +// + +#ifndef GOOGLE_PROTOBUF_STUBS_STATUSOR_H_ +#define GOOGLE_PROTOBUF_STUBS_STATUSOR_H_ + +#include <new> +#include <string> +#include <utility> + +#include <google/protobuf/stubs/status.h> + +#include <google/protobuf/port_def.inc> + +namespace google { +namespace protobuf { +namespace util { +namespace statusor_internal { + +template<typename T> +class StatusOr { + template<typename U> friend class StatusOr; + + public: + using value_type = T; + + // Construct a new StatusOr with Status::UNKNOWN status. + // Construct a new StatusOr with UnknownError() status. + explicit StatusOr(); + + // Construct a new StatusOr with the given non-ok status. After calling + // this constructor, calls to value() will CHECK-fail. + // + // NOTE: Not explicit - we want to use StatusOr<T> as a return + // value, so it is convenient and sensible to be able to do 'return + // Status()' when the return type is StatusOr<T>. + // + // REQUIRES: status != OkStatus(). This requirement is DCHECKed. + // In optimized builds, passing OkStatus() here will have the effect + // of passing PosixErrorSpace::EINVAL as a fallback. + StatusOr(const Status& status); // NOLINT + + // Construct a new StatusOr with the given value. If T is a plain pointer, + // value must not be nullptr. After calling this constructor, calls to + // value() will succeed, and calls to status() will return OK. + // + // NOTE: Not explicit - we want to use StatusOr<T> as a return type + // so it is convenient and sensible to be able to do 'return T()' + // when when the return type is StatusOr<T>. + // + // REQUIRES: if T is a plain pointer, value != nullptr. This requirement is + // DCHECKed. In optimized builds, passing a null pointer here will have + // the effect of passing PosixErrorSpace::EINVAL as a fallback. + StatusOr(const T& value); // NOLINT + + // Copy constructor. + StatusOr(const StatusOr& other); + + // Conversion copy constructor, T must be copy constructible from U + template<typename U> + StatusOr(const StatusOr<U>& other); + + // Assignment operator. + StatusOr& operator=(const StatusOr& other); + + // Conversion assignment operator, T must be assignable from U + template<typename U> + StatusOr& operator=(const StatusOr<U>& other); + + // Returns a reference to our status. If this contains a T, then + // returns OkStatus(). + const Status& status() const; + + // Returns this->status().ok() + bool ok() const; + + // Returns a reference to our current value, or CHECK-fails if !this->ok(). + const T& value () const; + + private: + Status status_; + T value_; +}; + +//////////////////////////////////////////////////////////////////////////////// +// Implementation details for StatusOr<T> + +class PROTOBUF_EXPORT StatusOrHelper { + public: + // Move type-agnostic error handling to the .cc. + static void Crash(const util::Status& status); + + // Customized behavior for StatusOr<T> vs. StatusOr<T*> + template<typename T> + struct Specialize; +}; + +template<typename T> +struct StatusOrHelper::Specialize { + // For non-pointer T, a reference can never be nullptr. + static inline bool IsValueNull(const T& /*t*/) { return false; } +}; + +template<typename T> +struct StatusOrHelper::Specialize<T*> { + static inline bool IsValueNull(const T* t) { return t == nullptr; } +}; + +template <typename T> +inline StatusOr<T>::StatusOr() : status_(util::UnknownError("")) {} + +template<typename T> +inline StatusOr<T>::StatusOr(const Status& status) { + if (status.ok()) { + status_ = util::InternalError("OkStatus() is not a valid argument."); + } else { + status_ = status; + } +} + +template<typename T> +inline StatusOr<T>::StatusOr(const T& value) { + if (StatusOrHelper::Specialize<T>::IsValueNull(value)) { + status_ = util::InternalError("nullptr is not a valid argument."); + } else { + status_ = util::OkStatus(); + value_ = value; + } +} + +template<typename T> +inline StatusOr<T>::StatusOr(const StatusOr<T>& other) + : status_(other.status_), value_(other.value_) { +} + +template<typename T> +inline StatusOr<T>& StatusOr<T>::operator=(const StatusOr<T>& other) { + status_ = other.status_; + value_ = other.value_; + return *this; +} + +template<typename T> +template<typename U> +inline StatusOr<T>::StatusOr(const StatusOr<U>& other) + : status_(other.status_), value_(other.status_.ok() ? other.value_ : T()) { +} + +template<typename T> +template<typename U> +inline StatusOr<T>& StatusOr<T>::operator=(const StatusOr<U>& other) { + status_ = other.status_; + if (status_.ok()) value_ = other.value_; + return *this; +} + +template<typename T> +inline const Status& StatusOr<T>::status() const { + return status_; +} + +template<typename T> +inline bool StatusOr<T>::ok() const { + return status().ok(); +} + +template<typename T> +inline const T& StatusOr<T>::value() const { + if (!status_.ok()) { + StatusOrHelper::Crash(status_); + } + return value_; +} + +} // namespace statusor_internal + +using ::google::protobuf::util::statusor_internal::StatusOr; + +} // namespace util +} // namespace protobuf +} // namespace google + +#include <google/protobuf/port_undef.inc> + +#endif // GOOGLE_PROTOBUF_STUBS_STATUSOR_H_ diff --git a/toolkit/components/protobuf/src/google/protobuf/stubs/stl_util.h b/toolkit/components/protobuf/src/google/protobuf/stubs/stl_util.h new file mode 100644 index 0000000000..e6260d0760 --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/stubs/stl_util.h @@ -0,0 +1,90 @@ +// 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. + +// from google3/util/gtl/stl_util.h + +#ifndef GOOGLE_PROTOBUF_STUBS_STL_UTIL_H__ +#define GOOGLE_PROTOBUF_STUBS_STL_UTIL_H__ + +#include <google/protobuf/stubs/common.h> + +#include <algorithm> + +// Must be last. +#include <google/protobuf/port_def.inc> // NOLINT + +namespace google { +namespace protobuf { + +// Inside Google, this function implements a horrible, disgusting hack in which +// we reach into the string's private implementation and resize it without +// initializing the new bytes. In some cases doing this can significantly +// improve performance. However, since it's totally non-portable it has no +// place in open source code. Feel free to fill this function in with your +// own disgusting hack if you want the perf boost. +inline void STLStringResizeUninitialized(std::string* s, size_t new_size) { + s->resize(new_size); +} + +// As above, but we make sure to follow amortized growth in which we always +// increase the capacity by at least a constant factor >1. +inline void STLStringResizeUninitializedAmortized(std::string* s, + size_t new_size) { + const size_t cap = s->capacity(); + if (new_size > cap) { + // Make sure to always grow by at least a factor of 2x. + s->reserve(std::max<size_t>(new_size, 2 * cap)); + } + STLStringResizeUninitialized(s, new_size); +} + +// Return a mutable char* pointing to a string's internal buffer, +// which may not be null-terminated. Writing through this pointer will +// modify the string. +// +// string_as_array(&str)[i] is valid for 0 <= i < str.size() until the +// next call to a string method that invalidates iterators. +// +// As of 2006-04, there is no standard-blessed way of getting a +// mutable reference to a string's internal buffer. However, issue 530 +// (http://www.open-std.org/JTC1/SC22/WG21/docs/lwg-active.html#530) +// proposes this as the method. According to Matt Austern, this should +// already work on all current implementations. +inline char* string_as_array(std::string* str) { + // DO NOT USE const_cast<char*>(str->data())! See the unittest for why. + return str->empty() ? nullptr : &*str->begin(); +} + +} // namespace protobuf +} // namespace google + +#include <google/protobuf/port_undef.inc> // NOLINT + +#endif // GOOGLE_PROTOBUF_STUBS_STL_UTIL_H__ diff --git a/toolkit/components/protobuf/src/google/protobuf/stubs/stringpiece.cc b/toolkit/components/protobuf/src/google/protobuf/stubs/stringpiece.cc new file mode 100644 index 0000000000..71880464c7 --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/stubs/stringpiece.cc @@ -0,0 +1,256 @@ +// 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. +#include <google/protobuf/stubs/stringpiece.h> + +#include <string.h> +#include <algorithm> +#include <climits> +#include <string> +#include <ostream> + +#include <google/protobuf/stubs/logging.h> + +namespace google { +namespace protobuf { +namespace stringpiece_internal { + +std::ostream& operator<<(std::ostream& o, StringPiece piece) { + o.write(piece.data(), piece.size()); + return o; +} + +void StringPiece::LogFatalSizeTooBig(size_t size, const char* details) { + GOOGLE_LOG(FATAL) << "size too big: " << size << " details: " << details; +} + +void StringPiece::CopyToString(std::string* target) const { + target->assign(ptr_, length_); +} + +void StringPiece::AppendToString(std::string* target) const { + target->append(ptr_, length_); +} + +bool StringPiece::Consume(StringPiece x) { + if (starts_with(x)) { + ptr_ += x.length_; + length_ -= x.length_; + return true; + } + return false; +} + +bool StringPiece::ConsumeFromEnd(StringPiece x) { + if (ends_with(x)) { + length_ -= x.length_; + return true; + } + return false; +} + +StringPiece::size_type StringPiece::copy(char* buf, size_type n, + size_type pos) const { + size_type ret = std::min(length_ - pos, n); + memcpy(buf, ptr_ + pos, ret); + return ret; +} + +bool StringPiece::contains(StringPiece s) const { + return find(s, 0) != npos; +} + +StringPiece::size_type StringPiece::find(StringPiece s, size_type pos) const { + if (length_ <= 0 || pos > static_cast<size_type>(length_)) { + if (length_ == 0 && pos == 0 && s.length_ == 0) return 0; + return npos; + } + const char *result = std::search(ptr_ + pos, ptr_ + length_, + s.ptr_, s.ptr_ + s.length_); + return result == ptr_ + length_ ? npos : result - ptr_; +} + +StringPiece::size_type StringPiece::find(char c, size_type pos) const { + if (length_ <= 0 || pos >= static_cast<size_type>(length_)) { + return npos; + } + const char* result = static_cast<const char*>( + memchr(ptr_ + pos, c, length_ - pos)); + return result != nullptr ? result - ptr_ : npos; +} + +StringPiece::size_type StringPiece::rfind(StringPiece s, size_type pos) const { + if (length_ < s.length_) return npos; + const size_t ulen = length_; + if (s.length_ == 0) return std::min(ulen, pos); + + const char* last = ptr_ + std::min(ulen - s.length_, pos) + s.length_; + const char* result = std::find_end(ptr_, last, s.ptr_, s.ptr_ + s.length_); + return result != last ? result - ptr_ : npos; +} + +// Search range is [0..pos] inclusive. If pos == npos, search everything. +StringPiece::size_type StringPiece::rfind(char c, size_type pos) const { + // Note: memrchr() is not available on Windows. + if (empty()) return npos; + for (size_type i = std::min(pos, length_ - 1);; --i) { + if (ptr_[i] == c) { + return i; + } + if (i == 0) break; + } + return npos; +} + +// For each character in characters_wanted, sets the index corresponding +// to the ASCII code of that character to 1 in table. This is used by +// the find_.*_of methods below to tell whether or not a character is in +// the lookup table in constant time. +// The argument `table' must be an array that is large enough to hold all +// the possible values of an unsigned char. Thus it should be be declared +// as follows: +// bool table[UCHAR_MAX + 1] +static inline void BuildLookupTable(StringPiece characters_wanted, + bool* table) { + const StringPiece::size_type length = characters_wanted.length(); + const char* const data = characters_wanted.data(); + for (StringPiece::size_type i = 0; i < length; ++i) { + table[static_cast<unsigned char>(data[i])] = true; + } +} + +StringPiece::size_type StringPiece::find_first_of(StringPiece s, + size_type pos) const { + if (empty() || s.empty()) { + return npos; + } + // Avoid the cost of BuildLookupTable() for a single-character search. + if (s.length_ == 1) return find_first_of(s.ptr_[0], pos); + + bool lookup[UCHAR_MAX + 1] = { false }; + BuildLookupTable(s, lookup); + for (size_type i = pos; i < length_; ++i) { + if (lookup[static_cast<unsigned char>(ptr_[i])]) { + return i; + } + } + return npos; +} + +StringPiece::size_type StringPiece::find_first_not_of(StringPiece s, + size_type pos) const { + if (empty()) return npos; + if (s.empty()) return 0; + // Avoid the cost of BuildLookupTable() for a single-character search. + if (s.length_ == 1) return find_first_not_of(s.ptr_[0], pos); + + bool lookup[UCHAR_MAX + 1] = { false }; + BuildLookupTable(s, lookup); + for (size_type i = pos; i < length_; ++i) { + if (!lookup[static_cast<unsigned char>(ptr_[i])]) { + return i; + } + } + return npos; +} + +StringPiece::size_type StringPiece::find_first_not_of(char c, + size_type pos) const { + if (empty()) return npos; + + for (; pos < static_cast<size_type>(length_); ++pos) { + if (ptr_[pos] != c) { + return pos; + } + } + return npos; +} + +StringPiece::size_type StringPiece::find_last_of(StringPiece s, + size_type pos) const { + if (empty() || s.empty()) return npos; + // Avoid the cost of BuildLookupTable() for a single-character search. + if (s.length_ == 1) return find_last_of(s.ptr_[0], pos); + + bool lookup[UCHAR_MAX + 1] = { false }; + BuildLookupTable(s, lookup); + for (size_type i = std::min(pos, length_ - 1);; --i) { + if (lookup[static_cast<unsigned char>(ptr_[i])]) { + return i; + } + if (i == 0) break; + } + return npos; +} + +StringPiece::size_type StringPiece::find_last_not_of(StringPiece s, + size_type pos) const { + if (empty()) return npos; + + size_type i = std::min(pos, length() - 1); + if (s.empty()) return i; + + // Avoid the cost of BuildLookupTable() for a single-character search. + if (s.length_ == 1) return find_last_not_of(s.ptr_[0], pos); + + bool lookup[UCHAR_MAX + 1] = { false }; + BuildLookupTable(s, lookup); + for (;; --i) { + if (!lookup[static_cast<unsigned char>(ptr_[i])]) { + return i; + } + if (i == 0) break; + } + return npos; +} + +StringPiece::size_type StringPiece::find_last_not_of(char c, + size_type pos) const { + if (empty()) return npos; + size_type i = std::min(pos, length_ - 1); + for (;; --i) { + if (ptr_[i] != c) { + return i; + } + if (i == 0) break; + } + return npos; +} + +StringPiece StringPiece::substr(size_type pos, size_type n) const { + if (pos > length()) pos = length(); + if (n > length_ - pos) n = length() - pos; + return StringPiece(ptr_ + pos, n); +} + +const StringPiece::size_type StringPiece::npos = size_type(-1); + +} // namespace stringpiece_internal +} // namespace protobuf +} // namespace google diff --git a/toolkit/components/protobuf/src/google/protobuf/stubs/stringpiece.h b/toolkit/components/protobuf/src/google/protobuf/stubs/stringpiece.h new file mode 100644 index 0000000000..c63e25b254 --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/stubs/stringpiece.h @@ -0,0 +1,402 @@ +// 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. + +// A StringPiece points to part or all of a string, Cord, double-quoted string +// literal, or other string-like object. A StringPiece does *not* own the +// string to which it points. A StringPiece is not null-terminated. +// +// You can use StringPiece as a function or method parameter. A StringPiece +// parameter can receive a double-quoted string literal argument, a "const +// char*" argument, a string argument, or a StringPiece argument with no data +// copying. Systematic use of StringPiece for arguments reduces data +// copies and strlen() calls. +// +// Prefer passing StringPieces by value: +// void MyFunction(StringPiece arg); +// If circumstances require, you may also pass by const reference: +// void MyFunction(const StringPiece& arg); // not preferred +// Both of these have the same lifetime semantics. Passing by value +// generates slightly smaller code. For more discussion, see the thread +// go/stringpiecebyvalue on c-users. +// +// StringPiece is also suitable for local variables if you know that +// the lifetime of the underlying object is longer than the lifetime +// of your StringPiece variable. +// +// Beware of binding a StringPiece to a temporary: +// StringPiece sp = obj.MethodReturningString(); // BAD: lifetime problem +// +// This code is okay: +// string str = obj.MethodReturningString(); // str owns its contents +// StringPiece sp(str); // GOOD, because str outlives sp +// +// StringPiece is sometimes a poor choice for a return value and usually a poor +// choice for a data member. If you do use a StringPiece this way, it is your +// responsibility to ensure that the object pointed to by the StringPiece +// outlives the StringPiece. +// +// A StringPiece may represent just part of a string; thus the name "Piece". +// For example, when splitting a string, vector<StringPiece> is a natural data +// type for the output. For another example, a Cord is a non-contiguous, +// potentially very long string-like object. The Cord class has an interface +// that iteratively provides StringPiece objects that point to the +// successive pieces of a Cord object. +// +// A StringPiece is not null-terminated. If you write code that scans a +// StringPiece, you must check its length before reading any characters. +// Common idioms that work on null-terminated strings do not work on +// StringPiece objects. +// +// There are several ways to create a null StringPiece: +// StringPiece() +// StringPiece(nullptr) +// StringPiece(nullptr, 0) +// For all of the above, sp.data() == nullptr, sp.length() == 0, +// and sp.empty() == true. Also, if you create a StringPiece with +// a non-null pointer then sp.data() != nullptr. Once created, +// sp.data() will stay either nullptr or not-nullptr, except if you call +// sp.clear() or sp.set(). +// +// Thus, you can use StringPiece(nullptr) to signal an out-of-band value +// that is different from other StringPiece values. This is similar +// to the way that const char* p1 = nullptr; is different from +// const char* p2 = "";. +// +// There are many ways to create an empty StringPiece: +// StringPiece() +// StringPiece(nullptr) +// StringPiece(nullptr, 0) +// StringPiece("") +// StringPiece("", 0) +// StringPiece("abcdef", 0) +// StringPiece("abcdef"+6, 0) +// For all of the above, sp.length() will be 0 and sp.empty() will be true. +// For some empty StringPiece values, sp.data() will be nullptr. +// For some empty StringPiece values, sp.data() will not be nullptr. +// +// Be careful not to confuse: null StringPiece and empty StringPiece. +// The set of empty StringPieces properly includes the set of null StringPieces. +// That is, every null StringPiece is an empty StringPiece, +// but some non-null StringPieces are empty Stringpieces too. +// +// All empty StringPiece values compare equal to each other. +// Even a null StringPieces compares equal to a non-null empty StringPiece: +// StringPiece() == StringPiece("", 0) +// StringPiece(nullptr) == StringPiece("abc", 0) +// StringPiece(nullptr, 0) == StringPiece("abcdef"+6, 0) +// +// Look carefully at this example: +// StringPiece("") == nullptr +// True or false? TRUE, because StringPiece::operator== converts +// the right-hand side from nullptr to StringPiece(nullptr), +// and then compares two zero-length spans of characters. +// However, we are working to make this example produce a compile error. +// +// Suppose you want to write: +// bool TestWhat?(StringPiece sp) { return sp == nullptr; } // BAD +// Do not do that. Write one of these instead: +// bool TestNull(StringPiece sp) { return sp.data() == nullptr; } +// bool TestEmpty(StringPiece sp) { return sp.empty(); } +// The intent of TestWhat? is unclear. Did you mean TestNull or TestEmpty? +// Right now, TestWhat? behaves likes TestEmpty. +// We are working to make TestWhat? produce a compile error. +// TestNull is good to test for an out-of-band signal. +// TestEmpty is good to test for an empty StringPiece. +// +// Caveats (again): +// (1) The lifetime of the pointed-to string (or piece of a string) +// must be longer than the lifetime of the StringPiece. +// (2) There may or may not be a '\0' character after the end of +// StringPiece data. +// (3) A null StringPiece is empty. +// An empty StringPiece may or may not be a null StringPiece. + +#ifndef GOOGLE_PROTOBUF_STUBS_STRINGPIECE_H_ +#define GOOGLE_PROTOBUF_STUBS_STRINGPIECE_H_ + +#include <assert.h> +#include <stddef.h> +#include <string.h> +#include <iosfwd> +#include <limits> +#include <string> + +#if defined(__cpp_lib_string_view) +#include <string_view> +#endif + +#include <google/protobuf/stubs/hash.h> + +#include <google/protobuf/port_def.inc> + +namespace google { +namespace protobuf { +namespace stringpiece_internal { + +class PROTOBUF_EXPORT StringPiece { + public: + using traits_type = std::char_traits<char>; + using value_type = char; + using pointer = char*; + using const_pointer = const char*; + using reference = char&; + using const_reference = const char&; + using const_iterator = const char*; + using iterator = const_iterator; + using const_reverse_iterator = std::reverse_iterator<const_iterator>; + using reverse_iterator = const_reverse_iterator; + using size_type = size_t; + using difference_type = std::ptrdiff_t; + + private: + const char* ptr_; + size_type length_; + + static constexpr size_type kMaxSize = + (std::numeric_limits<difference_type>::max)(); + + static size_type CheckSize(size_type size) { +#if !defined(NDEBUG) || defined(_FORTIFY_SOURCE) && _FORTIFY_SOURCE > 0 + if (PROTOBUF_PREDICT_FALSE(size > kMaxSize)) { + // Some people grep for this message in logs + // so take care if you ever change it. + LogFatalSizeTooBig(size, "string length exceeds max size"); + } +#endif + return size; + } + + // Out-of-line error path. + static void LogFatalSizeTooBig(size_type size, const char* details); + + public: + // We provide non-explicit singleton constructors so users can pass + // in a "const char*" or a "string" wherever a "StringPiece" is + // expected. + // + // Style guide exception granted: + // http://goto/style-guide-exception-20978288 + StringPiece() : ptr_(nullptr), length_(0) {} + + StringPiece(const char* str) // NOLINT(runtime/explicit) + : ptr_(str), length_(0) { + if (str != nullptr) { + length_ = CheckSize(strlen(str)); + } + } + + template <class Allocator> + StringPiece( // NOLINT(runtime/explicit) + const std::basic_string<char, std::char_traits<char>, Allocator>& str) + : ptr_(str.data()), length_(0) { + length_ = CheckSize(str.size()); + } + +#if defined(__cpp_lib_string_view) + StringPiece( // NOLINT(runtime/explicit) + std::string_view str) + : ptr_(str.data()), length_(0) { + length_ = CheckSize(str.size()); + } +#endif + + StringPiece(const char* offset, size_type len) + : ptr_(offset), length_(CheckSize(len)) {} + + // data() may return a pointer to a buffer with embedded NULs, and the + // returned buffer may or may not be null terminated. Therefore it is + // typically a mistake to pass data() to a routine that expects a NUL + // terminated string. + const_pointer data() const { return ptr_; } + size_type size() const { return length_; } + size_type length() const { return length_; } + bool empty() const { return length_ == 0; } + + char operator[](size_type i) const { + assert(i < length_); + return ptr_[i]; + } + + void remove_prefix(size_type n) { + assert(length_ >= n); + ptr_ += n; + length_ -= n; + } + + void remove_suffix(size_type n) { + assert(length_ >= n); + length_ -= n; + } + + // returns {-1, 0, 1} + int compare(StringPiece x) const { + size_type min_size = length_ < x.length_ ? length_ : x.length_; + int r = memcmp(ptr_, x.ptr_, static_cast<size_t>(min_size)); + if (r < 0) return -1; + if (r > 0) return 1; + if (length_ < x.length_) return -1; + if (length_ > x.length_) return 1; + return 0; + } + + std::string as_string() const { return ToString(); } + // We also define ToString() here, since many other string-like + // interfaces name the routine that converts to a C++ string + // "ToString", and it's confusing to have the method that does that + // for a StringPiece be called "as_string()". We also leave the + // "as_string()" method defined here for existing code. + std::string ToString() const { + if (ptr_ == nullptr) return ""; + return std::string(data(), static_cast<size_type>(size())); + } + + explicit operator std::string() const { return ToString(); } + + void CopyToString(std::string* target) const; + void AppendToString(std::string* target) const; + + bool starts_with(StringPiece x) const { + return (length_ >= x.length_) && + (memcmp(ptr_, x.ptr_, static_cast<size_t>(x.length_)) == 0); + } + + bool ends_with(StringPiece x) const { + return ((length_ >= x.length_) && + (memcmp(ptr_ + (length_-x.length_), x.ptr_, + static_cast<size_t>(x.length_)) == 0)); + } + + // Checks whether StringPiece starts with x and if so advances the beginning + // of it to past the match. It's basically a shortcut for starts_with + // followed by remove_prefix. + bool Consume(StringPiece x); + // Like above but for the end of the string. + bool ConsumeFromEnd(StringPiece x); + + // standard STL container boilerplate + static const size_type npos; + const_iterator begin() const { return ptr_; } + const_iterator end() const { return ptr_ + length_; } + const_reverse_iterator rbegin() const { + return const_reverse_iterator(ptr_ + length_); + } + const_reverse_iterator rend() const { + return const_reverse_iterator(ptr_); + } + size_type max_size() const { return length_; } + size_type capacity() const { return length_; } + + // cpplint.py emits a false positive [build/include_what_you_use] + size_type copy(char* buf, size_type n, size_type pos = 0) const; // NOLINT + + bool contains(StringPiece s) const; + + size_type find(StringPiece s, size_type pos = 0) const; + size_type find(char c, size_type pos = 0) const; + size_type rfind(StringPiece s, size_type pos = npos) const; + size_type rfind(char c, size_type pos = npos) const; + + size_type find_first_of(StringPiece s, size_type pos = 0) const; + size_type find_first_of(char c, size_type pos = 0) const { + return find(c, pos); + } + size_type find_first_not_of(StringPiece s, size_type pos = 0) const; + size_type find_first_not_of(char c, size_type pos = 0) const; + size_type find_last_of(StringPiece s, size_type pos = npos) const; + size_type find_last_of(char c, size_type pos = npos) const { + return rfind(c, pos); + } + size_type find_last_not_of(StringPiece s, size_type pos = npos) const; + size_type find_last_not_of(char c, size_type pos = npos) const; + + StringPiece substr(size_type pos, size_type n = npos) const; +}; + +// This large function is defined inline so that in a fairly common case where +// one of the arguments is a literal, the compiler can elide a lot of the +// following comparisons. +inline bool operator==(StringPiece x, StringPiece y) { + StringPiece::size_type len = x.size(); + if (len != y.size()) { + return false; + } + + return x.data() == y.data() || len <= 0 || + memcmp(x.data(), y.data(), static_cast<size_t>(len)) == 0; +} + +inline bool operator!=(StringPiece x, StringPiece y) { + return !(x == y); +} + +inline bool operator<(StringPiece x, StringPiece y) { + const StringPiece::size_type min_size = + x.size() < y.size() ? x.size() : y.size(); + const int r = memcmp(x.data(), y.data(), static_cast<size_t>(min_size)); + return (r < 0) || (r == 0 && x.size() < y.size()); +} + +inline bool operator>(StringPiece x, StringPiece y) { + return y < x; +} + +inline bool operator<=(StringPiece x, StringPiece y) { + return !(x > y); +} + +inline bool operator>=(StringPiece x, StringPiece y) { + return !(x < y); +} + +// allow StringPiece to be logged +extern std::ostream& operator<<(std::ostream& o, StringPiece piece); + +} // namespace stringpiece_internal + +using ::google::protobuf::stringpiece_internal::StringPiece; + +} // namespace protobuf +} // namespace google + +GOOGLE_PROTOBUF_HASH_NAMESPACE_DECLARATION_START +template<> struct hash<StringPiece> { + size_t operator()(const StringPiece& s) const { + size_t result = 0; + for (const char *str = s.data(), *end = str + s.size(); str < end; str++) { + result = 5 * result + static_cast<size_t>(*str); + } + return result; + } +}; +GOOGLE_PROTOBUF_HASH_NAMESPACE_DECLARATION_END + +#include <google/protobuf/port_undef.inc> + +#endif // STRINGS_STRINGPIECE_H_ diff --git a/toolkit/components/protobuf/src/google/protobuf/stubs/stringprintf.cc b/toolkit/components/protobuf/src/google/protobuf/stubs/stringprintf.cc new file mode 100644 index 0000000000..a6ad4c0da4 --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/stubs/stringprintf.cc @@ -0,0 +1,175 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2012 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. + +// from google3/base/stringprintf.cc + +#include <google/protobuf/stubs/stringprintf.h> + +#include <errno.h> +#include <stdarg.h> // For va_list and related operations +#include <stdio.h> // MSVC requires this for _vsnprintf +#include <vector> + +#include <google/protobuf/stubs/common.h> +#include <google/protobuf/stubs/logging.h> + +namespace google { +namespace protobuf { + +#ifdef _MSC_VER +#ifndef va_copy +// Define va_copy for MSVC. This is a hack, assuming va_list is simply a +// pointer into the stack and is safe to copy. +#define va_copy(dest, src) ((dest) = (src)) +#endif +#endif + +void StringAppendV(std::string* dst, const char* format, va_list ap) { + // First try with a small fixed size buffer + static const int kSpaceLength = 1024; + char space[kSpaceLength]; + + // It's possible for methods that use a va_list to invalidate + // the data in it upon use. The fix is to make a copy + // of the structure before using it and use that copy instead. + va_list backup_ap; + va_copy(backup_ap, ap); + int result = vsnprintf(space, kSpaceLength, format, backup_ap); + va_end(backup_ap); + + if (result < kSpaceLength) { + if (result >= 0) { + // Normal case -- everything fit. + dst->append(space, result); + return; + } + +#ifdef _MSC_VER + { + // Error or MSVC running out of space. MSVC 8.0 and higher + // can be asked about space needed with the special idiom below: + va_copy(backup_ap, ap); + result = vsnprintf(nullptr, 0, format, backup_ap); + va_end(backup_ap); + } +#endif + + if (result < 0) { + // Just an error. + return; + } + } + + // Increase the buffer size to the size requested by vsnprintf, + // plus one for the closing \0. + int length = result+1; + char* buf = new char[length]; + + // Restore the va_list before we use it again + va_copy(backup_ap, ap); + result = vsnprintf(buf, length, format, backup_ap); + va_end(backup_ap); + + if (result >= 0 && result < length) { + // It fit + dst->append(buf, result); + } + delete[] buf; +} + +std::string StringPrintf(const char* format, ...) { + va_list ap; + va_start(ap, format); + std::string result; + StringAppendV(&result, format, ap); + va_end(ap); + return result; +} + +const std::string& SStringPrintf(std::string* dst, const char* format, ...) { + va_list ap; + va_start(ap, format); + dst->clear(); + StringAppendV(dst, format, ap); + va_end(ap); + return *dst; +} + +void StringAppendF(std::string* dst, const char* format, ...) { + va_list ap; + va_start(ap, format); + StringAppendV(dst, format, ap); + va_end(ap); +} + +// Max arguments supported by StringPrintVector +const int kStringPrintfVectorMaxArgs = 32; + +// An empty block of zero for filler arguments. This is const so that if +// printf tries to write to it (via %n) then the program gets a SIGSEGV +// and we can fix the problem or protect against an attack. +static const char string_printf_empty_block[256] = { '\0' }; + +std::string StringPrintfVector(const char* format, + const std::vector<std::string>& v) { + GOOGLE_CHECK_LE(v.size(), kStringPrintfVectorMaxArgs) + << "StringPrintfVector currently only supports up to " + << kStringPrintfVectorMaxArgs << " arguments. " + << "Feel free to add support for more if you need it."; + + // Add filler arguments so that bogus format+args have a harder time + // crashing the program, corrupting the program (%n), + // or displaying random chunks of memory to users. + + const char* cstr[kStringPrintfVectorMaxArgs]; + for (int i = 0; i < v.size(); ++i) { + cstr[i] = v[i].c_str(); + } + for (int i = v.size(); i < GOOGLE_ARRAYSIZE(cstr); ++i) { + cstr[i] = &string_printf_empty_block[0]; + } + + // I do not know any way to pass kStringPrintfVectorMaxArgs arguments, + // or any way to build a va_list by hand, or any API for printf + // that accepts an array of arguments. The best I can do is stick + // this COMPILE_ASSERT right next to the actual statement. + + static_assert(kStringPrintfVectorMaxArgs == 32, "arg_count_mismatch"); + return StringPrintf(format, + cstr[0], cstr[1], cstr[2], cstr[3], cstr[4], + cstr[5], cstr[6], cstr[7], cstr[8], cstr[9], + cstr[10], cstr[11], cstr[12], cstr[13], cstr[14], + cstr[15], cstr[16], cstr[17], cstr[18], cstr[19], + cstr[20], cstr[21], cstr[22], cstr[23], cstr[24], + cstr[25], cstr[26], cstr[27], cstr[28], cstr[29], + cstr[30], cstr[31]); +} +} // namespace protobuf +} // namespace google diff --git a/toolkit/components/protobuf/src/google/protobuf/stubs/stringprintf.h b/toolkit/components/protobuf/src/google/protobuf/stubs/stringprintf.h new file mode 100644 index 0000000000..e3858be130 --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/stubs/stringprintf.h @@ -0,0 +1,85 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2012 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. + +// from google3/base/stringprintf.h +// +// Printf variants that place their output in a C++ string. +// +// Usage: +// string result = StringPrintf("%d %s\n", 10, "hello"); +// SStringPrintf(&result, "%d %s\n", 10, "hello"); +// StringAppendF(&result, "%d %s\n", 20, "there"); + +#ifndef GOOGLE_PROTOBUF_STUBS_STRINGPRINTF_H +#define GOOGLE_PROTOBUF_STUBS_STRINGPRINTF_H + +#include <stdarg.h> +#include <string> +#include <vector> + +#include <google/protobuf/stubs/common.h> + +#include <google/protobuf/port_def.inc> + +namespace google { +namespace protobuf { + +// Return a C++ string +PROTOBUF_EXPORT extern std::string StringPrintf(const char* format, ...); + +// Store result into a supplied string and return it +PROTOBUF_EXPORT extern const std::string& SStringPrintf(std::string* dst, + const char* format, + ...); + +// Append result to a supplied string +PROTOBUF_EXPORT extern void StringAppendF(std::string* dst, const char* format, + ...); + +// Lower-level routine that takes a va_list and appends to a specified +// string. All other routines are just convenience wrappers around it. +PROTOBUF_EXPORT extern void StringAppendV(std::string* dst, const char* format, + va_list ap); + +// The max arguments supported by StringPrintfVector +PROTOBUF_EXPORT extern const int kStringPrintfVectorMaxArgs; + +// You can use this version when all your arguments are strings, but +// you don't know how many arguments you'll have at compile time. +// StringPrintfVector will LOG(FATAL) if v.size() > kStringPrintfVectorMaxArgs +PROTOBUF_EXPORT extern std::string StringPrintfVector( + const char* format, const std::vector<std::string>& v); + +} // namespace protobuf +} // namespace google + +#include <google/protobuf/port_undef.inc> + +#endif // GOOGLE_PROTOBUF_STUBS_STRINGPRINTF_H diff --git a/toolkit/components/protobuf/src/google/protobuf/stubs/structurally_valid.cc b/toolkit/components/protobuf/src/google/protobuf/stubs/structurally_valid.cc new file mode 100644 index 0000000000..a535736583 --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/stubs/structurally_valid.cc @@ -0,0 +1,617 @@ +// 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. + +// Author: jrm@google.com (Jim Meehan) + +#include <google/protobuf/stubs/common.h> + +#include <google/protobuf/stubs/stringpiece.h> + +namespace google { +namespace protobuf { +namespace internal { + +// These four-byte entries compactly encode how many bytes 0..255 to delete +// in making a string replacement, how many bytes to add 0..255, and the offset +// 0..64k-1 of the replacement string in remap_string. +struct RemapEntry { + uint8_t delete_bytes; + uint8_t add_bytes; + uint16_t bytes_offset; +}; + +// Exit type codes for state tables. All but the first get stuffed into +// signed one-byte entries. The first is only generated by executable code. +// To distinguish from next-state entries, these must be contiguous and +// all <= kExitNone +typedef enum { + kExitDstSpaceFull = 239, + kExitIllegalStructure, // 240 + kExitOK, // 241 + kExitReject, // ... + kExitReplace1, + kExitReplace2, + kExitReplace3, + kExitReplace21, + kExitReplace31, + kExitReplace32, + kExitReplaceOffset1, + kExitReplaceOffset2, + kExitReplace1S0, + kExitSpecial, + kExitDoAgain, + kExitRejectAlt, + kExitNone // 255 +} ExitReason; + + +// This struct represents one entire state table. The three initialized byte +// areas are state_table, remap_base, and remap_string. state0 and state0_size +// give the byte offset and length within state_table of the initial state -- +// table lookups are expected to start and end in this state, but for +// truncated UTF-8 strings, may end in a different state. These allow a quick +// test for that condition. entry_shift is 8 for tables subscripted by a full +// byte value and 6 for space-optimized tables subscripted by only six +// significant bits in UTF-8 continuation bytes. +typedef struct { + const uint32_t state0; + const uint32_t state0_size; + const uint32_t total_size; + const int max_expand; + const int entry_shift; + const int bytes_per_entry; + const uint32_t losub; + const uint32_t hiadd; + const uint8_t* state_table; + const RemapEntry* remap_base; + const uint8_t* remap_string; + const uint8_t* fast_state; +} UTF8StateMachineObj; + +typedef UTF8StateMachineObj UTF8ScanObj; + +#define X__ (kExitIllegalStructure) +#define RJ_ (kExitReject) +#define S1_ (kExitReplace1) +#define S2_ (kExitReplace2) +#define S3_ (kExitReplace3) +#define S21 (kExitReplace21) +#define S31 (kExitReplace31) +#define S32 (kExitReplace32) +#define T1_ (kExitReplaceOffset1) +#define T2_ (kExitReplaceOffset2) +#define S11 (kExitReplace1S0) +#define SP_ (kExitSpecial) +#define D__ (kExitDoAgain) +#define RJA (kExitRejectAlt) + +// Entire table has 9 state blocks of 256 entries each +static const unsigned int utf8acceptnonsurrogates_STATE0 = 0; // state[0] +static const unsigned int utf8acceptnonsurrogates_STATE0_SIZE = 256; // =[1] +static const unsigned int utf8acceptnonsurrogates_TOTAL_SIZE = 2304; +static const unsigned int utf8acceptnonsurrogates_MAX_EXPAND_X4 = 0; +static const unsigned int utf8acceptnonsurrogates_SHIFT = 8; +static const unsigned int utf8acceptnonsurrogates_BYTES = 1; +static const unsigned int utf8acceptnonsurrogates_LOSUB = 0x20202020; +static const unsigned int utf8acceptnonsurrogates_HIADD = 0x00000000; + +static const uint8_t utf8acceptnonsurrogates[] = { +// state[0] 0x000000 Byte 1 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, + +X__, X__, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 7, 3, 3, + 4, 5, 5, 5, 6, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, + +// state[1] 0x000080 Byte 2 of 2 +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, + +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, + + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, + +// state[2] 0x000000 Byte 2 of 3 +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, + +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, + +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, + +// state[3] 0x001000 Byte 2 of 3 +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, + +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, + + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, + +// state[4] 0x000000 Byte 2 of 4 +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, + +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, + +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, + +// state[5] 0x040000 Byte 2 of 4 +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, + +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, + + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, + +// state[6] 0x100000 Byte 2 of 4 +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, + +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, + + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, + +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, + +// state[7] 0x00d000 Byte 2 of 3 +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, + +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, + + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, + +// state[8] 0x00d800 Byte 3 of 3 +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, + +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, + +RJ_, RJ_, RJ_, RJ_, RJ_, RJ_, RJ_, RJ_, RJ_, RJ_, RJ_, RJ_, RJ_, RJ_, RJ_, RJ_, +RJ_, RJ_, RJ_, RJ_, RJ_, RJ_, RJ_, RJ_, RJ_, RJ_, RJ_, RJ_, RJ_, RJ_, RJ_, RJ_, +RJ_, RJ_, RJ_, RJ_, RJ_, RJ_, RJ_, RJ_, RJ_, RJ_, RJ_, RJ_, RJ_, RJ_, RJ_, RJ_, +RJ_, RJ_, RJ_, RJ_, RJ_, RJ_, RJ_, RJ_, RJ_, RJ_, RJ_, RJ_, RJ_, RJ_, RJ_, RJ_, + +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, +}; + +// Remap base[0] = (del, add, string_offset) +static const RemapEntry utf8acceptnonsurrogates_remap_base[] = { +{0, 0, 0} }; + +// Remap string[0] +static const unsigned char utf8acceptnonsurrogates_remap_string[] = { +0 }; + +static const unsigned char utf8acceptnonsurrogates_fast[256] = { +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + +1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, +1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, +1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, +1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + +1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, +1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, +1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, +1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, +}; + +static const UTF8ScanObj utf8acceptnonsurrogates_obj = { + utf8acceptnonsurrogates_STATE0, + utf8acceptnonsurrogates_STATE0_SIZE, + utf8acceptnonsurrogates_TOTAL_SIZE, + utf8acceptnonsurrogates_MAX_EXPAND_X4, + utf8acceptnonsurrogates_SHIFT, + utf8acceptnonsurrogates_BYTES, + utf8acceptnonsurrogates_LOSUB, + utf8acceptnonsurrogates_HIADD, + utf8acceptnonsurrogates, + utf8acceptnonsurrogates_remap_base, + utf8acceptnonsurrogates_remap_string, + utf8acceptnonsurrogates_fast +}; + + +#undef X__ +#undef RJ_ +#undef S1_ +#undef S2_ +#undef S3_ +#undef S21 +#undef S31 +#undef S32 +#undef T1_ +#undef T2_ +#undef S11 +#undef SP_ +#undef D__ +#undef RJA + +// Return true if current Tbl pointer is within state0 range +// Note that unsigned compare checks both ends of range simultaneously +static inline bool InStateZero(const UTF8ScanObj* st, const uint8_t* Tbl) { + const uint8_t* Tbl0 = &st->state_table[st->state0]; + return (static_cast<uint32_t>(Tbl - Tbl0) < st->state0_size); +} + +namespace { + +// Scan a UTF-8 string based on state table. +// Always scan complete UTF-8 characters +// Set number of bytes scanned. Return reason for exiting +int UTF8GenericScan(const UTF8ScanObj* st, + const char * str, + int str_length, + int* bytes_consumed) { + *bytes_consumed = 0; + if (str_length == 0) return kExitOK; + + int eshift = st->entry_shift; + const uint8_t* isrc = reinterpret_cast<const uint8_t*>(str); + const uint8_t* src = isrc; + const uint8_t* srclimit = isrc + str_length; + const uint8_t* srclimit8 = str_length < 7 ? isrc : srclimit - 7; + const uint8_t* Tbl_0 = &st->state_table[st->state0]; + + DoAgain: + // Do state-table scan + int e = 0; + uint8_t c; + const uint8_t* Tbl2 = &st->fast_state[0]; + const uint32_t losub = st->losub; + const uint32_t hiadd = st->hiadd; + // Check initial few bytes one at a time until 8-byte aligned + //---------------------------- + while ((((uintptr_t)src & 0x07) != 0) && + (src < srclimit) && + Tbl2[src[0]] == 0) { + src++; + } + if (((uintptr_t)src & 0x07) == 0) { + // Do fast for groups of 8 identity bytes. + // This covers a lot of 7-bit ASCII ~8x faster then the 1-byte loop, + // including slowing slightly on cr/lf/ht + //---------------------------- + while (src < srclimit8) { + uint32_t s0123 = (reinterpret_cast<const uint32_t *>(src))[0]; + uint32_t s4567 = (reinterpret_cast<const uint32_t *>(src))[1]; + src += 8; + // This is a fast range check for all bytes in [lowsub..0x80-hiadd) + uint32_t temp = (s0123 - losub) | (s0123 + hiadd) | + (s4567 - losub) | (s4567 + hiadd); + if ((temp & 0x80808080) != 0) { + // We typically end up here on cr/lf/ht; src was incremented + int e0123 = (Tbl2[src[-8]] | Tbl2[src[-7]]) | + (Tbl2[src[-6]] | Tbl2[src[-5]]); + if (e0123 != 0) { + src -= 8; + break; + } // Exit on Non-interchange + e0123 = (Tbl2[src[-4]] | Tbl2[src[-3]]) | + (Tbl2[src[-2]] | Tbl2[src[-1]]); + if (e0123 != 0) { + src -= 4; + break; + } // Exit on Non-interchange + // Else OK, go around again + } + } + } + //---------------------------- + + // Byte-at-a-time scan + //---------------------------- + const uint8_t* Tbl = Tbl_0; + while (src < srclimit) { + c = *src; + e = Tbl[c]; + src++; + if (e >= kExitIllegalStructure) {break;} + Tbl = &Tbl_0[e << eshift]; + } + //---------------------------- + + // Exit possibilities: + // Some exit code, !state0, back up over last char + // Some exit code, state0, back up one byte exactly + // source consumed, !state0, back up over partial char + // source consumed, state0, exit OK + // For illegal byte in state0, avoid backup up over PREVIOUS char + // For truncated last char, back up to beginning of it + + if (e >= kExitIllegalStructure) { + // Back up over exactly one byte of rejected/illegal UTF-8 character + src--; + // Back up more if needed + if (!InStateZero(st, Tbl)) { + do { + src--; + } while ((src > isrc) && ((src[0] & 0xc0) == 0x80)); + } + } else if (!InStateZero(st, Tbl)) { + // Back up over truncated UTF-8 character + e = kExitIllegalStructure; + do { + src--; + } while ((src > isrc) && ((src[0] & 0xc0) == 0x80)); + } else { + // Normal termination, source fully consumed + e = kExitOK; + } + + if (e == kExitDoAgain) { + // Loop back up to the fast scan + goto DoAgain; + } + + *bytes_consumed = src - isrc; + return e; +} + +int UTF8GenericScanFastAscii(const UTF8ScanObj* st, + const char * str, + int str_length, + int* bytes_consumed) { + *bytes_consumed = 0; + if (str_length == 0) return kExitOK; + + const uint8_t* isrc = reinterpret_cast<const uint8_t*>(str); + const uint8_t* src = isrc; + const uint8_t* srclimit = isrc + str_length; + const uint8_t* srclimit8 = str_length < 7 ? isrc : srclimit - 7; + int n; + int rest_consumed; + int exit_reason; + do { + // Check initial few bytes one at a time until 8-byte aligned + while ((((uintptr_t)src & 0x07) != 0) && + (src < srclimit) && (src[0] < 0x80)) { + src++; + } + if (((uintptr_t)src & 0x07) == 0) { + while ((src < srclimit8) && + (((reinterpret_cast<const uint32_t*>(src)[0] | + reinterpret_cast<const uint32_t*>(src)[1]) & + 0x80808080) == 0)) { + src += 8; + } + } + while ((src < srclimit) && (src[0] < 0x80)) { + src++; + } + // Run state table on the rest + n = src - isrc; + exit_reason = UTF8GenericScan(st, str + n, str_length - n, &rest_consumed); + src += rest_consumed; + } while ( exit_reason == kExitDoAgain ); + + *bytes_consumed = src - isrc; + return exit_reason; +} + +// Hack: On some compilers the static tables are initialized at startup. +// We can't use them until they are initialized. However, some Protocol +// Buffer parsing happens at static init time and may try to validate +// UTF-8 strings. Since UTF-8 validation is only used for debugging +// anyway, we simply always return success if initialization hasn't +// occurred yet. + +bool module_initialized_ = false; + +struct InitDetector { + InitDetector() { + module_initialized_ = true; + } +}; +InitDetector init_detector; + +} // namespace + +bool IsStructurallyValidUTF8(const char* buf, int len) { + if (!module_initialized_) return true; + + int bytes_consumed = 0; + UTF8GenericScanFastAscii(&utf8acceptnonsurrogates_obj, + buf, len, &bytes_consumed); + return (bytes_consumed == len); +} + +int UTF8SpnStructurallyValid(StringPiece str) { + if (!module_initialized_) return str.size(); + + int bytes_consumed = 0; + UTF8GenericScanFastAscii(&utf8acceptnonsurrogates_obj, + str.data(), str.size(), &bytes_consumed); + return bytes_consumed; +} + +// Coerce UTF-8 byte string in src_str to be +// a structurally-valid equal-length string by selectively +// overwriting illegal bytes with replace_char (typically blank). +// replace_char must be legal printable 7-bit Ascii 0x20..0x7e. +// src_str is read-only. If any overwriting is needed, a modified byte string +// is created in idst, length isrclen. +// +// Returns pointer to output buffer, isrc if no changes were made, +// or idst if some bytes were changed. +// +// Fast case: all is structurally valid and no byte copying is done. +// +char* UTF8CoerceToStructurallyValid(StringPiece src_str, char* idst, + const char replace_char) { + const char* isrc = src_str.data(); + const int len = src_str.length(); + int n = UTF8SpnStructurallyValid(src_str); + if (n == len) { // Normal case -- all is cool, return + return const_cast<char*>(isrc); + } else { // Unusual case -- copy w/o bad bytes + const char* src = isrc; + const char* srclimit = isrc + len; + char* dst = idst; + memmove(dst, src, n); // Copy initial good chunk + src += n; + dst += n; + while (src < srclimit) { // src points to bogus byte or is off the end + dst[0] = replace_char; // replace one bad byte + src++; + dst++; + StringPiece str2(src, srclimit - src); + n = UTF8SpnStructurallyValid(str2); // scan the remainder + memmove(dst, src, n); // copy next good chunk + src += n; + dst += n; + } + } + return idst; +} + +} // namespace internal +} // namespace protobuf +} // namespace google diff --git a/toolkit/components/protobuf/src/google/protobuf/stubs/strutil.cc b/toolkit/components/protobuf/src/google/protobuf/stubs/strutil.cc new file mode 100644 index 0000000000..594c8eac6a --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/stubs/strutil.cc @@ -0,0 +1,2479 @@ +// 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. + +// from google3/strings/strutil.cc + +#include <google/protobuf/stubs/strutil.h> + +#include <errno.h> +#include <float.h> // FLT_DIG and DBL_DIG +#include <limits.h> +#include <stdio.h> +#include <cmath> +#include <iterator> +#include <limits> + +#include <google/protobuf/stubs/logging.h> +#include <google/protobuf/stubs/stl_util.h> + +#ifdef _WIN32 +// MSVC has only _snprintf, not snprintf. +// +// MinGW has both snprintf and _snprintf, but they appear to be different +// functions. The former is buggy. When invoked like so: +// char buffer[32]; +// snprintf(buffer, 32, "%.*g\n", FLT_DIG, 1.23e10f); +// it prints "1.23000e+10". This is plainly wrong: %g should never print +// trailing zeros after the decimal point. For some reason this bug only +// occurs with some input values, not all. In any case, _snprintf does the +// right thing, so we use it. +#define snprintf _snprintf +#endif + +namespace google { +namespace protobuf { + +// These are defined as macros on some platforms. #undef them so that we can +// redefine them. +#undef isxdigit +#undef isprint + +// The definitions of these in ctype.h change based on locale. Since our +// string manipulation is all in relation to the protocol buffer and C++ +// languages, we always want to use the C locale. So, we re-define these +// exactly as we want them. +inline bool isxdigit(char c) { + return ('0' <= c && c <= '9') || + ('a' <= c && c <= 'f') || + ('A' <= c && c <= 'F'); +} + +inline bool isprint(char c) { + return c >= 0x20 && c <= 0x7E; +} + +// ---------------------------------------------------------------------- +// ReplaceCharacters +// Replaces any occurrence of the character 'remove' (or the characters +// in 'remove') with the character 'replacewith'. +// ---------------------------------------------------------------------- +void ReplaceCharacters(std::string *s, const char *remove, char replacewith) { + const char *str_start = s->c_str(); + const char *str = str_start; + for (str = strpbrk(str, remove); + str != nullptr; + str = strpbrk(str + 1, remove)) { + (*s)[str - str_start] = replacewith; + } +} + +void StripWhitespace(std::string *str) { + int str_length = str->length(); + + // Strip off leading whitespace. + int first = 0; + while (first < str_length && ascii_isspace(str->at(first))) { + ++first; + } + // If entire string is white space. + if (first == str_length) { + str->clear(); + return; + } + if (first > 0) { + str->erase(0, first); + str_length -= first; + } + + // Strip off trailing whitespace. + int last = str_length - 1; + while (last >= 0 && ascii_isspace(str->at(last))) { + --last; + } + if (last != (str_length - 1) && last >= 0) { + str->erase(last + 1, std::string::npos); + } +} + +// ---------------------------------------------------------------------- +// StringReplace() +// Replace the "old" pattern with the "new" pattern in a string, +// and append the result to "res". If replace_all is false, +// it only replaces the first instance of "old." +// ---------------------------------------------------------------------- + +void StringReplace(const std::string &s, const std::string &oldsub, + const std::string &newsub, bool replace_all, + std::string *res) { + if (oldsub.empty()) { + res->append(s); // if empty, append the given string. + return; + } + + std::string::size_type start_pos = 0; + std::string::size_type pos; + do { + pos = s.find(oldsub, start_pos); + if (pos == std::string::npos) { + break; + } + res->append(s, start_pos, pos - start_pos); + res->append(newsub); + start_pos = pos + oldsub.size(); // start searching again after the "old" + } while (replace_all); + res->append(s, start_pos, s.length() - start_pos); +} + +// ---------------------------------------------------------------------- +// StringReplace() +// Give me a string and two patterns "old" and "new", and I replace +// the first instance of "old" in the string with "new", if it +// exists. If "global" is true; call this repeatedly until it +// fails. RETURN a new string, regardless of whether the replacement +// happened or not. +// ---------------------------------------------------------------------- + +std::string StringReplace(const std::string &s, const std::string &oldsub, + const std::string &newsub, bool replace_all) { + std::string ret; + StringReplace(s, oldsub, newsub, replace_all, &ret); + return ret; +} + +// ---------------------------------------------------------------------- +// SplitStringUsing() +// Split a string using a character delimiter. Append the components +// to 'result'. +// +// Note: For multi-character delimiters, this routine will split on *ANY* of +// the characters in the string, not the entire string as a single delimiter. +// ---------------------------------------------------------------------- +template <typename ITR> +static inline void SplitStringToIteratorUsing(StringPiece full, + const char *delim, ITR &result) { + // Optimize the common case where delim is a single character. + if (delim[0] != '\0' && delim[1] == '\0') { + char c = delim[0]; + const char* p = full.data(); + const char* end = p + full.size(); + while (p != end) { + if (*p == c) { + ++p; + } else { + const char* start = p; + while (++p != end && *p != c); + *result++ = std::string(start, p - start); + } + } + return; + } + + std::string::size_type begin_index, end_index; + begin_index = full.find_first_not_of(delim); + while (begin_index != std::string::npos) { + end_index = full.find_first_of(delim, begin_index); + if (end_index == std::string::npos) { + *result++ = std::string(full.substr(begin_index)); + return; + } + *result++ = + std::string(full.substr(begin_index, (end_index - begin_index))); + begin_index = full.find_first_not_of(delim, end_index); + } +} + +void SplitStringUsing(StringPiece full, const char *delim, + std::vector<std::string> *result) { + std::back_insert_iterator<std::vector<std::string> > it(*result); + SplitStringToIteratorUsing(full, delim, it); +} + +// Split a string using a character delimiter. Append the components +// to 'result'. If there are consecutive delimiters, this function +// will return corresponding empty strings. The string is split into +// at most the specified number of pieces greedily. This means that the +// last piece may possibly be split further. To split into as many pieces +// as possible, specify 0 as the number of pieces. +// +// If "full" is the empty string, yields an empty string as the only value. +// +// If "pieces" is negative for some reason, it returns the whole string +// ---------------------------------------------------------------------- +template <typename ITR> +static inline void SplitStringToIteratorAllowEmpty(StringPiece full, + const char *delim, + int pieces, ITR &result) { + std::string::size_type begin_index, end_index; + begin_index = 0; + + for (int i = 0; (i < pieces-1) || (pieces == 0); i++) { + end_index = full.find_first_of(delim, begin_index); + if (end_index == std::string::npos) { + *result++ = std::string(full.substr(begin_index)); + return; + } + *result++ = + std::string(full.substr(begin_index, (end_index - begin_index))); + begin_index = end_index + 1; + } + *result++ = std::string(full.substr(begin_index)); +} + +void SplitStringAllowEmpty(StringPiece full, const char *delim, + std::vector<std::string> *result) { + std::back_insert_iterator<std::vector<std::string> > it(*result); + SplitStringToIteratorAllowEmpty(full, delim, 0, it); +} + +// ---------------------------------------------------------------------- +// JoinStrings() +// This merges a vector of string components with delim inserted +// as separaters between components. +// +// ---------------------------------------------------------------------- +template <class ITERATOR> +static void JoinStringsIterator(const ITERATOR &start, const ITERATOR &end, + const char *delim, std::string *result) { + GOOGLE_CHECK(result != nullptr); + result->clear(); + int delim_length = strlen(delim); + + // Precompute resulting length so we can reserve() memory in one shot. + int length = 0; + for (ITERATOR iter = start; iter != end; ++iter) { + if (iter != start) { + length += delim_length; + } + length += iter->size(); + } + result->reserve(length); + + // Now combine everything. + for (ITERATOR iter = start; iter != end; ++iter) { + if (iter != start) { + result->append(delim, delim_length); + } + result->append(iter->data(), iter->size()); + } +} + +void JoinStrings(const std::vector<std::string> &components, const char *delim, + std::string *result) { + JoinStringsIterator(components.begin(), components.end(), delim, result); +} + +// ---------------------------------------------------------------------- +// UnescapeCEscapeSequences() +// This does all the unescaping that C does: \ooo, \r, \n, etc +// Returns length of resulting string. +// The implementation of \x parses any positive number of hex digits, +// but it is an error if the value requires more than 8 bits, and the +// result is truncated to 8 bits. +// +// The second call stores its errors in a supplied string vector. +// If the string vector pointer is nullptr, it reports the errors with LOG(). +// ---------------------------------------------------------------------- + +#define IS_OCTAL_DIGIT(c) (((c) >= '0') && ((c) <= '7')) + +// Protocol buffers doesn't ever care about errors, but I don't want to remove +// the code. +#define LOG_STRING(LEVEL, VECTOR) GOOGLE_LOG_IF(LEVEL, false) + +int UnescapeCEscapeSequences(const char* source, char* dest) { + return UnescapeCEscapeSequences(source, dest, nullptr); +} + +int UnescapeCEscapeSequences(const char *source, char *dest, + std::vector<std::string> *errors) { + GOOGLE_DCHECK(errors == nullptr) << "Error reporting not implemented."; + + char* d = dest; + const char* p = source; + + // Small optimization for case where source = dest and there's no escaping + while ( p == d && *p != '\0' && *p != '\\' ) + p++, d++; + + while (*p != '\0') { + if (*p != '\\') { + *d++ = *p++; + } else { + switch ( *++p ) { // skip past the '\\' + case '\0': + LOG_STRING(ERROR, errors) << "String cannot end with \\"; + *d = '\0'; + return d - dest; // we're done with p + case 'a': *d++ = '\a'; break; + case 'b': *d++ = '\b'; break; + case 'f': *d++ = '\f'; break; + case 'n': *d++ = '\n'; break; + case 'r': *d++ = '\r'; break; + case 't': *d++ = '\t'; break; + case 'v': *d++ = '\v'; break; + case '\\': *d++ = '\\'; break; + case '?': *d++ = '\?'; break; // \? Who knew? + case '\'': *d++ = '\''; break; + case '"': *d++ = '\"'; break; + case '0': case '1': case '2': case '3': // octal digit: 1 to 3 digits + case '4': case '5': case '6': case '7': { + char ch = *p - '0'; + if ( IS_OCTAL_DIGIT(p[1]) ) + ch = ch * 8 + *++p - '0'; + if ( IS_OCTAL_DIGIT(p[1]) ) // safe (and easy) to do this twice + ch = ch * 8 + *++p - '0'; // now points at last digit + *d++ = ch; + break; + } + case 'x': case 'X': { + if (!isxdigit(p[1])) { + if (p[1] == '\0') { + LOG_STRING(ERROR, errors) << "String cannot end with \\x"; + } else { + LOG_STRING(ERROR, errors) << + "\\x cannot be followed by non-hex digit: \\" << *p << p[1]; + } + break; + } + unsigned int ch = 0; + const char *hex_start = p; + while (isxdigit(p[1])) // arbitrarily many hex digits + ch = (ch << 4) + hex_digit_to_int(*++p); + if (ch > 0xFF) + LOG_STRING(ERROR, errors) + << "Value of " + << "\\" << std::string(hex_start, p + 1 - hex_start) + << " exceeds 8 bits"; + *d++ = ch; + break; + } +#if 0 // TODO(kenton): Support \u and \U? Requires runetochar(). + case 'u': { + // \uhhhh => convert 4 hex digits to UTF-8 + char32 rune = 0; + const char *hex_start = p; + for (int i = 0; i < 4; ++i) { + if (isxdigit(p[1])) { // Look one char ahead. + rune = (rune << 4) + hex_digit_to_int(*++p); // Advance p. + } else { + LOG_STRING(ERROR, errors) + << "\\u must be followed by 4 hex digits: \\" + << std::string(hex_start, p+1-hex_start); + break; + } + } + d += runetochar(d, &rune); + break; + } + case 'U': { + // \Uhhhhhhhh => convert 8 hex digits to UTF-8 + char32 rune = 0; + const char *hex_start = p; + for (int i = 0; i < 8; ++i) { + if (isxdigit(p[1])) { // Look one char ahead. + // Don't change rune until we're sure this + // is within the Unicode limit, but do advance p. + char32 newrune = (rune << 4) + hex_digit_to_int(*++p); + if (newrune > 0x10FFFF) { + LOG_STRING(ERROR, errors) + << "Value of \\" + << std::string(hex_start, p + 1 - hex_start) + << " exceeds Unicode limit (0x10FFFF)"; + break; + } else { + rune = newrune; + } + } else { + LOG_STRING(ERROR, errors) + << "\\U must be followed by 8 hex digits: \\" + << std::string(hex_start, p+1-hex_start); + break; + } + } + d += runetochar(d, &rune); + break; + } +#endif + default: + LOG_STRING(ERROR, errors) << "Unknown escape sequence: \\" << *p; + } + p++; // read past letter we escaped + } + } + *d = '\0'; + return d - dest; +} + +// ---------------------------------------------------------------------- +// UnescapeCEscapeString() +// This does the same thing as UnescapeCEscapeSequences, but creates +// a new string. The caller does not need to worry about allocating +// a dest buffer. This should be used for non performance critical +// tasks such as printing debug messages. It is safe for src and dest +// to be the same. +// +// The second call stores its errors in a supplied string vector. +// If the string vector pointer is nullptr, it reports the errors with LOG(). +// +// In the first and second calls, the length of dest is returned. In the +// the third call, the new string is returned. +// ---------------------------------------------------------------------- +int UnescapeCEscapeString(const std::string &src, std::string *dest) { + return UnescapeCEscapeString(src, dest, nullptr); +} + +int UnescapeCEscapeString(const std::string &src, std::string *dest, + std::vector<std::string> *errors) { + std::unique_ptr<char[]> unescaped(new char[src.size() + 1]); + int len = UnescapeCEscapeSequences(src.c_str(), unescaped.get(), errors); + GOOGLE_CHECK(dest); + dest->assign(unescaped.get(), len); + return len; +} + +std::string UnescapeCEscapeString(const std::string &src) { + std::unique_ptr<char[]> unescaped(new char[src.size() + 1]); + int len = UnescapeCEscapeSequences(src.c_str(), unescaped.get(), nullptr); + return std::string(unescaped.get(), len); +} + +// ---------------------------------------------------------------------- +// CEscapeString() +// CHexEscapeString() +// Copies 'src' to 'dest', escaping dangerous characters using +// C-style escape sequences. This is very useful for preparing query +// flags. 'src' and 'dest' should not overlap. The 'Hex' version uses +// hexadecimal rather than octal sequences. +// Returns the number of bytes written to 'dest' (not including the \0) +// or -1 if there was insufficient space. +// +// Currently only \n, \r, \t, ", ', \ and !isprint() chars are escaped. +// ---------------------------------------------------------------------- +int CEscapeInternal(const char* src, int src_len, char* dest, + int dest_len, bool use_hex, bool utf8_safe) { + const char* src_end = src + src_len; + int used = 0; + bool last_hex_escape = false; // true if last output char was \xNN + + for (; src < src_end; src++) { + if (dest_len - used < 2) // Need space for two letter escape + return -1; + + bool is_hex_escape = false; + switch (*src) { + case '\n': dest[used++] = '\\'; dest[used++] = 'n'; break; + case '\r': dest[used++] = '\\'; dest[used++] = 'r'; break; + case '\t': dest[used++] = '\\'; dest[used++] = 't'; break; + case '\"': dest[used++] = '\\'; dest[used++] = '\"'; break; + case '\'': dest[used++] = '\\'; dest[used++] = '\''; break; + case '\\': dest[used++] = '\\'; dest[used++] = '\\'; break; + default: + // Note that if we emit \xNN and the src character after that is a hex + // digit then that digit must be escaped too to prevent it being + // interpreted as part of the character code by C. + if ((!utf8_safe || static_cast<uint8_t>(*src) < 0x80) && + (!isprint(*src) || + (last_hex_escape && isxdigit(*src)))) { + if (dest_len - used < 4) // need space for 4 letter escape + return -1; + sprintf(dest + used, (use_hex ? "\\x%02x" : "\\%03o"), + static_cast<uint8_t>(*src)); + is_hex_escape = use_hex; + used += 4; + } else { + dest[used++] = *src; break; + } + } + last_hex_escape = is_hex_escape; + } + + if (dest_len - used < 1) // make sure that there is room for \0 + return -1; + + dest[used] = '\0'; // doesn't count towards return value though + return used; +} + +// Calculates the length of the C-style escaped version of 'src'. +// Assumes that non-printable characters are escaped using octal sequences, and +// that UTF-8 bytes are not handled specially. +static inline size_t CEscapedLength(StringPiece src) { + static char c_escaped_len[256] = { + 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 4, 4, 2, 4, 4, // \t, \n, \r + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 1, 1, 2, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, // ", ' + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // '0'..'9' + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 'A'..'O' + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, // 'P'..'Z', '\' + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 'a'..'o' + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 4, // 'p'..'z', DEL + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + }; + + size_t escaped_len = 0; + for (StringPiece::size_type i = 0; i < src.size(); ++i) { + unsigned char c = static_cast<unsigned char>(src[i]); + escaped_len += c_escaped_len[c]; + } + return escaped_len; +} + +// ---------------------------------------------------------------------- +// Escapes 'src' using C-style escape sequences, and appends the escaped string +// to 'dest'. This version is faster than calling CEscapeInternal as it computes +// the required space using a lookup table, and also does not do any special +// handling for Hex or UTF-8 characters. +// ---------------------------------------------------------------------- +void CEscapeAndAppend(StringPiece src, std::string *dest) { + size_t escaped_len = CEscapedLength(src); + if (escaped_len == src.size()) { + dest->append(src.data(), src.size()); + return; + } + + size_t cur_dest_len = dest->size(); + dest->resize(cur_dest_len + escaped_len); + char* append_ptr = &(*dest)[cur_dest_len]; + + for (StringPiece::size_type i = 0; i < src.size(); ++i) { + unsigned char c = static_cast<unsigned char>(src[i]); + switch (c) { + case '\n': *append_ptr++ = '\\'; *append_ptr++ = 'n'; break; + case '\r': *append_ptr++ = '\\'; *append_ptr++ = 'r'; break; + case '\t': *append_ptr++ = '\\'; *append_ptr++ = 't'; break; + case '\"': *append_ptr++ = '\\'; *append_ptr++ = '\"'; break; + case '\'': *append_ptr++ = '\\'; *append_ptr++ = '\''; break; + case '\\': *append_ptr++ = '\\'; *append_ptr++ = '\\'; break; + default: + if (!isprint(c)) { + *append_ptr++ = '\\'; + *append_ptr++ = '0' + c / 64; + *append_ptr++ = '0' + (c % 64) / 8; + *append_ptr++ = '0' + c % 8; + } else { + *append_ptr++ = c; + } + break; + } + } +} + +std::string CEscape(const std::string &src) { + std::string dest; + CEscapeAndAppend(src, &dest); + return dest; +} + +namespace strings { + +std::string Utf8SafeCEscape(const std::string &src) { + const int dest_length = src.size() * 4 + 1; // Maximum possible expansion + std::unique_ptr<char[]> dest(new char[dest_length]); + const int len = CEscapeInternal(src.data(), src.size(), + dest.get(), dest_length, false, true); + GOOGLE_DCHECK_GE(len, 0); + return std::string(dest.get(), len); +} + +std::string CHexEscape(const std::string &src) { + const int dest_length = src.size() * 4 + 1; // Maximum possible expansion + std::unique_ptr<char[]> dest(new char[dest_length]); + const int len = CEscapeInternal(src.data(), src.size(), + dest.get(), dest_length, true, false); + GOOGLE_DCHECK_GE(len, 0); + return std::string(dest.get(), len); +} + +} // namespace strings + +// ---------------------------------------------------------------------- +// strto32_adaptor() +// strtou32_adaptor() +// Implementation of strto[u]l replacements that have identical +// overflow and underflow characteristics for both ILP-32 and LP-64 +// platforms, including errno preservation in error-free calls. +// ---------------------------------------------------------------------- + +int32_t strto32_adaptor(const char *nptr, char **endptr, int base) { + const int saved_errno = errno; + errno = 0; + const long result = strtol(nptr, endptr, base); + if (errno == ERANGE && result == LONG_MIN) { + return std::numeric_limits<int32_t>::min(); + } else if (errno == ERANGE && result == LONG_MAX) { + return std::numeric_limits<int32_t>::max(); + } else if (errno == 0 && result < std::numeric_limits<int32_t>::min()) { + errno = ERANGE; + return std::numeric_limits<int32_t>::min(); + } else if (errno == 0 && result > std::numeric_limits<int32_t>::max()) { + errno = ERANGE; + return std::numeric_limits<int32_t>::max(); + } + if (errno == 0) + errno = saved_errno; + return static_cast<int32_t>(result); +} + +uint32_t strtou32_adaptor(const char *nptr, char **endptr, int base) { + const int saved_errno = errno; + errno = 0; + const unsigned long result = strtoul(nptr, endptr, base); + if (errno == ERANGE && result == ULONG_MAX) { + return std::numeric_limits<uint32_t>::max(); + } else if (errno == 0 && result > std::numeric_limits<uint32_t>::max()) { + errno = ERANGE; + return std::numeric_limits<uint32_t>::max(); + } + if (errno == 0) + errno = saved_errno; + return static_cast<uint32_t>(result); +} + +inline bool safe_parse_sign(std::string *text /*inout*/, + bool *negative_ptr /*output*/) { + const char* start = text->data(); + const char* end = start + text->size(); + + // Consume whitespace. + while (start < end && (start[0] == ' ')) { + ++start; + } + while (start < end && (end[-1] == ' ')) { + --end; + } + if (start >= end) { + return false; + } + + // Consume sign. + *negative_ptr = (start[0] == '-'); + if (*negative_ptr || start[0] == '+') { + ++start; + if (start >= end) { + return false; + } + } + *text = text->substr(start - text->data(), end - start); + return true; +} + +template <typename IntType> +bool safe_parse_positive_int(std::string text, IntType *value_p) { + int base = 10; + IntType value = 0; + const IntType vmax = std::numeric_limits<IntType>::max(); + assert(vmax > 0); + assert(vmax >= base); + const IntType vmax_over_base = vmax / base; + const char* start = text.data(); + const char* end = start + text.size(); + // loop over digits + for (; start < end; ++start) { + unsigned char c = static_cast<unsigned char>(start[0]); + int digit = c - '0'; + if (digit >= base || digit < 0) { + *value_p = value; + return false; + } + if (value > vmax_over_base) { + *value_p = vmax; + return false; + } + value *= base; + if (value > vmax - digit) { + *value_p = vmax; + return false; + } + value += digit; + } + *value_p = value; + return true; +} + +template <typename IntType> +bool safe_parse_negative_int(const std::string &text, IntType *value_p) { + int base = 10; + IntType value = 0; + const IntType vmin = std::numeric_limits<IntType>::min(); + assert(vmin < 0); + assert(vmin <= 0 - base); + IntType vmin_over_base = vmin / base; + // 2003 c++ standard [expr.mul] + // "... the sign of the remainder is implementation-defined." + // Although (vmin/base)*base + vmin%base is always vmin. + // 2011 c++ standard tightens the spec but we cannot rely on it. + if (vmin % base > 0) { + vmin_over_base += 1; + } + const char* start = text.data(); + const char* end = start + text.size(); + // loop over digits + for (; start < end; ++start) { + unsigned char c = static_cast<unsigned char>(start[0]); + int digit = c - '0'; + if (digit >= base || digit < 0) { + *value_p = value; + return false; + } + if (value < vmin_over_base) { + *value_p = vmin; + return false; + } + value *= base; + if (value < vmin + digit) { + *value_p = vmin; + return false; + } + value -= digit; + } + *value_p = value; + return true; +} + +template <typename IntType> +bool safe_int_internal(std::string text, IntType *value_p) { + *value_p = 0; + bool negative; + if (!safe_parse_sign(&text, &negative)) { + return false; + } + if (!negative) { + return safe_parse_positive_int(text, value_p); + } else { + return safe_parse_negative_int(text, value_p); + } +} + +template <typename IntType> +bool safe_uint_internal(std::string text, IntType *value_p) { + *value_p = 0; + bool negative; + if (!safe_parse_sign(&text, &negative) || negative) { + return false; + } + return safe_parse_positive_int(text, value_p); +} + +// ---------------------------------------------------------------------- +// FastIntToBuffer() +// FastInt64ToBuffer() +// FastHexToBuffer() +// FastHex64ToBuffer() +// FastHex32ToBuffer() +// ---------------------------------------------------------------------- + +// Offset into buffer where FastInt64ToBuffer places the end of string +// null character. Also used by FastInt64ToBufferLeft. +static const int kFastInt64ToBufferOffset = 21; + +char *FastInt64ToBuffer(int64_t i, char* buffer) { + // We could collapse the positive and negative sections, but that + // would be slightly slower for positive numbers... + // 22 bytes is enough to store -2**64, -18446744073709551616. + char* p = buffer + kFastInt64ToBufferOffset; + *p-- = '\0'; + if (i >= 0) { + do { + *p-- = '0' + i % 10; + i /= 10; + } while (i > 0); + return p + 1; + } else { + // On different platforms, % and / have different behaviors for + // negative numbers, so we need to jump through hoops to make sure + // we don't divide negative numbers. + if (i > -10) { + i = -i; + *p-- = '0' + i; + *p = '-'; + return p; + } else { + // Make sure we aren't at MIN_INT, in which case we can't say i = -i + i = i + 10; + i = -i; + *p-- = '0' + i % 10; + // Undo what we did a moment ago + i = i / 10 + 1; + do { + *p-- = '0' + i % 10; + i /= 10; + } while (i > 0); + *p = '-'; + return p; + } + } +} + +// Offset into buffer where FastInt32ToBuffer places the end of string +// null character. Also used by FastInt32ToBufferLeft +static const int kFastInt32ToBufferOffset = 11; + +// Yes, this is a duplicate of FastInt64ToBuffer. But, we need this for the +// compiler to generate 32 bit arithmetic instructions. It's much faster, at +// least with 32 bit binaries. +char *FastInt32ToBuffer(int32_t i, char* buffer) { + // We could collapse the positive and negative sections, but that + // would be slightly slower for positive numbers... + // 12 bytes is enough to store -2**32, -4294967296. + char* p = buffer + kFastInt32ToBufferOffset; + *p-- = '\0'; + if (i >= 0) { + do { + *p-- = '0' + i % 10; + i /= 10; + } while (i > 0); + return p + 1; + } else { + // On different platforms, % and / have different behaviors for + // negative numbers, so we need to jump through hoops to make sure + // we don't divide negative numbers. + if (i > -10) { + i = -i; + *p-- = '0' + i; + *p = '-'; + return p; + } else { + // Make sure we aren't at MIN_INT, in which case we can't say i = -i + i = i + 10; + i = -i; + *p-- = '0' + i % 10; + // Undo what we did a moment ago + i = i / 10 + 1; + do { + *p-- = '0' + i % 10; + i /= 10; + } while (i > 0); + *p = '-'; + return p; + } + } +} + +char *FastHexToBuffer(int i, char* buffer) { + GOOGLE_CHECK(i >= 0) << "FastHexToBuffer() wants non-negative integers, not " << i; + + static const char *hexdigits = "0123456789abcdef"; + char *p = buffer + 21; + *p-- = '\0'; + do { + *p-- = hexdigits[i & 15]; // mod by 16 + i >>= 4; // divide by 16 + } while (i > 0); + return p + 1; +} + +char *InternalFastHexToBuffer(uint64_t value, char* buffer, int num_byte) { + static const char *hexdigits = "0123456789abcdef"; + buffer[num_byte] = '\0'; + for (int i = num_byte - 1; i >= 0; i--) { +#ifdef _M_X64 + // MSVC x64 platform has a bug optimizing the uint32(value) in the #else + // block. Given that the uint32 cast was to improve performance on 32-bit + // platforms, we use 64-bit '&' directly. + buffer[i] = hexdigits[value & 0xf]; +#else + buffer[i] = hexdigits[uint32_t(value) & 0xf]; +#endif + value >>= 4; + } + return buffer; +} + +char *FastHex64ToBuffer(uint64_t value, char* buffer) { + return InternalFastHexToBuffer(value, buffer, 16); +} + +char *FastHex32ToBuffer(uint32_t value, char* buffer) { + return InternalFastHexToBuffer(value, buffer, 8); +} + +// ---------------------------------------------------------------------- +// FastInt32ToBufferLeft() +// FastUInt32ToBufferLeft() +// FastInt64ToBufferLeft() +// FastUInt64ToBufferLeft() +// +// Like the Fast*ToBuffer() functions above, these are intended for speed. +// Unlike the Fast*ToBuffer() functions, however, these functions write +// their output to the beginning of the buffer (hence the name, as the +// output is left-aligned). The caller is responsible for ensuring that +// the buffer has enough space to hold the output. +// +// Returns a pointer to the end of the string (i.e. the null character +// terminating the string). +// ---------------------------------------------------------------------- + +static const char two_ASCII_digits[100][2] = { + {'0','0'}, {'0','1'}, {'0','2'}, {'0','3'}, {'0','4'}, + {'0','5'}, {'0','6'}, {'0','7'}, {'0','8'}, {'0','9'}, + {'1','0'}, {'1','1'}, {'1','2'}, {'1','3'}, {'1','4'}, + {'1','5'}, {'1','6'}, {'1','7'}, {'1','8'}, {'1','9'}, + {'2','0'}, {'2','1'}, {'2','2'}, {'2','3'}, {'2','4'}, + {'2','5'}, {'2','6'}, {'2','7'}, {'2','8'}, {'2','9'}, + {'3','0'}, {'3','1'}, {'3','2'}, {'3','3'}, {'3','4'}, + {'3','5'}, {'3','6'}, {'3','7'}, {'3','8'}, {'3','9'}, + {'4','0'}, {'4','1'}, {'4','2'}, {'4','3'}, {'4','4'}, + {'4','5'}, {'4','6'}, {'4','7'}, {'4','8'}, {'4','9'}, + {'5','0'}, {'5','1'}, {'5','2'}, {'5','3'}, {'5','4'}, + {'5','5'}, {'5','6'}, {'5','7'}, {'5','8'}, {'5','9'}, + {'6','0'}, {'6','1'}, {'6','2'}, {'6','3'}, {'6','4'}, + {'6','5'}, {'6','6'}, {'6','7'}, {'6','8'}, {'6','9'}, + {'7','0'}, {'7','1'}, {'7','2'}, {'7','3'}, {'7','4'}, + {'7','5'}, {'7','6'}, {'7','7'}, {'7','8'}, {'7','9'}, + {'8','0'}, {'8','1'}, {'8','2'}, {'8','3'}, {'8','4'}, + {'8','5'}, {'8','6'}, {'8','7'}, {'8','8'}, {'8','9'}, + {'9','0'}, {'9','1'}, {'9','2'}, {'9','3'}, {'9','4'}, + {'9','5'}, {'9','6'}, {'9','7'}, {'9','8'}, {'9','9'} +}; + +char* FastUInt32ToBufferLeft(uint32_t u, char* buffer) { + uint32_t digits; + const char *ASCII_digits = nullptr; + // The idea of this implementation is to trim the number of divides to as few + // as possible by using multiplication and subtraction rather than mod (%), + // and by outputting two digits at a time rather than one. + // The huge-number case is first, in the hopes that the compiler will output + // that case in one branch-free block of code, and only output conditional + // branches into it from below. + if (u >= 1000000000) { // >= 1,000,000,000 + digits = u / 100000000; // 100,000,000 + ASCII_digits = two_ASCII_digits[digits]; + buffer[0] = ASCII_digits[0]; + buffer[1] = ASCII_digits[1]; + buffer += 2; +sublt100_000_000: + u -= digits * 100000000; // 100,000,000 +lt100_000_000: + digits = u / 1000000; // 1,000,000 + ASCII_digits = two_ASCII_digits[digits]; + buffer[0] = ASCII_digits[0]; + buffer[1] = ASCII_digits[1]; + buffer += 2; +sublt1_000_000: + u -= digits * 1000000; // 1,000,000 +lt1_000_000: + digits = u / 10000; // 10,000 + ASCII_digits = two_ASCII_digits[digits]; + buffer[0] = ASCII_digits[0]; + buffer[1] = ASCII_digits[1]; + buffer += 2; +sublt10_000: + u -= digits * 10000; // 10,000 +lt10_000: + digits = u / 100; + ASCII_digits = two_ASCII_digits[digits]; + buffer[0] = ASCII_digits[0]; + buffer[1] = ASCII_digits[1]; + buffer += 2; +sublt100: + u -= digits * 100; +lt100: + digits = u; + ASCII_digits = two_ASCII_digits[digits]; + buffer[0] = ASCII_digits[0]; + buffer[1] = ASCII_digits[1]; + buffer += 2; +done: + *buffer = 0; + return buffer; + } + + if (u < 100) { + digits = u; + if (u >= 10) goto lt100; + *buffer++ = '0' + digits; + goto done; + } + if (u < 10000) { // 10,000 + if (u >= 1000) goto lt10_000; + digits = u / 100; + *buffer++ = '0' + digits; + goto sublt100; + } + if (u < 1000000) { // 1,000,000 + if (u >= 100000) goto lt1_000_000; + digits = u / 10000; // 10,000 + *buffer++ = '0' + digits; + goto sublt10_000; + } + if (u < 100000000) { // 100,000,000 + if (u >= 10000000) goto lt100_000_000; + digits = u / 1000000; // 1,000,000 + *buffer++ = '0' + digits; + goto sublt1_000_000; + } + // we already know that u < 1,000,000,000 + digits = u / 100000000; // 100,000,000 + *buffer++ = '0' + digits; + goto sublt100_000_000; +} + +char* FastInt32ToBufferLeft(int32_t i, char* buffer) { + uint32_t u = 0; + if (i < 0) { + *buffer++ = '-'; + u -= i; + } else { + u = i; + } + return FastUInt32ToBufferLeft(u, buffer); +} + +char* FastUInt64ToBufferLeft(uint64_t u64, char* buffer) { + int digits; + const char *ASCII_digits = nullptr; + + uint32_t u = static_cast<uint32_t>(u64); + if (u == u64) return FastUInt32ToBufferLeft(u, buffer); + + uint64_t top_11_digits = u64 / 1000000000; + buffer = FastUInt64ToBufferLeft(top_11_digits, buffer); + u = u64 - (top_11_digits * 1000000000); + + digits = u / 10000000; // 10,000,000 + GOOGLE_DCHECK_LT(digits, 100); + ASCII_digits = two_ASCII_digits[digits]; + buffer[0] = ASCII_digits[0]; + buffer[1] = ASCII_digits[1]; + buffer += 2; + u -= digits * 10000000; // 10,000,000 + digits = u / 100000; // 100,000 + ASCII_digits = two_ASCII_digits[digits]; + buffer[0] = ASCII_digits[0]; + buffer[1] = ASCII_digits[1]; + buffer += 2; + u -= digits * 100000; // 100,000 + digits = u / 1000; // 1,000 + ASCII_digits = two_ASCII_digits[digits]; + buffer[0] = ASCII_digits[0]; + buffer[1] = ASCII_digits[1]; + buffer += 2; + u -= digits * 1000; // 1,000 + digits = u / 10; + ASCII_digits = two_ASCII_digits[digits]; + buffer[0] = ASCII_digits[0]; + buffer[1] = ASCII_digits[1]; + buffer += 2; + u -= digits * 10; + digits = u; + *buffer++ = '0' + digits; + *buffer = 0; + return buffer; +} + +char* FastInt64ToBufferLeft(int64_t i, char* buffer) { + uint64_t u = 0; + if (i < 0) { + *buffer++ = '-'; + u -= i; + } else { + u = i; + } + return FastUInt64ToBufferLeft(u, buffer); +} + +// ---------------------------------------------------------------------- +// SimpleItoa() +// Description: converts an integer to a string. +// +// Return value: string +// ---------------------------------------------------------------------- + +std::string SimpleItoa(int i) { + char buffer[kFastToBufferSize]; + return (sizeof(i) == 4) ? + FastInt32ToBuffer(i, buffer) : + FastInt64ToBuffer(i, buffer); +} + +std::string SimpleItoa(unsigned int i) { + char buffer[kFastToBufferSize]; + return std::string(buffer, (sizeof(i) == 4) + ? FastUInt32ToBufferLeft(i, buffer) + : FastUInt64ToBufferLeft(i, buffer)); +} + +std::string SimpleItoa(long i) { + char buffer[kFastToBufferSize]; + return (sizeof(i) == 4) ? + FastInt32ToBuffer(i, buffer) : + FastInt64ToBuffer(i, buffer); +} + +std::string SimpleItoa(unsigned long i) { + char buffer[kFastToBufferSize]; + return std::string(buffer, (sizeof(i) == 4) + ? FastUInt32ToBufferLeft(i, buffer) + : FastUInt64ToBufferLeft(i, buffer)); +} + +std::string SimpleItoa(long long i) { + char buffer[kFastToBufferSize]; + return (sizeof(i) == 4) ? + FastInt32ToBuffer(i, buffer) : + FastInt64ToBuffer(i, buffer); +} + +std::string SimpleItoa(unsigned long long i) { + char buffer[kFastToBufferSize]; + return std::string(buffer, (sizeof(i) == 4) + ? FastUInt32ToBufferLeft(i, buffer) + : FastUInt64ToBufferLeft(i, buffer)); +} + +// ---------------------------------------------------------------------- +// SimpleDtoa() +// SimpleFtoa() +// DoubleToBuffer() +// FloatToBuffer() +// We want to print the value without losing precision, but we also do +// not want to print more digits than necessary. This turns out to be +// trickier than it sounds. Numbers like 0.2 cannot be represented +// exactly in binary. If we print 0.2 with a very large precision, +// e.g. "%.50g", we get "0.2000000000000000111022302462515654042363167". +// On the other hand, if we set the precision too low, we lose +// significant digits when printing numbers that actually need them. +// It turns out there is no precision value that does the right thing +// for all numbers. +// +// Our strategy is to first try printing with a precision that is never +// over-precise, then parse the result with strtod() to see if it +// matches. If not, we print again with a precision that will always +// give a precise result, but may use more digits than necessary. +// +// An arguably better strategy would be to use the algorithm described +// in "How to Print Floating-Point Numbers Accurately" by Steele & +// White, e.g. as implemented by David M. Gay's dtoa(). It turns out, +// however, that the following implementation is about as fast as +// DMG's code. Furthermore, DMG's code locks mutexes, which means it +// will not scale well on multi-core machines. DMG's code is slightly +// more accurate (in that it will never use more digits than +// necessary), but this is probably irrelevant for most users. +// +// Rob Pike and Ken Thompson also have an implementation of dtoa() in +// third_party/fmt/fltfmt.cc. Their implementation is similar to this +// one in that it makes guesses and then uses strtod() to check them. +// Their implementation is faster because they use their own code to +// generate the digits in the first place rather than use snprintf(), +// thus avoiding format string parsing overhead. However, this makes +// it considerably more complicated than the following implementation, +// and it is embedded in a larger library. If speed turns out to be +// an issue, we could re-implement this in terms of their +// implementation. +// ---------------------------------------------------------------------- + +std::string SimpleDtoa(double value) { + char buffer[kDoubleToBufferSize]; + return DoubleToBuffer(value, buffer); +} + +std::string SimpleFtoa(float value) { + char buffer[kFloatToBufferSize]; + return FloatToBuffer(value, buffer); +} + +static inline bool IsValidFloatChar(char c) { + return ('0' <= c && c <= '9') || + c == 'e' || c == 'E' || + c == '+' || c == '-'; +} + +void DelocalizeRadix(char* buffer) { + // Fast check: if the buffer has a normal decimal point, assume no + // translation is needed. + if (strchr(buffer, '.') != nullptr) return; + + // Find the first unknown character. + while (IsValidFloatChar(*buffer)) ++buffer; + + if (*buffer == '\0') { + // No radix character found. + return; + } + + // We are now pointing at the locale-specific radix character. Replace it + // with '.'. + *buffer = '.'; + ++buffer; + + if (!IsValidFloatChar(*buffer) && *buffer != '\0') { + // It appears the radix was a multi-byte character. We need to remove the + // extra bytes. + char* target = buffer; + do { ++buffer; } while (!IsValidFloatChar(*buffer) && *buffer != '\0'); + memmove(target, buffer, strlen(buffer) + 1); + } +} + +char* DoubleToBuffer(double value, char* buffer) { + // DBL_DIG is 15 for IEEE-754 doubles, which are used on almost all + // platforms these days. Just in case some system exists where DBL_DIG + // is significantly larger -- and risks overflowing our buffer -- we have + // this assert. + static_assert(DBL_DIG < 20, "DBL_DIG_is_too_big"); + + if (value == std::numeric_limits<double>::infinity()) { + strcpy(buffer, "inf"); + return buffer; + } else if (value == -std::numeric_limits<double>::infinity()) { + strcpy(buffer, "-inf"); + return buffer; + } else if (std::isnan(value)) { + strcpy(buffer, "nan"); + return buffer; + } + + int snprintf_result = + snprintf(buffer, kDoubleToBufferSize, "%.*g", DBL_DIG, value); + + // The snprintf should never overflow because the buffer is significantly + // larger than the precision we asked for. + GOOGLE_DCHECK(snprintf_result > 0 && snprintf_result < kDoubleToBufferSize); + + // We need to make parsed_value volatile in order to force the compiler to + // write it out to the stack. Otherwise, it may keep the value in a + // register, and if it does that, it may keep it as a long double instead + // of a double. This long double may have extra bits that make it compare + // unequal to "value" even though it would be exactly equal if it were + // truncated to a double. + volatile double parsed_value = internal::NoLocaleStrtod(buffer, nullptr); + if (parsed_value != value) { + snprintf_result = + snprintf(buffer, kDoubleToBufferSize, "%.*g", DBL_DIG + 2, value); + + // Should never overflow; see above. + GOOGLE_DCHECK(snprintf_result > 0 && snprintf_result < kDoubleToBufferSize); + } + + DelocalizeRadix(buffer); + return buffer; +} + +static int memcasecmp(const char *s1, const char *s2, size_t len) { + const unsigned char *us1 = reinterpret_cast<const unsigned char *>(s1); + const unsigned char *us2 = reinterpret_cast<const unsigned char *>(s2); + + for (size_t i = 0; i < len; i++) { + const int diff = + static_cast<int>(static_cast<unsigned char>(ascii_tolower(us1[i]))) - + static_cast<int>(static_cast<unsigned char>(ascii_tolower(us2[i]))); + if (diff != 0) return diff; + } + return 0; +} + +inline bool CaseEqual(StringPiece s1, StringPiece s2) { + if (s1.size() != s2.size()) return false; + return memcasecmp(s1.data(), s2.data(), s1.size()) == 0; +} + +bool safe_strtob(StringPiece str, bool* value) { + GOOGLE_CHECK(value != nullptr) << "nullptr output boolean given."; + if (CaseEqual(str, "true") || CaseEqual(str, "t") || + CaseEqual(str, "yes") || CaseEqual(str, "y") || + CaseEqual(str, "1")) { + *value = true; + return true; + } + if (CaseEqual(str, "false") || CaseEqual(str, "f") || + CaseEqual(str, "no") || CaseEqual(str, "n") || + CaseEqual(str, "0")) { + *value = false; + return true; + } + return false; +} + +bool safe_strtof(const char* str, float* value) { + char* endptr; + errno = 0; // errno only gets set on errors +#if defined(_WIN32) || defined (__hpux) // has no strtof() + *value = internal::NoLocaleStrtod(str, &endptr); +#else + *value = strtof(str, &endptr); +#endif + return *str != 0 && *endptr == 0 && errno == 0; +} + +bool safe_strtod(const char* str, double* value) { + char* endptr; + *value = internal::NoLocaleStrtod(str, &endptr); + if (endptr != str) { + while (ascii_isspace(*endptr)) ++endptr; + } + // Ignore range errors from strtod. The values it + // returns on underflow and overflow are the right + // fallback in a robust setting. + return *str != '\0' && *endptr == '\0'; +} + +bool safe_strto32(const std::string &str, int32_t *value) { + return safe_int_internal(str, value); +} + +bool safe_strtou32(const std::string &str, uint32_t *value) { + return safe_uint_internal(str, value); +} + +bool safe_strto64(const std::string &str, int64_t *value) { + return safe_int_internal(str, value); +} + +bool safe_strtou64(const std::string &str, uint64_t *value) { + return safe_uint_internal(str, value); +} + +char* FloatToBuffer(float value, char* buffer) { + // FLT_DIG is 6 for IEEE-754 floats, which are used on almost all + // platforms these days. Just in case some system exists where FLT_DIG + // is significantly larger -- and risks overflowing our buffer -- we have + // this assert. + static_assert(FLT_DIG < 10, "FLT_DIG_is_too_big"); + + if (value == std::numeric_limits<double>::infinity()) { + strcpy(buffer, "inf"); + return buffer; + } else if (value == -std::numeric_limits<double>::infinity()) { + strcpy(buffer, "-inf"); + return buffer; + } else if (std::isnan(value)) { + strcpy(buffer, "nan"); + return buffer; + } + + int snprintf_result = + snprintf(buffer, kFloatToBufferSize, "%.*g", FLT_DIG, value); + + // The snprintf should never overflow because the buffer is significantly + // larger than the precision we asked for. + GOOGLE_DCHECK(snprintf_result > 0 && snprintf_result < kFloatToBufferSize); + + float parsed_value; + if (!safe_strtof(buffer, &parsed_value) || parsed_value != value) { + snprintf_result = + snprintf(buffer, kFloatToBufferSize, "%.*g", FLT_DIG + 3, value); + + // Should never overflow; see above. + GOOGLE_DCHECK(snprintf_result > 0 && snprintf_result < kFloatToBufferSize); + } + + DelocalizeRadix(buffer); + return buffer; +} + +namespace strings { + +AlphaNum::AlphaNum(strings::Hex hex) { + char *const end = &digits[kFastToBufferSize]; + char *writer = end; + uint64_t value = hex.value; + uint64_t width = hex.spec; + // We accomplish minimum width by OR'ing in 0x10000 to the user's value, + // where 0x10000 is the smallest hex number that is as wide as the user + // asked for. + uint64_t mask = (static_cast<uint64_t>(1) << ((width - 1) * 4)) | value; + static const char hexdigits[] = "0123456789abcdef"; + do { + *--writer = hexdigits[value & 0xF]; + value >>= 4; + mask >>= 4; + } while (mask != 0); + piece_data_ = writer; + piece_size_ = end - writer; +} + +} // namespace strings + +// ---------------------------------------------------------------------- +// StrCat() +// This merges the given strings or integers, with no delimiter. This +// is designed to be the fastest possible way to construct a string out +// of a mix of raw C strings, C++ strings, and integer values. +// ---------------------------------------------------------------------- + +// Append is merely a version of memcpy that returns the address of the byte +// after the area just overwritten. It comes in multiple flavors to minimize +// call overhead. +static char *Append1(char *out, const AlphaNum &x) { + if (x.size() > 0) { + memcpy(out, x.data(), x.size()); + out += x.size(); + } + return out; +} + +static char *Append2(char *out, const AlphaNum &x1, const AlphaNum &x2) { + if (x1.size() > 0) { + memcpy(out, x1.data(), x1.size()); + out += x1.size(); + } + if (x2.size() > 0) { + memcpy(out, x2.data(), x2.size()); + out += x2.size(); + } + return out; +} + +static char *Append4(char *out, const AlphaNum &x1, const AlphaNum &x2, + const AlphaNum &x3, const AlphaNum &x4) { + if (x1.size() > 0) { + memcpy(out, x1.data(), x1.size()); + out += x1.size(); + } + if (x2.size() > 0) { + memcpy(out, x2.data(), x2.size()); + out += x2.size(); + } + if (x3.size() > 0) { + memcpy(out, x3.data(), x3.size()); + out += x3.size(); + } + if (x4.size() > 0) { + memcpy(out, x4.data(), x4.size()); + out += x4.size(); + } + return out; +} + +std::string StrCat(const AlphaNum &a, const AlphaNum &b) { + std::string result; + result.resize(a.size() + b.size()); + char *const begin = &*result.begin(); + char *out = Append2(begin, a, b); + GOOGLE_DCHECK_EQ(out, begin + result.size()); + return result; +} + +std::string StrCat(const AlphaNum &a, const AlphaNum &b, const AlphaNum &c) { + std::string result; + result.resize(a.size() + b.size() + c.size()); + char *const begin = &*result.begin(); + char *out = Append2(begin, a, b); + out = Append1(out, c); + GOOGLE_DCHECK_EQ(out, begin + result.size()); + return result; +} + +std::string StrCat(const AlphaNum &a, const AlphaNum &b, const AlphaNum &c, + const AlphaNum &d) { + std::string result; + result.resize(a.size() + b.size() + c.size() + d.size()); + char *const begin = &*result.begin(); + char *out = Append4(begin, a, b, c, d); + GOOGLE_DCHECK_EQ(out, begin + result.size()); + return result; +} + +std::string StrCat(const AlphaNum &a, const AlphaNum &b, const AlphaNum &c, + const AlphaNum &d, const AlphaNum &e) { + std::string result; + result.resize(a.size() + b.size() + c.size() + d.size() + e.size()); + char *const begin = &*result.begin(); + char *out = Append4(begin, a, b, c, d); + out = Append1(out, e); + GOOGLE_DCHECK_EQ(out, begin + result.size()); + return result; +} + +std::string StrCat(const AlphaNum &a, const AlphaNum &b, const AlphaNum &c, + const AlphaNum &d, const AlphaNum &e, const AlphaNum &f) { + std::string result; + result.resize(a.size() + b.size() + c.size() + d.size() + e.size() + + f.size()); + char *const begin = &*result.begin(); + char *out = Append4(begin, a, b, c, d); + out = Append2(out, e, f); + GOOGLE_DCHECK_EQ(out, begin + result.size()); + return result; +} + +std::string StrCat(const AlphaNum &a, const AlphaNum &b, const AlphaNum &c, + const AlphaNum &d, const AlphaNum &e, const AlphaNum &f, + const AlphaNum &g) { + std::string result; + result.resize(a.size() + b.size() + c.size() + d.size() + e.size() + + f.size() + g.size()); + char *const begin = &*result.begin(); + char *out = Append4(begin, a, b, c, d); + out = Append2(out, e, f); + out = Append1(out, g); + GOOGLE_DCHECK_EQ(out, begin + result.size()); + return result; +} + +std::string StrCat(const AlphaNum &a, const AlphaNum &b, const AlphaNum &c, + const AlphaNum &d, const AlphaNum &e, const AlphaNum &f, + const AlphaNum &g, const AlphaNum &h) { + std::string result; + result.resize(a.size() + b.size() + c.size() + d.size() + e.size() + + f.size() + g.size() + h.size()); + char *const begin = &*result.begin(); + char *out = Append4(begin, a, b, c, d); + out = Append4(out, e, f, g, h); + GOOGLE_DCHECK_EQ(out, begin + result.size()); + return result; +} + +std::string StrCat(const AlphaNum &a, const AlphaNum &b, const AlphaNum &c, + const AlphaNum &d, const AlphaNum &e, const AlphaNum &f, + const AlphaNum &g, const AlphaNum &h, const AlphaNum &i) { + std::string result; + result.resize(a.size() + b.size() + c.size() + d.size() + e.size() + + f.size() + g.size() + h.size() + i.size()); + char *const begin = &*result.begin(); + char *out = Append4(begin, a, b, c, d); + out = Append4(out, e, f, g, h); + out = Append1(out, i); + GOOGLE_DCHECK_EQ(out, begin + result.size()); + return result; +} + +// It's possible to call StrAppend with a char * pointer that is partway into +// the string we're appending to. However the results of this are random. +// Therefore, check for this in debug mode. Use unsigned math so we only have +// to do one comparison. +#define GOOGLE_DCHECK_NO_OVERLAP(dest, src) \ + GOOGLE_DCHECK_GT(uintptr_t((src).data() - (dest).data()), \ + uintptr_t((dest).size())) + +void StrAppend(std::string *result, const AlphaNum &a) { + GOOGLE_DCHECK_NO_OVERLAP(*result, a); + result->append(a.data(), a.size()); +} + +void StrAppend(std::string *result, const AlphaNum &a, const AlphaNum &b) { + GOOGLE_DCHECK_NO_OVERLAP(*result, a); + GOOGLE_DCHECK_NO_OVERLAP(*result, b); + std::string::size_type old_size = result->size(); + result->resize(old_size + a.size() + b.size()); + char *const begin = &*result->begin(); + char *out = Append2(begin + old_size, a, b); + GOOGLE_DCHECK_EQ(out, begin + result->size()); +} + +void StrAppend(std::string *result, const AlphaNum &a, const AlphaNum &b, + const AlphaNum &c) { + GOOGLE_DCHECK_NO_OVERLAP(*result, a); + GOOGLE_DCHECK_NO_OVERLAP(*result, b); + GOOGLE_DCHECK_NO_OVERLAP(*result, c); + std::string::size_type old_size = result->size(); + result->resize(old_size + a.size() + b.size() + c.size()); + char *const begin = &*result->begin(); + char *out = Append2(begin + old_size, a, b); + out = Append1(out, c); + GOOGLE_DCHECK_EQ(out, begin + result->size()); +} + +void StrAppend(std::string *result, const AlphaNum &a, const AlphaNum &b, + const AlphaNum &c, const AlphaNum &d) { + GOOGLE_DCHECK_NO_OVERLAP(*result, a); + GOOGLE_DCHECK_NO_OVERLAP(*result, b); + GOOGLE_DCHECK_NO_OVERLAP(*result, c); + GOOGLE_DCHECK_NO_OVERLAP(*result, d); + std::string::size_type old_size = result->size(); + result->resize(old_size + a.size() + b.size() + c.size() + d.size()); + char *const begin = &*result->begin(); + char *out = Append4(begin + old_size, a, b, c, d); + GOOGLE_DCHECK_EQ(out, begin + result->size()); +} + +int GlobalReplaceSubstring(const std::string &substring, + const std::string &replacement, std::string *s) { + GOOGLE_CHECK(s != nullptr); + if (s->empty() || substring.empty()) + return 0; + std::string tmp; + int num_replacements = 0; + int pos = 0; + for (StringPiece::size_type match_pos = + s->find(substring.data(), pos, substring.length()); + match_pos != std::string::npos; pos = match_pos + substring.length(), + match_pos = s->find(substring.data(), pos, + substring.length())) { + ++num_replacements; + // Append the original content before the match. + tmp.append(*s, pos, match_pos - pos); + // Append the replacement for the match. + tmp.append(replacement.begin(), replacement.end()); + } + // Append the content after the last match. If no replacements were made, the + // original string is left untouched. + if (num_replacements > 0) { + tmp.append(*s, pos, s->length() - pos); + s->swap(tmp); + } + return num_replacements; +} + +int CalculateBase64EscapedLen(int input_len, bool do_padding) { + // Base64 encodes three bytes of input at a time. If the input is not + // divisible by three, we pad as appropriate. + // + // (from http://tools.ietf.org/html/rfc3548) + // Special processing is performed if fewer than 24 bits are available + // at the end of the data being encoded. A full encoding quantum is + // always completed at the end of a quantity. When fewer than 24 input + // bits are available in an input group, zero bits are added (on the + // right) to form an integral number of 6-bit groups. Padding at the + // end of the data is performed using the '=' character. Since all base + // 64 input is an integral number of octets, only the following cases + // can arise: + + + // Base64 encodes each three bytes of input into four bytes of output. + int len = (input_len / 3) * 4; + + if (input_len % 3 == 0) { + // (from http://tools.ietf.org/html/rfc3548) + // (1) the final quantum of encoding input is an integral multiple of 24 + // bits; here, the final unit of encoded output will be an integral + // multiple of 4 characters with no "=" padding, + } else if (input_len % 3 == 1) { + // (from http://tools.ietf.org/html/rfc3548) + // (2) the final quantum of encoding input is exactly 8 bits; here, the + // final unit of encoded output will be two characters followed by two + // "=" padding characters, or + len += 2; + if (do_padding) { + len += 2; + } + } else { // (input_len % 3 == 2) + // (from http://tools.ietf.org/html/rfc3548) + // (3) the final quantum of encoding input is exactly 16 bits; here, the + // final unit of encoded output will be three characters followed by one + // "=" padding character. + len += 3; + if (do_padding) { + len += 1; + } + } + + assert(len >= input_len); // make sure we didn't overflow + return len; +} + +// Base64Escape does padding, so this calculation includes padding. +int CalculateBase64EscapedLen(int input_len) { + return CalculateBase64EscapedLen(input_len, true); +} + +// ---------------------------------------------------------------------- +// int Base64Unescape() - base64 decoder +// int Base64Escape() - base64 encoder +// int WebSafeBase64Unescape() - Google's variation of base64 decoder +// int WebSafeBase64Escape() - Google's variation of base64 encoder +// +// Check out +// http://tools.ietf.org/html/rfc2045 for formal description, but what we +// care about is that... +// Take the encoded stuff in groups of 4 characters and turn each +// character into a code 0 to 63 thus: +// A-Z map to 0 to 25 +// a-z map to 26 to 51 +// 0-9 map to 52 to 61 +// +(- for WebSafe) maps to 62 +// /(_ for WebSafe) maps to 63 +// There will be four numbers, all less than 64 which can be represented +// by a 6 digit binary number (aaaaaa, bbbbbb, cccccc, dddddd respectively). +// Arrange the 6 digit binary numbers into three bytes as such: +// aaaaaabb bbbbcccc ccdddddd +// Equals signs (one or two) are used at the end of the encoded block to +// indicate that the text was not an integer multiple of three bytes long. +// ---------------------------------------------------------------------- + +int Base64UnescapeInternal(const char *src_param, int szsrc, + char *dest, int szdest, + const signed char* unbase64) { + static const char kPad64Equals = '='; + static const char kPad64Dot = '.'; + + int decode = 0; + int destidx = 0; + int state = 0; + unsigned int ch = 0; + unsigned int temp = 0; + + // If "char" is signed by default, using *src as an array index results in + // accessing negative array elements. Treat the input as a pointer to + // unsigned char to avoid this. + const unsigned char *src = reinterpret_cast<const unsigned char*>(src_param); + + // The GET_INPUT macro gets the next input character, skipping + // over any whitespace, and stopping when we reach the end of the + // string or when we read any non-data character. The arguments are + // an arbitrary identifier (used as a label for goto) and the number + // of data bytes that must remain in the input to avoid aborting the + // loop. +#define GET_INPUT(label, remain) \ + label: \ + --szsrc; \ + ch = *src++; \ + decode = unbase64[ch]; \ + if (decode < 0) { \ + if (ascii_isspace(ch) && szsrc >= remain) \ + goto label; \ + state = 4 - remain; \ + break; \ + } + + // if dest is null, we're just checking to see if it's legal input + // rather than producing output. (I suspect this could just be done + // with a regexp...). We duplicate the loop so this test can be + // outside it instead of in every iteration. + + if (dest) { + // This loop consumes 4 input bytes and produces 3 output bytes + // per iteration. We can't know at the start that there is enough + // data left in the string for a full iteration, so the loop may + // break out in the middle; if so 'state' will be set to the + // number of input bytes read. + + while (szsrc >= 4) { + // We'll start by optimistically assuming that the next four + // bytes of the string (src[0..3]) are four good data bytes + // (that is, no nulls, whitespace, padding chars, or illegal + // chars). We need to test src[0..2] for nulls individually + // before constructing temp to preserve the property that we + // never read past a null in the string (no matter how long + // szsrc claims the string is). + + if (!src[0] || !src[1] || !src[2] || + (temp = ((unsigned(unbase64[src[0]]) << 18) | + (unsigned(unbase64[src[1]]) << 12) | + (unsigned(unbase64[src[2]]) << 6) | + (unsigned(unbase64[src[3]])))) & 0x80000000) { + // Iff any of those four characters was bad (null, illegal, + // whitespace, padding), then temp's high bit will be set + // (because unbase64[] is -1 for all bad characters). + // + // We'll back up and resort to the slower decoder, which knows + // how to handle those cases. + + GET_INPUT(first, 4); + temp = decode; + GET_INPUT(second, 3); + temp = (temp << 6) | decode; + GET_INPUT(third, 2); + temp = (temp << 6) | decode; + GET_INPUT(fourth, 1); + temp = (temp << 6) | decode; + } else { + // We really did have four good data bytes, so advance four + // characters in the string. + + szsrc -= 4; + src += 4; + decode = -1; + ch = '\0'; + } + + // temp has 24 bits of input, so write that out as three bytes. + + if (destidx+3 > szdest) return -1; + dest[destidx+2] = temp; + temp >>= 8; + dest[destidx+1] = temp; + temp >>= 8; + dest[destidx] = temp; + destidx += 3; + } + } else { + while (szsrc >= 4) { + if (!src[0] || !src[1] || !src[2] || + (temp = ((unsigned(unbase64[src[0]]) << 18) | + (unsigned(unbase64[src[1]]) << 12) | + (unsigned(unbase64[src[2]]) << 6) | + (unsigned(unbase64[src[3]])))) & 0x80000000) { + GET_INPUT(first_no_dest, 4); + GET_INPUT(second_no_dest, 3); + GET_INPUT(third_no_dest, 2); + GET_INPUT(fourth_no_dest, 1); + } else { + szsrc -= 4; + src += 4; + decode = -1; + ch = '\0'; + } + destidx += 3; + } + } + +#undef GET_INPUT + + // if the loop terminated because we read a bad character, return + // now. + if (decode < 0 && ch != '\0' && + ch != kPad64Equals && ch != kPad64Dot && !ascii_isspace(ch)) + return -1; + + if (ch == kPad64Equals || ch == kPad64Dot) { + // if we stopped by hitting an '=' or '.', un-read that character -- we'll + // look at it again when we count to check for the proper number of + // equals signs at the end. + ++szsrc; + --src; + } else { + // This loop consumes 1 input byte per iteration. It's used to + // clean up the 0-3 input bytes remaining when the first, faster + // loop finishes. 'temp' contains the data from 'state' input + // characters read by the first loop. + while (szsrc > 0) { + --szsrc; + ch = *src++; + decode = unbase64[ch]; + if (decode < 0) { + if (ascii_isspace(ch)) { + continue; + } else if (ch == '\0') { + break; + } else if (ch == kPad64Equals || ch == kPad64Dot) { + // back up one character; we'll read it again when we check + // for the correct number of pad characters at the end. + ++szsrc; + --src; + break; + } else { + return -1; + } + } + + // Each input character gives us six bits of output. + temp = (temp << 6) | decode; + ++state; + if (state == 4) { + // If we've accumulated 24 bits of output, write that out as + // three bytes. + if (dest) { + if (destidx+3 > szdest) return -1; + dest[destidx+2] = temp; + temp >>= 8; + dest[destidx+1] = temp; + temp >>= 8; + dest[destidx] = temp; + } + destidx += 3; + state = 0; + temp = 0; + } + } + } + + // Process the leftover data contained in 'temp' at the end of the input. + int expected_equals = 0; + switch (state) { + case 0: + // Nothing left over; output is a multiple of 3 bytes. + break; + + case 1: + // Bad input; we have 6 bits left over. + return -1; + + case 2: + // Produce one more output byte from the 12 input bits we have left. + if (dest) { + if (destidx+1 > szdest) return -1; + temp >>= 4; + dest[destidx] = temp; + } + ++destidx; + expected_equals = 2; + break; + + case 3: + // Produce two more output bytes from the 18 input bits we have left. + if (dest) { + if (destidx+2 > szdest) return -1; + temp >>= 2; + dest[destidx+1] = temp; + temp >>= 8; + dest[destidx] = temp; + } + destidx += 2; + expected_equals = 1; + break; + + default: + // state should have no other values at this point. + GOOGLE_LOG(FATAL) << "This can't happen; base64 decoder state = " << state; + } + + // The remainder of the string should be all whitespace, mixed with + // exactly 0 equals signs, or exactly 'expected_equals' equals + // signs. (Always accepting 0 equals signs is a google extension + // not covered in the RFC, as is accepting dot as the pad character.) + + int equals = 0; + while (szsrc > 0 && *src) { + if (*src == kPad64Equals || *src == kPad64Dot) + ++equals; + else if (!ascii_isspace(*src)) + return -1; + --szsrc; + ++src; + } + + return (equals == 0 || equals == expected_equals) ? destidx : -1; +} + +// The arrays below were generated by the following code +// #include <sys/time.h> +// #include <stdlib.h> +// #include <string.h> +// #include <stdio.h> +// main() +// { +// static const char Base64[] = +// "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; +// const char *pos; +// int idx, i, j; +// printf(" "); +// for (i = 0; i < 255; i += 8) { +// for (j = i; j < i + 8; j++) { +// pos = strchr(Base64, j); +// if ((pos == nullptr) || (j == 0)) +// idx = -1; +// else +// idx = pos - Base64; +// if (idx == -1) +// printf(" %2d, ", idx); +// else +// printf(" %2d/""*%c*""/,", idx, j); +// } +// printf("\n "); +// } +// } +// +// where the value of "Base64[]" was replaced by one of the base-64 conversion +// tables from the functions below. +static const signed char kUnBase64[] = { + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 62/*+*/, -1, -1, -1, 63/*/ */, + 52/*0*/, 53/*1*/, 54/*2*/, 55/*3*/, 56/*4*/, 57/*5*/, 58/*6*/, 59/*7*/, + 60/*8*/, 61/*9*/, -1, -1, -1, -1, -1, -1, + -1, 0/*A*/, 1/*B*/, 2/*C*/, 3/*D*/, 4/*E*/, 5/*F*/, 6/*G*/, + 7/*H*/, 8/*I*/, 9/*J*/, 10/*K*/, 11/*L*/, 12/*M*/, 13/*N*/, 14/*O*/, + 15/*P*/, 16/*Q*/, 17/*R*/, 18/*S*/, 19/*T*/, 20/*U*/, 21/*V*/, 22/*W*/, + 23/*X*/, 24/*Y*/, 25/*Z*/, -1, -1, -1, -1, -1, + -1, 26/*a*/, 27/*b*/, 28/*c*/, 29/*d*/, 30/*e*/, 31/*f*/, 32/*g*/, + 33/*h*/, 34/*i*/, 35/*j*/, 36/*k*/, 37/*l*/, 38/*m*/, 39/*n*/, 40/*o*/, + 41/*p*/, 42/*q*/, 43/*r*/, 44/*s*/, 45/*t*/, 46/*u*/, 47/*v*/, 48/*w*/, + 49/*x*/, 50/*y*/, 51/*z*/, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1 +}; +static const signed char kUnWebSafeBase64[] = { + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 62/*-*/, -1, -1, + 52/*0*/, 53/*1*/, 54/*2*/, 55/*3*/, 56/*4*/, 57/*5*/, 58/*6*/, 59/*7*/, + 60/*8*/, 61/*9*/, -1, -1, -1, -1, -1, -1, + -1, 0/*A*/, 1/*B*/, 2/*C*/, 3/*D*/, 4/*E*/, 5/*F*/, 6/*G*/, + 7/*H*/, 8/*I*/, 9/*J*/, 10/*K*/, 11/*L*/, 12/*M*/, 13/*N*/, 14/*O*/, + 15/*P*/, 16/*Q*/, 17/*R*/, 18/*S*/, 19/*T*/, 20/*U*/, 21/*V*/, 22/*W*/, + 23/*X*/, 24/*Y*/, 25/*Z*/, -1, -1, -1, -1, 63/*_*/, + -1, 26/*a*/, 27/*b*/, 28/*c*/, 29/*d*/, 30/*e*/, 31/*f*/, 32/*g*/, + 33/*h*/, 34/*i*/, 35/*j*/, 36/*k*/, 37/*l*/, 38/*m*/, 39/*n*/, 40/*o*/, + 41/*p*/, 42/*q*/, 43/*r*/, 44/*s*/, 45/*t*/, 46/*u*/, 47/*v*/, 48/*w*/, + 49/*x*/, 50/*y*/, 51/*z*/, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1 +}; + +int WebSafeBase64Unescape(const char *src, int szsrc, char *dest, int szdest) { + return Base64UnescapeInternal(src, szsrc, dest, szdest, kUnWebSafeBase64); +} + +static bool Base64UnescapeInternal(const char *src, int slen, std::string *dest, + const signed char *unbase64) { + // Determine the size of the output string. Base64 encodes every 3 bytes into + // 4 characters. any leftover chars are added directly for good measure. + // This is documented in the base64 RFC: http://tools.ietf.org/html/rfc3548 + const int dest_len = 3 * (slen / 4) + (slen % 4); + + dest->resize(dest_len); + + // We are getting the destination buffer by getting the beginning of the + // string and converting it into a char *. + const int len = Base64UnescapeInternal(src, slen, string_as_array(dest), + dest_len, unbase64); + if (len < 0) { + dest->clear(); + return false; + } + + // could be shorter if there was padding + GOOGLE_DCHECK_LE(len, dest_len); + dest->erase(len); + + return true; +} + +bool Base64Unescape(StringPiece src, std::string *dest) { + return Base64UnescapeInternal(src.data(), src.size(), dest, kUnBase64); +} + +bool WebSafeBase64Unescape(StringPiece src, std::string *dest) { + return Base64UnescapeInternal(src.data(), src.size(), dest, kUnWebSafeBase64); +} + +int Base64EscapeInternal(const unsigned char *src, int szsrc, + char *dest, int szdest, const char *base64, + bool do_padding) { + static const char kPad64 = '='; + + if (szsrc <= 0) return 0; + + if (szsrc * 4 > szdest * 3) return 0; + + char *cur_dest = dest; + const unsigned char *cur_src = src; + + char *limit_dest = dest + szdest; + const unsigned char *limit_src = src + szsrc; + + // Three bytes of data encodes to four characters of ciphertext. + // So we can pump through three-byte chunks atomically. + while (cur_src < limit_src - 3) { // keep going as long as we have >= 32 bits + uint32_t in = BigEndian::Load32(cur_src) >> 8; + + cur_dest[0] = base64[in >> 18]; + in &= 0x3FFFF; + cur_dest[1] = base64[in >> 12]; + in &= 0xFFF; + cur_dest[2] = base64[in >> 6]; + in &= 0x3F; + cur_dest[3] = base64[in]; + + cur_dest += 4; + cur_src += 3; + } + // To save time, we didn't update szdest or szsrc in the loop. So do it now. + szdest = limit_dest - cur_dest; + szsrc = limit_src - cur_src; + + /* now deal with the tail (<=3 bytes) */ + switch (szsrc) { + case 0: + // Nothing left; nothing more to do. + break; + case 1: { + // One byte left: this encodes to two characters, and (optionally) + // two pad characters to round out the four-character cipherblock. + if ((szdest -= 2) < 0) return 0; + uint32_t in = cur_src[0]; + cur_dest[0] = base64[in >> 2]; + in &= 0x3; + cur_dest[1] = base64[in << 4]; + cur_dest += 2; + if (do_padding) { + if ((szdest -= 2) < 0) return 0; + cur_dest[0] = kPad64; + cur_dest[1] = kPad64; + cur_dest += 2; + } + break; + } + case 2: { + // Two bytes left: this encodes to three characters, and (optionally) + // one pad character to round out the four-character cipherblock. + if ((szdest -= 3) < 0) return 0; + uint32_t in = BigEndian::Load16(cur_src); + cur_dest[0] = base64[in >> 10]; + in &= 0x3FF; + cur_dest[1] = base64[in >> 4]; + in &= 0x00F; + cur_dest[2] = base64[in << 2]; + cur_dest += 3; + if (do_padding) { + if ((szdest -= 1) < 0) return 0; + cur_dest[0] = kPad64; + cur_dest += 1; + } + break; + } + case 3: { + // Three bytes left: same as in the big loop above. We can't do this in + // the loop because the loop above always reads 4 bytes, and the fourth + // byte is past the end of the input. + if ((szdest -= 4) < 0) return 0; + uint32_t in = (cur_src[0] << 16) + BigEndian::Load16(cur_src + 1); + cur_dest[0] = base64[in >> 18]; + in &= 0x3FFFF; + cur_dest[1] = base64[in >> 12]; + in &= 0xFFF; + cur_dest[2] = base64[in >> 6]; + in &= 0x3F; + cur_dest[3] = base64[in]; + cur_dest += 4; + break; + } + default: + // Should not be reached: blocks of 4 bytes are handled + // in the while loop before this switch statement. + GOOGLE_LOG(FATAL) << "Logic problem? szsrc = " << szsrc; + break; + } + return (cur_dest - dest); +} + +static const char kBase64Chars[] = +"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + +static const char kWebSafeBase64Chars[] = +"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"; + +int Base64Escape(const unsigned char *src, int szsrc, char *dest, int szdest) { + return Base64EscapeInternal(src, szsrc, dest, szdest, kBase64Chars, true); +} +int WebSafeBase64Escape(const unsigned char *src, int szsrc, char *dest, + int szdest, bool do_padding) { + return Base64EscapeInternal(src, szsrc, dest, szdest, + kWebSafeBase64Chars, do_padding); +} + +void Base64EscapeInternal(const unsigned char *src, int szsrc, + std::string *dest, bool do_padding, + const char *base64_chars) { + const int calc_escaped_size = + CalculateBase64EscapedLen(szsrc, do_padding); + dest->resize(calc_escaped_size); + const int escaped_len = Base64EscapeInternal(src, szsrc, + string_as_array(dest), + dest->size(), + base64_chars, + do_padding); + GOOGLE_DCHECK_EQ(calc_escaped_size, escaped_len); + dest->erase(escaped_len); +} + +void Base64Escape(const unsigned char *src, int szsrc, std::string *dest, + bool do_padding) { + Base64EscapeInternal(src, szsrc, dest, do_padding, kBase64Chars); +} + +void WebSafeBase64Escape(const unsigned char *src, int szsrc, std::string *dest, + bool do_padding) { + Base64EscapeInternal(src, szsrc, dest, do_padding, kWebSafeBase64Chars); +} + +void Base64Escape(StringPiece src, std::string *dest) { + Base64Escape(reinterpret_cast<const unsigned char*>(src.data()), + src.size(), dest, true); +} + +void WebSafeBase64Escape(StringPiece src, std::string *dest) { + WebSafeBase64Escape(reinterpret_cast<const unsigned char*>(src.data()), + src.size(), dest, false); +} + +void WebSafeBase64EscapeWithPadding(StringPiece src, std::string *dest) { + WebSafeBase64Escape(reinterpret_cast<const unsigned char*>(src.data()), + src.size(), dest, true); +} + +// Helper to append a Unicode code point to a string as UTF8, without bringing +// in any external dependencies. +int EncodeAsUTF8Char(uint32_t code_point, char* output) { + uint32_t tmp = 0; + int len = 0; + if (code_point <= 0x7f) { + tmp = code_point; + len = 1; + } else if (code_point <= 0x07ff) { + tmp = 0x0000c080 | + ((code_point & 0x07c0) << 2) | + (code_point & 0x003f); + len = 2; + } else if (code_point <= 0xffff) { + tmp = 0x00e08080 | + ((code_point & 0xf000) << 4) | + ((code_point & 0x0fc0) << 2) | + (code_point & 0x003f); + len = 3; + } else { + // UTF-16 is only defined for code points up to 0x10FFFF, and UTF-8 is + // normally only defined up to there as well. + tmp = 0xf0808080 | + ((code_point & 0x1c0000) << 6) | + ((code_point & 0x03f000) << 4) | + ((code_point & 0x000fc0) << 2) | + (code_point & 0x003f); + len = 4; + } + tmp = ghtonl(tmp); + memcpy(output, reinterpret_cast<const char*>(&tmp) + sizeof(tmp) - len, len); + return len; +} + +// Table of UTF-8 character lengths, based on first byte +static const unsigned char kUTF8LenTbl[256] = { + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 4, 4, 4, 4, 4, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}; + +// Return length of a single UTF-8 source character +int UTF8FirstLetterNumBytes(const char* src, int len) { + if (len == 0) { + return 0; + } + return kUTF8LenTbl[*reinterpret_cast<const uint8_t*>(src)]; +} + +// ---------------------------------------------------------------------- +// CleanStringLineEndings() +// Clean up a multi-line string to conform to Unix line endings. +// Reads from src and appends to dst, so usually dst should be empty. +// +// If there is no line ending at the end of a non-empty string, it can +// be added automatically. +// +// Four different types of input are correctly handled: +// +// - Unix/Linux files: line ending is LF: pass through unchanged +// +// - DOS/Windows files: line ending is CRLF: convert to LF +// +// - Legacy Mac files: line ending is CR: convert to LF +// +// - Garbled files: random line endings: convert gracefully +// lonely CR, lonely LF, CRLF: convert to LF +// +// @param src The multi-line string to convert +// @param dst The converted string is appended to this string +// @param auto_end_last_line Automatically terminate the last line +// +// Limitations: +// +// This does not do the right thing for CRCRLF files created by +// broken programs that do another Unix->DOS conversion on files +// that are already in CRLF format. For this, a two-pass approach +// brute-force would be needed that +// +// (1) determines the presence of LF (first one is ok) +// (2) if yes, removes any CR, else convert every CR to LF + +void CleanStringLineEndings(const std::string &src, std::string *dst, + bool auto_end_last_line) { + if (dst->empty()) { + dst->append(src); + CleanStringLineEndings(dst, auto_end_last_line); + } else { + std::string tmp = src; + CleanStringLineEndings(&tmp, auto_end_last_line); + dst->append(tmp); + } +} + +void CleanStringLineEndings(std::string *str, bool auto_end_last_line) { + ptrdiff_t output_pos = 0; + bool r_seen = false; + ptrdiff_t len = str->size(); + + char *p = &(*str)[0]; + + for (ptrdiff_t input_pos = 0; input_pos < len;) { + if (!r_seen && input_pos + 8 < len) { + uint64_t v = GOOGLE_UNALIGNED_LOAD64(p + input_pos); + // Loop over groups of 8 bytes at a time until we come across + // a word that has a byte whose value is less than or equal to + // '\r' (i.e. could contain a \n (0x0a) or a \r (0x0d) ). + // + // We use a has_less macro that quickly tests a whole 64-bit + // word to see if any of the bytes has a value < N. + // + // For more details, see: + // http://graphics.stanford.edu/~seander/bithacks.html#HasLessInWord +#define has_less(x, n) (((x) - ~0ULL / 255 * (n)) & ~(x) & ~0ULL / 255 * 128) + if (!has_less(v, '\r' + 1)) { +#undef has_less + // No byte in this word has a value that could be a \r or a \n + if (output_pos != input_pos) { + GOOGLE_UNALIGNED_STORE64(p + output_pos, v); + } + input_pos += 8; + output_pos += 8; + continue; + } + } + std::string::const_reference in = p[input_pos]; + if (in == '\r') { + if (r_seen) p[output_pos++] = '\n'; + r_seen = true; + } else if (in == '\n') { + if (input_pos != output_pos) + p[output_pos++] = '\n'; + else + output_pos++; + r_seen = false; + } else { + if (r_seen) p[output_pos++] = '\n'; + r_seen = false; + if (input_pos != output_pos) + p[output_pos++] = in; + else + output_pos++; + } + input_pos++; + } + if (r_seen || + (auto_end_last_line && output_pos > 0 && p[output_pos - 1] != '\n')) { + str->resize(output_pos + 1); + str->operator[](output_pos) = '\n'; + } else if (output_pos < len) { + str->resize(output_pos); + } +} + +namespace internal { + +// ---------------------------------------------------------------------- +// NoLocaleStrtod() +// This code will make you cry. +// ---------------------------------------------------------------------- + +namespace { + +// Returns a string identical to *input except that the character pointed to +// by radix_pos (which should be '.') is replaced with the locale-specific +// radix character. +std::string LocalizeRadix(const char *input, const char *radix_pos) { + // Determine the locale-specific radix character by calling sprintf() to + // print the number 1.5, then stripping off the digits. As far as I can + // tell, this is the only portable, thread-safe way to get the C library + // to divuldge the locale's radix character. No, localeconv() is NOT + // thread-safe. + char temp[16]; + int size = snprintf(temp, sizeof(temp), "%.1f", 1.5); + GOOGLE_CHECK_EQ(temp[0], '1'); + GOOGLE_CHECK_EQ(temp[size - 1], '5'); + GOOGLE_CHECK_LE(size, 6); + + // Now replace the '.' in the input with it. + std::string result; + result.reserve(strlen(input) + size - 3); + result.append(input, radix_pos); + result.append(temp + 1, size - 2); + result.append(radix_pos + 1); + return result; +} + +} // namespace + +double NoLocaleStrtod(const char *str, char **endptr) { + // We cannot simply set the locale to "C" temporarily with setlocale() + // as this is not thread-safe. Instead, we try to parse in the current + // locale first. If parsing stops at a '.' character, then this is a + // pretty good hint that we're actually in some other locale in which + // '.' is not the radix character. + + char *temp_endptr; + double result = strtod(str, &temp_endptr); + if (endptr != NULL) *endptr = temp_endptr; + if (*temp_endptr != '.') return result; + + // Parsing halted on a '.'. Perhaps we're in a different locale? Let's + // try to replace the '.' with a locale-specific radix character and + // try again. + std::string localized = LocalizeRadix(str, temp_endptr); + const char *localized_cstr = localized.c_str(); + char *localized_endptr; + result = strtod(localized_cstr, &localized_endptr); + if ((localized_endptr - localized_cstr) > (temp_endptr - str)) { + // This attempt got further, so replacing the decimal must have helped. + // Update endptr to point at the right location. + if (endptr != NULL) { + // size_diff is non-zero if the localized radix has multiple bytes. + int size_diff = localized.size() - strlen(str); + // const_cast is necessary to match the strtod() interface. + *endptr = const_cast<char *>( + str + (localized_endptr - localized_cstr - size_diff)); + } + } + + return result; +} + +} // namespace internal + +} // namespace protobuf +} // namespace google diff --git a/toolkit/components/protobuf/src/google/protobuf/stubs/strutil.h b/toolkit/components/protobuf/src/google/protobuf/stubs/strutil.h new file mode 100644 index 0000000000..9658abf908 --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/stubs/strutil.h @@ -0,0 +1,950 @@ +// 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. + +// from google3/strings/strutil.h + +#ifndef GOOGLE_PROTOBUF_STUBS_STRUTIL_H__ +#define GOOGLE_PROTOBUF_STUBS_STRUTIL_H__ + +#include <google/protobuf/stubs/common.h> +#include <google/protobuf/stubs/stringpiece.h> +#include <stdlib.h> + +#include <cstring> +#include <google/protobuf/port_def.inc> +#include <vector> + +namespace google { +namespace protobuf { + +#if defined(_MSC_VER) && _MSC_VER < 1800 +#define strtoll _strtoi64 +#define strtoull _strtoui64 +#elif defined(__DECCXX) && defined(__osf__) +// HP C++ on Tru64 does not have strtoll, but strtol is already 64-bit. +#define strtoll strtol +#define strtoull strtoul +#endif + +// ---------------------------------------------------------------------- +// ascii_isalnum() +// Check if an ASCII character is alphanumeric. We can't use ctype's +// isalnum() because it is affected by locale. This function is applied +// to identifiers in the protocol buffer language, not to natural-language +// strings, so locale should not be taken into account. +// ascii_isdigit() +// Like above, but only accepts digits. +// ascii_isspace() +// Check if the character is a space character. +// ---------------------------------------------------------------------- + +inline bool ascii_isalnum(char c) { + return ('a' <= c && c <= 'z') || + ('A' <= c && c <= 'Z') || + ('0' <= c && c <= '9'); +} + +inline bool ascii_isdigit(char c) { + return ('0' <= c && c <= '9'); +} + +inline bool ascii_isspace(char c) { + return c == ' ' || c == '\t' || c == '\n' || c == '\v' || c == '\f' || + c == '\r'; +} + +inline bool ascii_isupper(char c) { + return c >= 'A' && c <= 'Z'; +} + +inline bool ascii_islower(char c) { + return c >= 'a' && c <= 'z'; +} + +inline char ascii_toupper(char c) { + return ascii_islower(c) ? c - ('a' - 'A') : c; +} + +inline char ascii_tolower(char c) { + return ascii_isupper(c) ? c + ('a' - 'A') : c; +} + +inline int hex_digit_to_int(char c) { + /* Assume ASCII. */ + int x = static_cast<unsigned char>(c); + if (x > '9') { + x += 9; + } + return x & 0xf; +} + +// ---------------------------------------------------------------------- +// HasPrefixString() +// Check if a string begins with a given prefix. +// StripPrefixString() +// Given a string and a putative prefix, returns the string minus the +// prefix string if the prefix matches, otherwise the original +// string. +// ---------------------------------------------------------------------- +inline bool HasPrefixString(StringPiece str, StringPiece prefix) { + return str.size() >= prefix.size() && + memcmp(str.data(), prefix.data(), prefix.size()) == 0; +} + +inline std::string StripPrefixString(const std::string& str, + const std::string& prefix) { + if (HasPrefixString(str, prefix)) { + return str.substr(prefix.size()); + } else { + return str; + } +} + +// ---------------------------------------------------------------------- +// HasSuffixString() +// Return true if str ends in suffix. +// StripSuffixString() +// Given a string and a putative suffix, returns the string minus the +// suffix string if the suffix matches, otherwise the original +// string. +// ---------------------------------------------------------------------- +inline bool HasSuffixString(StringPiece str, StringPiece suffix) { + return str.size() >= suffix.size() && + memcmp(str.data() + str.size() - suffix.size(), suffix.data(), + suffix.size()) == 0; +} + +inline std::string StripSuffixString(const std::string& str, + const std::string& suffix) { + if (HasSuffixString(str, suffix)) { + return str.substr(0, str.size() - suffix.size()); + } else { + return str; + } +} + +// ---------------------------------------------------------------------- +// ReplaceCharacters +// Replaces any occurrence of the character 'remove' (or the characters +// in 'remove') with the character 'replacewith'. +// Good for keeping html characters or protocol characters (\t) out +// of places where they might cause a problem. +// StripWhitespace +// Removes whitespaces from both ends of the given string. +// ---------------------------------------------------------------------- +PROTOBUF_EXPORT void ReplaceCharacters(std::string* s, const char* remove, + char replacewith); + +PROTOBUF_EXPORT void StripWhitespace(std::string* s); + +// ---------------------------------------------------------------------- +// LowerString() +// UpperString() +// ToUpper() +// Convert the characters in "s" to lowercase or uppercase. ASCII-only: +// these functions intentionally ignore locale because they are applied to +// identifiers used in the Protocol Buffer language, not to natural-language +// strings. +// ---------------------------------------------------------------------- + +inline void LowerString(std::string* s) { + std::string::iterator end = s->end(); + for (std::string::iterator i = s->begin(); i != end; ++i) { + // tolower() changes based on locale. We don't want this! + if ('A' <= *i && *i <= 'Z') *i += 'a' - 'A'; + } +} + +inline void UpperString(std::string* s) { + std::string::iterator end = s->end(); + for (std::string::iterator i = s->begin(); i != end; ++i) { + // toupper() changes based on locale. We don't want this! + if ('a' <= *i && *i <= 'z') *i += 'A' - 'a'; + } +} + +inline void ToUpper(std::string* s) { UpperString(s); } + +inline std::string ToUpper(const std::string& s) { + std::string out = s; + UpperString(&out); + return out; +} + +// ---------------------------------------------------------------------- +// StringReplace() +// Give me a string and two patterns "old" and "new", and I replace +// the first instance of "old" in the string with "new", if it +// exists. RETURN a new string, regardless of whether the replacement +// happened or not. +// ---------------------------------------------------------------------- + +PROTOBUF_EXPORT std::string StringReplace(const std::string& s, + const std::string& oldsub, + const std::string& newsub, + bool replace_all); + +// ---------------------------------------------------------------------- +// SplitStringUsing() +// Split a string using a character delimiter. Append the components +// to 'result'. If there are consecutive delimiters, this function skips +// over all of them. +// ---------------------------------------------------------------------- +PROTOBUF_EXPORT void SplitStringUsing(StringPiece full, const char* delim, + std::vector<std::string>* res); + +// Split a string using one or more byte delimiters, presented +// as a nul-terminated c string. Append the components to 'result'. +// If there are consecutive delimiters, this function will return +// corresponding empty strings. If you want to drop the empty +// strings, try SplitStringUsing(). +// +// If "full" is the empty string, yields an empty string as the only value. +// ---------------------------------------------------------------------- +PROTOBUF_EXPORT void SplitStringAllowEmpty(StringPiece full, const char* delim, + std::vector<std::string>* result); + +// ---------------------------------------------------------------------- +// Split() +// Split a string using a character delimiter. +// ---------------------------------------------------------------------- +inline std::vector<std::string> Split(StringPiece full, const char* delim, + bool skip_empty = true) { + std::vector<std::string> result; + if (skip_empty) { + SplitStringUsing(full, delim, &result); + } else { + SplitStringAllowEmpty(full, delim, &result); + } + return result; +} + +// ---------------------------------------------------------------------- +// JoinStrings() +// These methods concatenate a vector of strings into a C++ string, using +// the C-string "delim" as a separator between components. There are two +// flavors of the function, one flavor returns the concatenated string, +// another takes a pointer to the target string. In the latter case the +// target string is cleared and overwritten. +// ---------------------------------------------------------------------- +PROTOBUF_EXPORT void JoinStrings(const std::vector<std::string>& components, + const char* delim, std::string* result); + +inline std::string JoinStrings(const std::vector<std::string>& components, + const char* delim) { + std::string result; + JoinStrings(components, delim, &result); + return result; +} + +// ---------------------------------------------------------------------- +// UnescapeCEscapeSequences() +// Copies "source" to "dest", rewriting C-style escape sequences +// -- '\n', '\r', '\\', '\ooo', etc -- to their ASCII +// equivalents. "dest" must be sufficiently large to hold all +// the characters in the rewritten string (i.e. at least as large +// as strlen(source) + 1 should be safe, since the replacements +// are always shorter than the original escaped sequences). It's +// safe for source and dest to be the same. RETURNS the length +// of dest. +// +// It allows hex sequences \xhh, or generally \xhhhhh with an +// arbitrary number of hex digits, but all of them together must +// specify a value of a single byte (e.g. \x0045 is equivalent +// to \x45, and \x1234 is erroneous). +// +// It also allows escape sequences of the form \uhhhh (exactly four +// hex digits, upper or lower case) or \Uhhhhhhhh (exactly eight +// hex digits, upper or lower case) to specify a Unicode code +// point. The dest array will contain the UTF8-encoded version of +// that code-point (e.g., if source contains \u2019, then dest will +// contain the three bytes 0xE2, 0x80, and 0x99). +// +// Errors: In the first form of the call, errors are reported with +// LOG(ERROR). The same is true for the second form of the call if +// the pointer to the string std::vector is nullptr; otherwise, error +// messages are stored in the std::vector. In either case, the effect on +// the dest array is not defined, but rest of the source will be +// processed. +// ---------------------------------------------------------------------- + +PROTOBUF_EXPORT int UnescapeCEscapeSequences(const char* source, char* dest); +PROTOBUF_EXPORT int UnescapeCEscapeSequences(const char* source, char* dest, + std::vector<std::string>* errors); + +// ---------------------------------------------------------------------- +// UnescapeCEscapeString() +// This does the same thing as UnescapeCEscapeSequences, but creates +// a new string. The caller does not need to worry about allocating +// a dest buffer. This should be used for non performance critical +// tasks such as printing debug messages. It is safe for src and dest +// to be the same. +// +// The second call stores its errors in a supplied string vector. +// If the string vector pointer is nullptr, it reports the errors with LOG(). +// +// In the first and second calls, the length of dest is returned. In the +// the third call, the new string is returned. +// ---------------------------------------------------------------------- + +PROTOBUF_EXPORT int UnescapeCEscapeString(const std::string& src, + std::string* dest); +PROTOBUF_EXPORT int UnescapeCEscapeString(const std::string& src, + std::string* dest, + std::vector<std::string>* errors); +PROTOBUF_EXPORT std::string UnescapeCEscapeString(const std::string& src); + +// ---------------------------------------------------------------------- +// CEscape() +// Escapes 'src' using C-style escape sequences and returns the resulting +// string. +// +// Escaped chars: \n, \r, \t, ", ', \, and !isprint(). +// ---------------------------------------------------------------------- +PROTOBUF_EXPORT std::string CEscape(const std::string& src); + +// ---------------------------------------------------------------------- +// CEscapeAndAppend() +// Escapes 'src' using C-style escape sequences, and appends the escaped +// string to 'dest'. +// ---------------------------------------------------------------------- +PROTOBUF_EXPORT void CEscapeAndAppend(StringPiece src, std::string* dest); + +namespace strings { +// Like CEscape() but does not escape bytes with the upper bit set. +PROTOBUF_EXPORT std::string Utf8SafeCEscape(const std::string& src); + +// Like CEscape() but uses hex (\x) escapes instead of octals. +PROTOBUF_EXPORT std::string CHexEscape(const std::string& src); +} // namespace strings + +// ---------------------------------------------------------------------- +// strto32() +// strtou32() +// strto64() +// strtou64() +// Architecture-neutral plug compatible replacements for strtol() and +// strtoul(). Long's have different lengths on ILP-32 and LP-64 +// platforms, so using these is safer, from the point of view of +// overflow behavior, than using the standard libc functions. +// ---------------------------------------------------------------------- +PROTOBUF_EXPORT int32_t strto32_adaptor(const char* nptr, char** endptr, + int base); +PROTOBUF_EXPORT uint32_t strtou32_adaptor(const char* nptr, char** endptr, + int base); + +inline int32_t strto32(const char *nptr, char **endptr, int base) { + if (sizeof(int32_t) == sizeof(long)) + return strtol(nptr, endptr, base); + else + return strto32_adaptor(nptr, endptr, base); +} + +inline uint32_t strtou32(const char *nptr, char **endptr, int base) { + if (sizeof(uint32_t) == sizeof(unsigned long)) + return strtoul(nptr, endptr, base); + else + return strtou32_adaptor(nptr, endptr, base); +} + +// For now, long long is 64-bit on all the platforms we care about, so these +// functions can simply pass the call to strto[u]ll. +inline int64_t strto64(const char *nptr, char **endptr, int base) { + static_assert(sizeof(int64_t) == sizeof(long long), + "sizeof int64_t is not sizeof long long"); + return strtoll(nptr, endptr, base); +} + +inline uint64_t strtou64(const char *nptr, char **endptr, int base) { + static_assert(sizeof(uint64_t) == sizeof(unsigned long long), + "sizeof uint64_t is not sizeof unsigned long long"); + return strtoull(nptr, endptr, base); +} + +// ---------------------------------------------------------------------- +// safe_strtob() +// safe_strto32() +// safe_strtou32() +// safe_strto64() +// safe_strtou64() +// safe_strtof() +// safe_strtod() +// ---------------------------------------------------------------------- +PROTOBUF_EXPORT bool safe_strtob(StringPiece str, bool* value); + +PROTOBUF_EXPORT bool safe_strto32(const std::string& str, int32_t* value); +PROTOBUF_EXPORT bool safe_strtou32(const std::string& str, uint32_t* value); +inline bool safe_strto32(const char* str, int32_t* value) { + return safe_strto32(std::string(str), value); +} +inline bool safe_strto32(StringPiece str, int32_t* value) { + return safe_strto32(str.ToString(), value); +} +inline bool safe_strtou32(const char* str, uint32_t* value) { + return safe_strtou32(std::string(str), value); +} +inline bool safe_strtou32(StringPiece str, uint32_t* value) { + return safe_strtou32(str.ToString(), value); +} + +PROTOBUF_EXPORT bool safe_strto64(const std::string& str, int64_t* value); +PROTOBUF_EXPORT bool safe_strtou64(const std::string& str, uint64_t* value); +inline bool safe_strto64(const char* str, int64_t* value) { + return safe_strto64(std::string(str), value); +} +inline bool safe_strto64(StringPiece str, int64_t* value) { + return safe_strto64(str.ToString(), value); +} +inline bool safe_strtou64(const char* str, uint64_t* value) { + return safe_strtou64(std::string(str), value); +} +inline bool safe_strtou64(StringPiece str, uint64_t* value) { + return safe_strtou64(str.ToString(), value); +} + +PROTOBUF_EXPORT bool safe_strtof(const char* str, float* value); +PROTOBUF_EXPORT bool safe_strtod(const char* str, double* value); +inline bool safe_strtof(const std::string& str, float* value) { + return safe_strtof(str.c_str(), value); +} +inline bool safe_strtod(const std::string& str, double* value) { + return safe_strtod(str.c_str(), value); +} +inline bool safe_strtof(StringPiece str, float* value) { + return safe_strtof(str.ToString(), value); +} +inline bool safe_strtod(StringPiece str, double* value) { + return safe_strtod(str.ToString(), value); +} + +// ---------------------------------------------------------------------- +// FastIntToBuffer() +// FastHexToBuffer() +// FastHex64ToBuffer() +// FastHex32ToBuffer() +// FastTimeToBuffer() +// These are intended for speed. FastIntToBuffer() assumes the +// integer is non-negative. FastHexToBuffer() puts output in +// hex rather than decimal. FastTimeToBuffer() puts the output +// into RFC822 format. +// +// FastHex64ToBuffer() puts a 64-bit unsigned value in hex-format, +// padded to exactly 16 bytes (plus one byte for '\0') +// +// FastHex32ToBuffer() puts a 32-bit unsigned value in hex-format, +// padded to exactly 8 bytes (plus one byte for '\0') +// +// All functions take the output buffer as an arg. +// They all return a pointer to the beginning of the output, +// which may not be the beginning of the input buffer. +// ---------------------------------------------------------------------- + +// Suggested buffer size for FastToBuffer functions. Also works with +// DoubleToBuffer() and FloatToBuffer(). +static const int kFastToBufferSize = 32; + +PROTOBUF_EXPORT char* FastInt32ToBuffer(int32_t i, char* buffer); +PROTOBUF_EXPORT char* FastInt64ToBuffer(int64_t i, char* buffer); +char* FastUInt32ToBuffer(uint32_t i, char* buffer); // inline below +char* FastUInt64ToBuffer(uint64_t i, char* buffer); // inline below +PROTOBUF_EXPORT char* FastHexToBuffer(int i, char* buffer); +PROTOBUF_EXPORT char* FastHex64ToBuffer(uint64_t i, char* buffer); +PROTOBUF_EXPORT char* FastHex32ToBuffer(uint32_t i, char* buffer); + +// at least 22 bytes long +inline char* FastIntToBuffer(int i, char* buffer) { + return (sizeof(i) == 4 ? + FastInt32ToBuffer(i, buffer) : FastInt64ToBuffer(i, buffer)); +} +inline char* FastUIntToBuffer(unsigned int i, char* buffer) { + return (sizeof(i) == 4 ? + FastUInt32ToBuffer(i, buffer) : FastUInt64ToBuffer(i, buffer)); +} +inline char* FastLongToBuffer(long i, char* buffer) { + return (sizeof(i) == 4 ? + FastInt32ToBuffer(i, buffer) : FastInt64ToBuffer(i, buffer)); +} +inline char* FastULongToBuffer(unsigned long i, char* buffer) { + return (sizeof(i) == 4 ? + FastUInt32ToBuffer(i, buffer) : FastUInt64ToBuffer(i, buffer)); +} + +// ---------------------------------------------------------------------- +// FastInt32ToBufferLeft() +// FastUInt32ToBufferLeft() +// FastInt64ToBufferLeft() +// FastUInt64ToBufferLeft() +// +// Like the Fast*ToBuffer() functions above, these are intended for speed. +// Unlike the Fast*ToBuffer() functions, however, these functions write +// their output to the beginning of the buffer (hence the name, as the +// output is left-aligned). The caller is responsible for ensuring that +// the buffer has enough space to hold the output. +// +// Returns a pointer to the end of the string (i.e. the null character +// terminating the string). +// ---------------------------------------------------------------------- + +PROTOBUF_EXPORT char* FastInt32ToBufferLeft(int32_t i, char* buffer); +PROTOBUF_EXPORT char* FastUInt32ToBufferLeft(uint32_t i, char* buffer); +PROTOBUF_EXPORT char* FastInt64ToBufferLeft(int64_t i, char* buffer); +PROTOBUF_EXPORT char* FastUInt64ToBufferLeft(uint64_t i, char* buffer); + +// Just define these in terms of the above. +inline char* FastUInt32ToBuffer(uint32_t i, char* buffer) { + FastUInt32ToBufferLeft(i, buffer); + return buffer; +} +inline char* FastUInt64ToBuffer(uint64_t i, char* buffer) { + FastUInt64ToBufferLeft(i, buffer); + return buffer; +} + +inline std::string SimpleBtoa(bool value) { return value ? "true" : "false"; } + +// ---------------------------------------------------------------------- +// SimpleItoa() +// Description: converts an integer to a string. +// +// Return value: string +// ---------------------------------------------------------------------- +PROTOBUF_EXPORT std::string SimpleItoa(int i); +PROTOBUF_EXPORT std::string SimpleItoa(unsigned int i); +PROTOBUF_EXPORT std::string SimpleItoa(long i); +PROTOBUF_EXPORT std::string SimpleItoa(unsigned long i); +PROTOBUF_EXPORT std::string SimpleItoa(long long i); +PROTOBUF_EXPORT std::string SimpleItoa(unsigned long long i); + +// ---------------------------------------------------------------------- +// SimpleDtoa() +// SimpleFtoa() +// DoubleToBuffer() +// FloatToBuffer() +// Description: converts a double or float to a string which, if +// passed to NoLocaleStrtod(), will produce the exact same original double +// (except in case of NaN; all NaNs are considered the same value). +// We try to keep the string short but it's not guaranteed to be as +// short as possible. +// +// DoubleToBuffer() and FloatToBuffer() write the text to the given +// buffer and return it. The buffer must be at least +// kDoubleToBufferSize bytes for doubles and kFloatToBufferSize +// bytes for floats. kFastToBufferSize is also guaranteed to be large +// enough to hold either. +// +// Return value: string +// ---------------------------------------------------------------------- +PROTOBUF_EXPORT std::string SimpleDtoa(double value); +PROTOBUF_EXPORT std::string SimpleFtoa(float value); + +PROTOBUF_EXPORT char* DoubleToBuffer(double i, char* buffer); +PROTOBUF_EXPORT char* FloatToBuffer(float i, char* buffer); + +// In practice, doubles should never need more than 24 bytes and floats +// should never need more than 14 (including null terminators), but we +// overestimate to be safe. +static const int kDoubleToBufferSize = 32; +static const int kFloatToBufferSize = 24; + +namespace strings { + +enum PadSpec { + NO_PAD = 1, + ZERO_PAD_2, + ZERO_PAD_3, + ZERO_PAD_4, + ZERO_PAD_5, + ZERO_PAD_6, + ZERO_PAD_7, + ZERO_PAD_8, + ZERO_PAD_9, + ZERO_PAD_10, + ZERO_PAD_11, + ZERO_PAD_12, + ZERO_PAD_13, + ZERO_PAD_14, + ZERO_PAD_15, + ZERO_PAD_16, +}; + +struct Hex { + uint64_t value; + enum PadSpec spec; + template <class Int> + explicit Hex(Int v, PadSpec s = NO_PAD) + : spec(s) { + // Prevent sign-extension by casting integers to + // their unsigned counterparts. +#ifdef LANG_CXX11 + static_assert( + sizeof(v) == 1 || sizeof(v) == 2 || sizeof(v) == 4 || sizeof(v) == 8, + "Unknown integer type"); +#endif + value = sizeof(v) == 1 ? static_cast<uint8_t>(v) + : sizeof(v) == 2 ? static_cast<uint16_t>(v) + : sizeof(v) == 4 ? static_cast<uint32_t>(v) + : static_cast<uint64_t>(v); + } +}; + +struct PROTOBUF_EXPORT AlphaNum { + const char *piece_data_; // move these to string_ref eventually + size_t piece_size_; // move these to string_ref eventually + + char digits[kFastToBufferSize]; + + // No bool ctor -- bools convert to an integral type. + // A bool ctor would also convert incoming pointers (bletch). + + AlphaNum(int i32) + : piece_data_(digits), + piece_size_(FastInt32ToBufferLeft(i32, digits) - &digits[0]) {} + AlphaNum(unsigned int u32) + : piece_data_(digits), + piece_size_(FastUInt32ToBufferLeft(u32, digits) - &digits[0]) {} + AlphaNum(long long i64) + : piece_data_(digits), + piece_size_(FastInt64ToBufferLeft(i64, digits) - &digits[0]) {} + AlphaNum(unsigned long long u64) + : piece_data_(digits), + piece_size_(FastUInt64ToBufferLeft(u64, digits) - &digits[0]) {} + + // Note: on some architectures, "long" is only 32 bits, not 64, but the + // performance hit of using FastInt64ToBufferLeft to handle 32-bit values + // is quite minor. + AlphaNum(long i64) + : piece_data_(digits), + piece_size_(FastInt64ToBufferLeft(i64, digits) - &digits[0]) {} + AlphaNum(unsigned long u64) + : piece_data_(digits), + piece_size_(FastUInt64ToBufferLeft(u64, digits) - &digits[0]) {} + + AlphaNum(float f) + : piece_data_(digits), piece_size_(strlen(FloatToBuffer(f, digits))) {} + AlphaNum(double f) + : piece_data_(digits), piece_size_(strlen(DoubleToBuffer(f, digits))) {} + + AlphaNum(Hex hex); + + AlphaNum(const char* c_str) + : piece_data_(c_str), piece_size_(strlen(c_str)) {} + // TODO: Add a string_ref constructor, eventually + // AlphaNum(const StringPiece &pc) : piece(pc) {} + + AlphaNum(const std::string& str) + : piece_data_(str.data()), piece_size_(str.size()) {} + + AlphaNum(StringPiece str) + : piece_data_(str.data()), piece_size_(str.size()) {} + + size_t size() const { return piece_size_; } + const char *data() const { return piece_data_; } + + private: + // Use ":" not ':' + AlphaNum(char c); // NOLINT(runtime/explicit) + + // Disallow copy and assign. + AlphaNum(const AlphaNum&); + void operator=(const AlphaNum&); +}; + +} // namespace strings + +using strings::AlphaNum; + +// ---------------------------------------------------------------------- +// StrCat() +// This merges the given strings or numbers, with no delimiter. This +// is designed to be the fastest possible way to construct a string out +// of a mix of raw C strings, strings, bool values, +// and numeric values. +// +// Don't use this for user-visible strings. The localization process +// works poorly on strings built up out of fragments. +// +// For clarity and performance, don't use StrCat when appending to a +// string. In particular, avoid using any of these (anti-)patterns: +// str.append(StrCat(...) +// str += StrCat(...) +// str = StrCat(str, ...) +// where the last is the worse, with the potential to change a loop +// from a linear time operation with O(1) dynamic allocations into a +// quadratic time operation with O(n) dynamic allocations. StrAppend +// is a better choice than any of the above, subject to the restriction +// of StrAppend(&str, a, b, c, ...) that none of the a, b, c, ... may +// be a reference into str. +// ---------------------------------------------------------------------- + +PROTOBUF_EXPORT std::string StrCat(const AlphaNum& a, const AlphaNum& b); +PROTOBUF_EXPORT std::string StrCat(const AlphaNum& a, const AlphaNum& b, + const AlphaNum& c); +PROTOBUF_EXPORT std::string StrCat(const AlphaNum& a, const AlphaNum& b, + const AlphaNum& c, const AlphaNum& d); +PROTOBUF_EXPORT std::string StrCat(const AlphaNum& a, const AlphaNum& b, + const AlphaNum& c, const AlphaNum& d, + const AlphaNum& e); +PROTOBUF_EXPORT std::string StrCat(const AlphaNum& a, const AlphaNum& b, + const AlphaNum& c, const AlphaNum& d, + const AlphaNum& e, const AlphaNum& f); +PROTOBUF_EXPORT std::string StrCat(const AlphaNum& a, const AlphaNum& b, + const AlphaNum& c, const AlphaNum& d, + const AlphaNum& e, const AlphaNum& f, + const AlphaNum& g); +PROTOBUF_EXPORT std::string StrCat(const AlphaNum& a, const AlphaNum& b, + const AlphaNum& c, const AlphaNum& d, + const AlphaNum& e, const AlphaNum& f, + const AlphaNum& g, const AlphaNum& h); +PROTOBUF_EXPORT std::string StrCat(const AlphaNum& a, const AlphaNum& b, + const AlphaNum& c, const AlphaNum& d, + const AlphaNum& e, const AlphaNum& f, + const AlphaNum& g, const AlphaNum& h, + const AlphaNum& i); + +inline std::string StrCat(const AlphaNum& a) { + return std::string(a.data(), a.size()); +} + +// ---------------------------------------------------------------------- +// StrAppend() +// Same as above, but adds the output to the given string. +// WARNING: For speed, StrAppend does not try to check each of its input +// arguments to be sure that they are not a subset of the string being +// appended to. That is, while this will work: +// +// string s = "foo"; +// s += s; +// +// This will not (necessarily) work: +// +// string s = "foo"; +// StrAppend(&s, s); +// +// Note: while StrCat supports appending up to 9 arguments, StrAppend +// is currently limited to 4. That's rarely an issue except when +// automatically transforming StrCat to StrAppend, and can easily be +// worked around as consecutive calls to StrAppend are quite efficient. +// ---------------------------------------------------------------------- + +PROTOBUF_EXPORT void StrAppend(std::string* dest, const AlphaNum& a); +PROTOBUF_EXPORT void StrAppend(std::string* dest, const AlphaNum& a, + const AlphaNum& b); +PROTOBUF_EXPORT void StrAppend(std::string* dest, const AlphaNum& a, + const AlphaNum& b, const AlphaNum& c); +PROTOBUF_EXPORT void StrAppend(std::string* dest, const AlphaNum& a, + const AlphaNum& b, const AlphaNum& c, + const AlphaNum& d); + +// ---------------------------------------------------------------------- +// Join() +// These methods concatenate a range of components into a C++ string, using +// the C-string "delim" as a separator between components. +// ---------------------------------------------------------------------- +template <typename Iterator> +void Join(Iterator start, Iterator end, const char* delim, + std::string* result) { + for (Iterator it = start; it != end; ++it) { + if (it != start) { + result->append(delim); + } + StrAppend(result, *it); + } +} + +template <typename Range> +std::string Join(const Range& components, const char* delim) { + std::string result; + Join(components.begin(), components.end(), delim, &result); + return result; +} + +// ---------------------------------------------------------------------- +// ToHex() +// Return a lower-case hex string representation of the given integer. +// ---------------------------------------------------------------------- +PROTOBUF_EXPORT std::string ToHex(uint64_t num); + +// ---------------------------------------------------------------------- +// GlobalReplaceSubstring() +// Replaces all instances of a substring in a string. Does nothing +// if 'substring' is empty. Returns the number of replacements. +// +// NOTE: The string pieces must not overlap s. +// ---------------------------------------------------------------------- +PROTOBUF_EXPORT int GlobalReplaceSubstring(const std::string& substring, + const std::string& replacement, + std::string* s); + +// ---------------------------------------------------------------------- +// Base64Unescape() +// Converts "src" which is encoded in Base64 to its binary equivalent and +// writes it to "dest". If src contains invalid characters, dest is cleared +// and the function returns false. Returns true on success. +// ---------------------------------------------------------------------- +PROTOBUF_EXPORT bool Base64Unescape(StringPiece src, std::string* dest); + +// ---------------------------------------------------------------------- +// WebSafeBase64Unescape() +// This is a variation of Base64Unescape which uses '-' instead of '+', and +// '_' instead of '/'. src is not null terminated, instead specify len. I +// recommend that slen<szdest, but we honor szdest anyway. +// RETURNS the length of dest, or -1 if src contains invalid chars. + +// The variation that stores into a string clears the string first, and +// returns false (with dest empty) if src contains invalid chars; for +// this version src and dest must be different strings. +// ---------------------------------------------------------------------- +PROTOBUF_EXPORT int WebSafeBase64Unescape(const char* src, int slen, char* dest, + int szdest); +PROTOBUF_EXPORT bool WebSafeBase64Unescape(StringPiece src, std::string* dest); + +// Return the length to use for the output buffer given to the base64 escape +// routines. Make sure to use the same value for do_padding in both. +// This function may return incorrect results if given input_len values that +// are extremely high, which should happen rarely. +PROTOBUF_EXPORT int CalculateBase64EscapedLen(int input_len, bool do_padding); +// Use this version when calling Base64Escape without a do_padding arg. +PROTOBUF_EXPORT int CalculateBase64EscapedLen(int input_len); + +// ---------------------------------------------------------------------- +// Base64Escape() +// WebSafeBase64Escape() +// Encode "src" to "dest" using base64 encoding. +// src is not null terminated, instead specify len. +// 'dest' should have at least CalculateBase64EscapedLen() length. +// RETURNS the length of dest. +// The WebSafe variation use '-' instead of '+' and '_' instead of '/' +// so that we can place the out in the URL or cookies without having +// to escape them. It also has an extra parameter "do_padding", +// which when set to false will prevent padding with "=". +// ---------------------------------------------------------------------- +PROTOBUF_EXPORT int Base64Escape(const unsigned char* src, int slen, char* dest, + int szdest); +PROTOBUF_EXPORT int WebSafeBase64Escape(const unsigned char* src, int slen, + char* dest, int szdest, + bool do_padding); +// Encode src into dest with padding. +PROTOBUF_EXPORT void Base64Escape(StringPiece src, std::string* dest); +// Encode src into dest web-safely without padding. +PROTOBUF_EXPORT void WebSafeBase64Escape(StringPiece src, std::string* dest); +// Encode src into dest web-safely with padding. +PROTOBUF_EXPORT void WebSafeBase64EscapeWithPadding(StringPiece src, + std::string* dest); + +PROTOBUF_EXPORT void Base64Escape(const unsigned char* src, int szsrc, + std::string* dest, bool do_padding); +PROTOBUF_EXPORT void WebSafeBase64Escape(const unsigned char* src, int szsrc, + std::string* dest, bool do_padding); + +inline bool IsValidCodePoint(uint32_t code_point) { + return code_point < 0xD800 || + (code_point >= 0xE000 && code_point <= 0x10FFFF); +} + +static const int UTFmax = 4; +// ---------------------------------------------------------------------- +// EncodeAsUTF8Char() +// Helper to append a Unicode code point to a string as UTF8, without bringing +// in any external dependencies. The output buffer must be as least 4 bytes +// large. +// ---------------------------------------------------------------------- +PROTOBUF_EXPORT int EncodeAsUTF8Char(uint32_t code_point, char* output); + +// ---------------------------------------------------------------------- +// UTF8FirstLetterNumBytes() +// Length of the first UTF-8 character. +// ---------------------------------------------------------------------- +PROTOBUF_EXPORT int UTF8FirstLetterNumBytes(const char* src, int len); + +// From google3/third_party/absl/strings/escaping.h + +// ---------------------------------------------------------------------- +// CleanStringLineEndings() +// Clean up a multi-line string to conform to Unix line endings. +// Reads from src and appends to dst, so usually dst should be empty. +// +// If there is no line ending at the end of a non-empty string, it can +// be added automatically. +// +// Four different types of input are correctly handled: +// +// - Unix/Linux files: line ending is LF: pass through unchanged +// +// - DOS/Windows files: line ending is CRLF: convert to LF +// +// - Legacy Mac files: line ending is CR: convert to LF +// +// - Garbled files: random line endings: convert gracefully +// lonely CR, lonely LF, CRLF: convert to LF +// +// @param src The multi-line string to convert +// @param dst The converted string is appended to this string +// @param auto_end_last_line Automatically terminate the last line +// +// Limitations: +// +// This does not do the right thing for CRCRLF files created by +// broken programs that do another Unix->DOS conversion on files +// that are already in CRLF format. For this, a two-pass approach +// brute-force would be needed that +// +// (1) determines the presence of LF (first one is ok) +// (2) if yes, removes any CR, else convert every CR to LF +PROTOBUF_EXPORT void CleanStringLineEndings(const std::string& src, + std::string* dst, + bool auto_end_last_line); + +// Same as above, but transforms the argument in place. +PROTOBUF_EXPORT void CleanStringLineEndings(std::string* str, + bool auto_end_last_line); + +namespace strings { +inline bool EndsWith(StringPiece text, StringPiece suffix) { + return suffix.empty() || + (text.size() >= suffix.size() && + memcmp(text.data() + (text.size() - suffix.size()), suffix.data(), + suffix.size()) == 0); +} +} // namespace strings + +namespace internal { + +// A locale-independent version of the standard strtod(), which always +// uses a dot as the decimal separator. +double NoLocaleStrtod(const char* str, char** endptr); + +} // namespace internal + +} // namespace protobuf +} // namespace google + +#include <google/protobuf/port_undef.inc> + +#endif // GOOGLE_PROTOBUF_STUBS_STRUTIL_H__ diff --git a/toolkit/components/protobuf/src/google/protobuf/stubs/substitute.cc b/toolkit/components/protobuf/src/google/protobuf/stubs/substitute.cc new file mode 100644 index 0000000000..d301682ee3 --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/stubs/substitute.cc @@ -0,0 +1,136 @@ +// 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. + +// Author: kenton@google.com (Kenton Varda) + +#include <google/protobuf/stubs/substitute.h> + +#include <google/protobuf/stubs/logging.h> +#include <google/protobuf/stubs/strutil.h> +#include <google/protobuf/stubs/stl_util.h> + +namespace google { +namespace protobuf { +namespace strings { + +using internal::SubstituteArg; + +// Returns the number of args in arg_array which were passed explicitly +// to Substitute(). +static int CountSubstituteArgs(const SubstituteArg* const* args_array) { + int count = 0; + while (args_array[count] != nullptr && args_array[count]->size() != -1) { + ++count; + } + return count; +} + +std::string Substitute(const std::string& format, const SubstituteArg& arg0, + const SubstituteArg& arg1, const SubstituteArg& arg2, + const SubstituteArg& arg3, const SubstituteArg& arg4, + const SubstituteArg& arg5, const SubstituteArg& arg6, + const SubstituteArg& arg7, const SubstituteArg& arg8, + const SubstituteArg& arg9) { + std::string result; + SubstituteAndAppend(&result, format.c_str(), arg0, arg1, arg2, arg3, arg4, + arg5, arg6, arg7, arg8, arg9); + return result; +} + +void SubstituteAndAppend(std::string* output, const char* format, + const SubstituteArg& arg0, const SubstituteArg& arg1, + const SubstituteArg& arg2, const SubstituteArg& arg3, + const SubstituteArg& arg4, const SubstituteArg& arg5, + const SubstituteArg& arg6, const SubstituteArg& arg7, + const SubstituteArg& arg8, const SubstituteArg& arg9) { + const SubstituteArg* const args_array[] = { + &arg0, &arg1, &arg2, &arg3, &arg4, &arg5, &arg6, &arg7, &arg8, &arg9, nullptr + }; + + // Determine total size needed. + int size = 0; + for (int i = 0; format[i] != '\0'; i++) { + if (format[i] == '$') { + if (ascii_isdigit(format[i+1])) { + int index = format[i+1] - '0'; + if (args_array[index]->size() == -1) { + GOOGLE_LOG(DFATAL) + << "strings::Substitute format string invalid: asked for \"$" + << index << "\", but only " << CountSubstituteArgs(args_array) + << " args were given. Full format string was: \"" + << CEscape(format) << "\"."; + return; + } + size += args_array[index]->size(); + ++i; // Skip next char. + } else if (format[i+1] == '$') { + ++size; + ++i; // Skip next char. + } else { + GOOGLE_LOG(DFATAL) + << "Invalid strings::Substitute() format string: \"" + << CEscape(format) << "\"."; + return; + } + } else { + ++size; + } + } + + if (size == 0) return; + + // Build the string. + int original_size = output->size(); + STLStringResizeUninitialized(output, original_size + size); + char* target = string_as_array(output) + original_size; + for (int i = 0; format[i] != '\0'; i++) { + if (format[i] == '$') { + if (ascii_isdigit(format[i+1])) { + unsigned int index = format[i+1] - '0'; + assert(index < 10); + const SubstituteArg* src = args_array[index]; + memcpy(target, src->data(), src->size()); + target += src->size(); + ++i; // Skip next char. + } else if (format[i+1] == '$') { + *target++ = '$'; + ++i; // Skip next char. + } + } else { + *target++ = format[i]; + } + } + + GOOGLE_DCHECK_EQ(target - output->data(), output->size()); +} + +} // namespace strings +} // namespace protobuf +} // namespace google diff --git a/toolkit/components/protobuf/src/google/protobuf/stubs/substitute.h b/toolkit/components/protobuf/src/google/protobuf/stubs/substitute.h new file mode 100644 index 0000000000..0f851de096 --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/stubs/substitute.h @@ -0,0 +1,178 @@ +// 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. + +// Author: kenton@google.com (Kenton Varda) +// from google3/strings/substitute.h + +#include <google/protobuf/stubs/common.h> +#include <google/protobuf/stubs/stringpiece.h> +#include <google/protobuf/stubs/strutil.h> + +#include <string> + +#ifndef GOOGLE_PROTOBUF_STUBS_SUBSTITUTE_H_ +#define GOOGLE_PROTOBUF_STUBS_SUBSTITUTE_H_ + +#include <google/protobuf/port_def.inc> + +namespace google { +namespace protobuf { +namespace strings { + +// ---------------------------------------------------------------------- +// strings::Substitute() +// strings::SubstituteAndAppend() +// Kind of like StringPrintf, but different. +// +// Example: +// string GetMessage(string first_name, string last_name, int age) { +// return strings::Substitute("My name is $0 $1 and I am $2 years old.", +// first_name, last_name, age); +// } +// +// Differences from StringPrintf: +// * The format string does not identify the types of arguments. +// Instead, the magic of C++ deals with this for us. See below +// for a list of accepted types. +// * Substitutions in the format string are identified by a '$' +// followed by a digit. So, you can use arguments out-of-order and +// use the same argument multiple times. +// * It's much faster than StringPrintf. +// +// Supported types: +// * Strings (const char*, const string&) +// * Note that this means you do not have to add .c_str() to all of +// your strings. In fact, you shouldn't; it will be slower. +// * int32, int64, uint32, uint64: Formatted using SimpleItoa(). +// * float, double: Formatted using SimpleFtoa() and SimpleDtoa(). +// * bool: Printed as "true" or "false". +// +// SubstituteAndAppend() is like Substitute() but appends the result to +// *output. Example: +// +// string str; +// strings::SubstituteAndAppend(&str, +// "My name is $0 $1 and I am $2 years old.", +// first_name, last_name, age); +// +// Substitute() is significantly faster than StringPrintf(). For very +// large strings, it may be orders of magnitude faster. +// ---------------------------------------------------------------------- + +namespace internal { // Implementation details. + +class SubstituteArg { + public: + inline SubstituteArg(const char* value) + : text_(value), size_(strlen(text_)) {} + inline SubstituteArg(const std::string& value) + : text_(value.data()), size_(value.size()) {} + inline SubstituteArg(const StringPiece value) + : text_(value.data()), size_(value.size()) {} + + // Indicates that no argument was given. + inline explicit SubstituteArg() + : text_(nullptr), size_(-1) {} + + // Primitives + // We don't overload for signed and unsigned char because if people are + // explicitly declaring their chars as signed or unsigned then they are + // probably actually using them as 8-bit integers and would probably + // prefer an integer representation. But, we don't really know. So, we + // make the caller decide what to do. + inline SubstituteArg(char value) + : text_(scratch_), size_(1) { scratch_[0] = value; } + inline SubstituteArg(short value) + : text_(FastInt32ToBuffer(value, scratch_)), size_(strlen(text_)) {} + inline SubstituteArg(unsigned short value) + : text_(FastUInt32ToBuffer(value, scratch_)), size_(strlen(text_)) {} + inline SubstituteArg(int value) + : text_(FastInt32ToBuffer(value, scratch_)), size_(strlen(text_)) {} + inline SubstituteArg(unsigned int value) + : text_(FastUInt32ToBuffer(value, scratch_)), size_(strlen(text_)) {} + inline SubstituteArg(long value) + : text_(FastLongToBuffer(value, scratch_)), size_(strlen(text_)) {} + inline SubstituteArg(unsigned long value) + : text_(FastULongToBuffer(value, scratch_)), size_(strlen(text_)) {} + inline SubstituteArg(long long value) + : text_(FastInt64ToBuffer(value, scratch_)), size_(strlen(text_)) {} + inline SubstituteArg(unsigned long long value) + : text_(FastUInt64ToBuffer(value, scratch_)), size_(strlen(text_)) {} + inline SubstituteArg(float value) + : text_(FloatToBuffer(value, scratch_)), size_(strlen(text_)) {} + inline SubstituteArg(double value) + : text_(DoubleToBuffer(value, scratch_)), size_(strlen(text_)) {} + inline SubstituteArg(bool value) + : text_(value ? "true" : "false"), size_(strlen(text_)) {} + + inline const char* data() const { return text_; } + inline int size() const { return size_; } + + private: + const char* text_; + int size_; + char scratch_[kFastToBufferSize]; +}; + +} // namespace internal + +PROTOBUF_EXPORT std::string Substitute( + const std::string& format, + const internal::SubstituteArg& arg0 = internal::SubstituteArg(), + const internal::SubstituteArg& arg1 = internal::SubstituteArg(), + const internal::SubstituteArg& arg2 = internal::SubstituteArg(), + const internal::SubstituteArg& arg3 = internal::SubstituteArg(), + const internal::SubstituteArg& arg4 = internal::SubstituteArg(), + const internal::SubstituteArg& arg5 = internal::SubstituteArg(), + const internal::SubstituteArg& arg6 = internal::SubstituteArg(), + const internal::SubstituteArg& arg7 = internal::SubstituteArg(), + const internal::SubstituteArg& arg8 = internal::SubstituteArg(), + const internal::SubstituteArg& arg9 = internal::SubstituteArg()); + +PROTOBUF_EXPORT void SubstituteAndAppend( + std::string* output, const char* format, + const internal::SubstituteArg& arg0 = internal::SubstituteArg(), + const internal::SubstituteArg& arg1 = internal::SubstituteArg(), + const internal::SubstituteArg& arg2 = internal::SubstituteArg(), + const internal::SubstituteArg& arg3 = internal::SubstituteArg(), + const internal::SubstituteArg& arg4 = internal::SubstituteArg(), + const internal::SubstituteArg& arg5 = internal::SubstituteArg(), + const internal::SubstituteArg& arg6 = internal::SubstituteArg(), + const internal::SubstituteArg& arg7 = internal::SubstituteArg(), + const internal::SubstituteArg& arg8 = internal::SubstituteArg(), + const internal::SubstituteArg& arg9 = internal::SubstituteArg()); + +} // namespace strings +} // namespace protobuf +} // namespace google + +#include <google/protobuf/port_undef.inc> + +#endif // GOOGLE_PROTOBUF_STUBS_SUBSTITUTE_H_ diff --git a/toolkit/components/protobuf/src/google/protobuf/stubs/template_util.h b/toolkit/components/protobuf/src/google/protobuf/stubs/template_util.h new file mode 100644 index 0000000000..feef904bea --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/stubs/template_util.h @@ -0,0 +1,138 @@ +// Copyright 2005 Google Inc. +// All rights reserved. +// +// 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. + +// ---- +// Author: lar@google.com (Laramie Leavitt) +// +// Template metaprogramming utility functions. +// +// This code is compiled directly on many platforms, including client +// platforms like Windows, Mac, and embedded systems. Before making +// any changes here, make sure that you're not breaking any platforms. +// +// +// The names chosen here reflect those used in tr1 and the boost::mpl +// library, there are similar operations used in the Loki library as +// well. I prefer the boost names for 2 reasons: +// 1. I think that portions of the Boost libraries are more likely to +// be included in the c++ standard. +// 2. It is not impossible that some of the boost libraries will be +// included in our own build in the future. +// Both of these outcomes means that we may be able to directly replace +// some of these with boost equivalents. +// +#ifndef GOOGLE_PROTOBUF_TEMPLATE_UTIL_H_ +#define GOOGLE_PROTOBUF_TEMPLATE_UTIL_H_ + +namespace google { +namespace protobuf { +namespace internal { + +// Types small_ and big_ are guaranteed such that sizeof(small_) < +// sizeof(big_) +typedef char small_; + +struct big_ { + char dummy[2]; +}; + +// Identity metafunction. +template <class T> +struct identity_ { + typedef T type; +}; + +// integral_constant, defined in tr1, is a wrapper for an integer +// value. We don't really need this generality; we could get away +// with hardcoding the integer type to bool. We use the fully +// general integer_constant for compatibility with tr1. + +template<class T, T v> +struct integral_constant { + static const T value = v; + typedef T value_type; + typedef integral_constant<T, v> type; +}; + +template <class T, T v> const T integral_constant<T, v>::value; + + +// Abbreviations: true_type and false_type are structs that represent boolean +// true and false values. Also define the boost::mpl versions of those names, +// true_ and false_. +typedef integral_constant<bool, true> true_type; +typedef integral_constant<bool, false> false_type; +typedef true_type true_; +typedef false_type false_; + +// if_ is a templatized conditional statement. +// if_<cond, A, B> is a compile time evaluation of cond. +// if_<>::type contains A if cond is true, B otherwise. +template<bool cond, typename A, typename B> +struct if_{ + typedef A type; +}; + +template<typename A, typename B> +struct if_<false, A, B> { + typedef B type; +}; + + +// type_equals_ is a template type comparator, similar to Loki IsSameType. +// type_equals_<A, B>::value is true iff "A" is the same type as "B". +// +// New code should prefer base::is_same, defined in base/type_traits.h. +// It is functionally identical, but is_same is the standard spelling. +template<typename A, typename B> +struct type_equals_ : public false_ { +}; + +template<typename A> +struct type_equals_<A, A> : public true_ { +}; + +// and_ is a template && operator. +// and_<A, B>::value evaluates "A::value && B::value". +template<typename A, typename B> +struct and_ : public integral_constant<bool, (A::value && B::value)> { +}; + +// or_ is a template || operator. +// or_<A, B>::value evaluates "A::value || B::value". +template<typename A, typename B> +struct or_ : public integral_constant<bool, (A::value || B::value)> { +}; + + +} // namespace internal +} // namespace protobuf +} // namespace google + +#endif // GOOGLE_PROTOBUF_TEMPLATE_UTIL_H_ diff --git a/toolkit/components/protobuf/src/google/protobuf/stubs/time.cc b/toolkit/components/protobuf/src/google/protobuf/stubs/time.cc new file mode 100644 index 0000000000..692cb82287 --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/stubs/time.cc @@ -0,0 +1,365 @@ +#include <google/protobuf/stubs/time.h> + +#include <ctime> + +#include <google/protobuf/stubs/stringprintf.h> +#include <google/protobuf/stubs/strutil.h> + +namespace google { +namespace protobuf { +namespace internal { + +namespace { +static const int64_t kSecondsPerMinute = 60; +static const int64_t kSecondsPerHour = 3600; +static const int64_t kSecondsPerDay = kSecondsPerHour * 24; +static const int64_t kSecondsPer400Years = + kSecondsPerDay * (400 * 365 + 400 / 4 - 3); +// Seconds from 0001-01-01T00:00:00 to 1970-01-01T:00:00:00 +static const int64_t kSecondsFromEraToEpoch = 62135596800LL; +// The range of timestamp values we support. +static const int64_t kMinTime = -62135596800LL; // 0001-01-01T00:00:00 +static const int64_t kMaxTime = 253402300799LL; // 9999-12-31T23:59:59 + +static const int kNanosPerMillisecond = 1000000; +static const int kNanosPerMicrosecond = 1000; + +// Count the seconds from the given year (start at Jan 1, 00:00) to 100 years +// after. +int64_t SecondsPer100Years(int year) { + if (year % 400 == 0 || year % 400 > 300) { + return kSecondsPerDay * (100 * 365 + 100 / 4); + } else { + return kSecondsPerDay * (100 * 365 + 100 / 4 - 1); + } +} + +// Count the seconds from the given year (start at Jan 1, 00:00) to 4 years +// after. +int64_t SecondsPer4Years(int year) { + if ((year % 100 == 0 || year % 100 > 96) && + !(year % 400 == 0 || year % 400 > 396)) { + // No leap years. + return kSecondsPerDay * (4 * 365); + } else { + // One leap years. + return kSecondsPerDay * (4 * 365 + 1); + } +} + +bool IsLeapYear(int year) { + return year % 400 == 0 || (year % 4 == 0 && year % 100 != 0); +} + +int64_t SecondsPerYear(int year) { + return kSecondsPerDay * (IsLeapYear(year) ? 366 : 365); +} + +static const int kDaysInMonth[13] = { + 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 +}; + +int64_t SecondsPerMonth(int month, bool leap) { + if (month == 2 && leap) { + return kSecondsPerDay * (kDaysInMonth[month] + 1); + } + return kSecondsPerDay * kDaysInMonth[month]; +} + +static const int kDaysSinceJan[13] = { + 0, 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, +}; + +bool ValidateDateTime(const DateTime& time) { + if (time.year < 1 || time.year > 9999 || + time.month < 1 || time.month > 12 || + time.day < 1 || time.day > 31 || + time.hour < 0 || time.hour > 23 || + time.minute < 0 || time.minute > 59 || + time.second < 0 || time.second > 59) { + return false; + } + if (time.month == 2 && IsLeapYear(time.year)) { + return time.day <= kDaysInMonth[time.month] + 1; + } else { + return time.day <= kDaysInMonth[time.month]; + } +} + +// Count the number of seconds elapsed from 0001-01-01T00:00:00 to the given +// time. +int64_t SecondsSinceCommonEra(const DateTime& time) { + int64_t result = 0; + // Years should be between 1 and 9999. + assert(time.year >= 1 && time.year <= 9999); + int year = 1; + if ((time.year - year) >= 400) { + int count_400years = (time.year - year) / 400; + result += kSecondsPer400Years * count_400years; + year += count_400years * 400; + } + while ((time.year - year) >= 100) { + result += SecondsPer100Years(year); + year += 100; + } + while ((time.year - year) >= 4) { + result += SecondsPer4Years(year); + year += 4; + } + while (time.year > year) { + result += SecondsPerYear(year); + ++year; + } + // Months should be between 1 and 12. + assert(time.month >= 1 && time.month <= 12); + int month = time.month; + result += kSecondsPerDay * kDaysSinceJan[month]; + if (month > 2 && IsLeapYear(year)) { + result += kSecondsPerDay; + } + assert(time.day >= 1 && + time.day <= (month == 2 && IsLeapYear(year) + ? kDaysInMonth[month] + 1 + : kDaysInMonth[month])); + result += kSecondsPerDay * (time.day - 1); + result += kSecondsPerHour * time.hour + + kSecondsPerMinute * time.minute + + time.second; + return result; +} + +// Format nanoseconds with either 3, 6, or 9 digits depending on the required +// precision to represent the exact value. +std::string FormatNanos(int32_t nanos) { + if (nanos % kNanosPerMillisecond == 0) { + return StringPrintf("%03d", nanos / kNanosPerMillisecond); + } else if (nanos % kNanosPerMicrosecond == 0) { + return StringPrintf("%06d", nanos / kNanosPerMicrosecond); + } else { + return StringPrintf("%09d", nanos); + } +} + +// Parses an integer from a null-terminated char sequence. The method +// consumes at most "width" chars. Returns a pointer after the consumed +// integer, or nullptr if the data does not start with an integer or the +// integer value does not fall in the range of [min_value, max_value]. +const char* ParseInt(const char* data, int width, int min_value, + int max_value, int* result) { + if (!ascii_isdigit(*data)) { + return nullptr; + } + int value = 0; + for (int i = 0; i < width; ++i, ++data) { + if (ascii_isdigit(*data)) { + value = value * 10 + (*data - '0'); + } else { + break; + } + } + if (value >= min_value && value <= max_value) { + *result = value; + return data; + } else { + return nullptr; + } +} + +// Consumes the fractional parts of a second into nanos. For example, +// "010" will be parsed to 10000000 nanos. +const char* ParseNanos(const char* data, int32_t* nanos) { + if (!ascii_isdigit(*data)) { + return nullptr; + } + int value = 0; + int len = 0; + // Consume as many digits as there are but only take the first 9 into + // account. + while (ascii_isdigit(*data)) { + if (len < 9) { + value = value * 10 + *data - '0'; + } + ++len; + ++data; + } + while (len < 9) { + value = value * 10; + ++len; + } + *nanos = value; + return data; +} + +const char* ParseTimezoneOffset(const char* data, int64_t* offset) { + // Accept format "HH:MM". E.g., "08:00" + int hour; + if ((data = ParseInt(data, 2, 0, 23, &hour)) == nullptr) { + return nullptr; + } + if (*data++ != ':') { + return nullptr; + } + int minute; + if ((data = ParseInt(data, 2, 0, 59, &minute)) == nullptr) { + return nullptr; + } + *offset = (hour * 60 + minute) * 60; + return data; +} +} // namespace + +bool SecondsToDateTime(int64_t seconds, DateTime* time) { + if (seconds < kMinTime || seconds > kMaxTime) { + return false; + } + // It's easier to calculate the DateTime starting from 0001-01-01T00:00:00 + seconds = seconds + kSecondsFromEraToEpoch; + int year = 1; + if (seconds >= kSecondsPer400Years) { + int count_400years = seconds / kSecondsPer400Years; + year += 400 * count_400years; + seconds %= kSecondsPer400Years; + } + while (seconds >= SecondsPer100Years(year)) { + seconds -= SecondsPer100Years(year); + year += 100; + } + while (seconds >= SecondsPer4Years(year)) { + seconds -= SecondsPer4Years(year); + year += 4; + } + while (seconds >= SecondsPerYear(year)) { + seconds -= SecondsPerYear(year); + year += 1; + } + bool leap = IsLeapYear(year); + int month = 1; + while (seconds >= SecondsPerMonth(month, leap)) { + seconds -= SecondsPerMonth(month, leap); + ++month; + } + int day = 1 + seconds / kSecondsPerDay; + seconds %= kSecondsPerDay; + int hour = seconds / kSecondsPerHour; + seconds %= kSecondsPerHour; + int minute = seconds / kSecondsPerMinute; + seconds %= kSecondsPerMinute; + time->year = year; + time->month = month; + time->day = day; + time->hour = hour; + time->minute = minute; + time->second = static_cast<int>(seconds); + return true; +} + +bool DateTimeToSeconds(const DateTime& time, int64_t* seconds) { + if (!ValidateDateTime(time)) { + return false; + } + *seconds = SecondsSinceCommonEra(time) - kSecondsFromEraToEpoch; + return true; +} + +void GetCurrentTime(int64_t* seconds, int32_t* nanos) { + // TODO(xiaofeng): Improve the accuracy of this implementation (or just + // remove this method from protobuf). + *seconds = time(nullptr); + *nanos = 0; +} + +std::string FormatTime(int64_t seconds, int32_t nanos) { + DateTime time; + if (nanos < 0 || nanos > 999999999 || !SecondsToDateTime(seconds, &time)) { + return "InvalidTime"; + } + std::string result = + StringPrintf("%04d-%02d-%02dT%02d:%02d:%02d", time.year, time.month, + time.day, time.hour, time.minute, time.second); + if (nanos != 0) { + result += "." + FormatNanos(nanos); + } + return result + "Z"; +} + +bool ParseTime(const std::string& value, int64_t* seconds, int32_t* nanos) { + DateTime time; + const char* data = value.c_str(); + // We only accept: + // Z-normalized: 2015-05-20T13:29:35.120Z + // With UTC offset: 2015-05-20T13:29:35.120-08:00 + + // Parse year + if ((data = ParseInt(data, 4, 1, 9999, &time.year)) == nullptr) { + return false; + } + // Expect '-' + if (*data++ != '-') return false; + // Parse month + if ((data = ParseInt(data, 2, 1, 12, &time.month)) == nullptr) { + return false; + } + // Expect '-' + if (*data++ != '-') return false; + // Parse day + if ((data = ParseInt(data, 2, 1, 31, &time.day)) == nullptr) { + return false; + } + // Expect 'T' + if (*data++ != 'T') return false; + // Parse hour + if ((data = ParseInt(data, 2, 0, 23, &time.hour)) == nullptr) { + return false; + } + // Expect ':' + if (*data++ != ':') return false; + // Parse minute + if ((data = ParseInt(data, 2, 0, 59, &time.minute)) == nullptr) { + return false; + } + // Expect ':' + if (*data++ != ':') return false; + // Parse second + if ((data = ParseInt(data, 2, 0, 59, &time.second)) == nullptr) { + return false; + } + if (!DateTimeToSeconds(time, seconds)) { + return false; + } + // Parse nanoseconds. + if (*data == '.') { + ++data; + // Parse nanoseconds. + if ((data = ParseNanos(data, nanos)) == nullptr) { + return false; + } + } else { + *nanos = 0; + } + // Parse UTC offsets. + if (*data == 'Z') { + ++data; + } else if (*data == '+') { + ++data; + int64_t offset; + if ((data = ParseTimezoneOffset(data, &offset)) == nullptr) { + return false; + } + *seconds -= offset; + } else if (*data == '-') { + ++data; + int64_t offset; + if ((data = ParseTimezoneOffset(data, &offset)) == nullptr) { + return false; + } + *seconds += offset; + } else { + return false; + } + // Done with parsing. + return *data == 0; +} + +} // namespace internal +} // namespace protobuf +} // namespace google diff --git a/toolkit/components/protobuf/src/google/protobuf/stubs/time.h b/toolkit/components/protobuf/src/google/protobuf/stubs/time.h new file mode 100644 index 0000000000..8b6e56214f --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/stubs/time.h @@ -0,0 +1,82 @@ +// 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. +#ifndef GOOGLE_PROTOBUF_STUBS_TIME_H_ +#define GOOGLE_PROTOBUF_STUBS_TIME_H_ + +#include <cstdint> + +#include <google/protobuf/stubs/common.h> + +#include <google/protobuf/port_def.inc> + +namespace google { +namespace protobuf { +namespace internal { + +struct DateTime { + int year; + int month; + int day; + int hour; + int minute; + int second; +}; + +// Converts a timestamp (seconds elapsed since 1970-01-01T00:00:00, could be +// negative to represent time before 1970-01-01) to DateTime. Returns false +// if the timestamp is not in the range between 0001-01-01T00:00:00 and +// 9999-12-31T23:59:59. +bool PROTOBUF_EXPORT SecondsToDateTime(int64_t seconds, DateTime* time); +// Converts DateTime to a timestamp (seconds since 1970-01-01T00:00:00). +// Returns false if the DateTime is not valid or is not in the valid range. +bool PROTOBUF_EXPORT DateTimeToSeconds(const DateTime& time, int64_t* seconds); + +void PROTOBUF_EXPORT GetCurrentTime(int64_t* seconds, int32_t* nanos); + +// Formats a time string in RFC3339 format. +// +// For example, "2015-05-20T13:29:35.120Z". For nanos, 0, 3, 6 or 9 fractional +// digits will be used depending on how many are required to represent the exact +// value. +// +// Note that "nanos" must in the range of [0, 999999999]. +std::string PROTOBUF_EXPORT FormatTime(int64_t seconds, int32_t nanos); +// Parses a time string. This method accepts RFC3339 date/time string with UTC +// offset. For example, "2015-05-20T13:29:35.120-08:00". +bool PROTOBUF_EXPORT ParseTime(const std::string& value, int64_t* seconds, + int32_t* nanos); + +} // namespace internal +} // namespace protobuf +} // namespace google + +#include <google/protobuf/port_undef.inc> + +#endif // GOOGLE_PROTOBUF_STUBS_TIME_H_ diff --git a/toolkit/components/protobuf/src/google/protobuf/text_format.cc b/toolkit/components/protobuf/src/google/protobuf/text_format.cc new file mode 100644 index 0000000000..19110499d7 --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/text_format.cc @@ -0,0 +1,2746 @@ +// 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. + +// Author: jschorr@google.com (Joseph Schorr) +// Based on original Protocol Buffers design by +// Sanjay Ghemawat, Jeff Dean, and others. + +#include <google/protobuf/text_format.h> + +#include <float.h> +#include <stdio.h> + +#include <algorithm> +#include <atomic> +#include <climits> +#include <cmath> +#include <limits> +#include <utility> +#include <vector> + +#include <google/protobuf/io/coded_stream.h> +#include <google/protobuf/io/tokenizer.h> +#include <google/protobuf/io/zero_copy_stream.h> +#include <google/protobuf/io/zero_copy_stream_impl.h> +#include <google/protobuf/stubs/strutil.h> +#include <google/protobuf/any.h> +#include <google/protobuf/descriptor.h> +#include <google/protobuf/descriptor.pb.h> +#include <google/protobuf/dynamic_message.h> +#include <google/protobuf/io/strtod.h> +#include <google/protobuf/map_field.h> +#include <google/protobuf/message.h> +#include <google/protobuf/repeated_field.h> +#include <google/protobuf/unknown_field_set.h> +#include <google/protobuf/wire_format_lite.h> +#include <google/protobuf/stubs/map_util.h> +#include <google/protobuf/stubs/stl_util.h> + +// Must be included last. +#include <google/protobuf/port_def.inc> + +namespace google { +namespace protobuf { + +namespace { + +inline bool IsHexNumber(const std::string& str) { + return (str.length() >= 2 && str[0] == '0' && + (str[1] == 'x' || str[1] == 'X')); +} + +inline bool IsOctNumber(const std::string& str) { + return (str.length() >= 2 && str[0] == '0' && + (str[1] >= '0' && str[1] < '8')); +} + +} // namespace + +namespace internal { +const char kDebugStringSilentMarker[] = ""; +const char kDebugStringSilentMarkerForDetection[] = "\t "; + +// Controls insertion of kDebugStringSilentMarker. +PROTOBUF_EXPORT std::atomic<bool> enable_debug_text_format_marker; +} // namespace internal + +std::string Message::DebugString() const { + std::string debug_string; + + TextFormat::Printer printer; + printer.SetExpandAny(true); + printer.SetInsertSilentMarker(internal::enable_debug_text_format_marker.load( + std::memory_order_relaxed)); + + printer.PrintToString(*this, &debug_string); + + return debug_string; +} + +std::string Message::ShortDebugString() const { + std::string debug_string; + + TextFormat::Printer printer; + printer.SetSingleLineMode(true); + printer.SetExpandAny(true); + printer.SetInsertSilentMarker(internal::enable_debug_text_format_marker.load( + std::memory_order_relaxed)); + + printer.PrintToString(*this, &debug_string); + // Single line mode currently might have an extra space at the end. + if (!debug_string.empty() && debug_string[debug_string.size() - 1] == ' ') { + debug_string.resize(debug_string.size() - 1); + } + + return debug_string; +} + +std::string Message::Utf8DebugString() const { + std::string debug_string; + + TextFormat::Printer printer; + printer.SetUseUtf8StringEscaping(true); + printer.SetExpandAny(true); + printer.SetInsertSilentMarker(internal::enable_debug_text_format_marker.load( + std::memory_order_relaxed)); + + printer.PrintToString(*this, &debug_string); + + return debug_string; +} + +void Message::PrintDebugString() const { printf("%s", DebugString().c_str()); } + + +// =========================================================================== +// Implementation of the parse information tree class. +void TextFormat::ParseInfoTree::RecordLocation( + const FieldDescriptor* field, TextFormat::ParseLocationRange range) { + locations_[field].push_back(range); +} + +TextFormat::ParseInfoTree* TextFormat::ParseInfoTree::CreateNested( + const FieldDescriptor* field) { + // Owned by us in the map. + auto& vec = nested_[field]; + vec.emplace_back(new TextFormat::ParseInfoTree()); + return vec.back().get(); +} + +void CheckFieldIndex(const FieldDescriptor* field, int index) { + if (field == nullptr) { + return; + } + + if (field->is_repeated() && index == -1) { + GOOGLE_LOG(DFATAL) << "Index must be in range of repeated field values. " + << "Field: " << field->name(); + } else if (!field->is_repeated() && index != -1) { + GOOGLE_LOG(DFATAL) << "Index must be -1 for singular fields." + << "Field: " << field->name(); + } +} + +TextFormat::ParseLocationRange TextFormat::ParseInfoTree::GetLocationRange( + const FieldDescriptor* field, int index) const { + CheckFieldIndex(field, index); + if (index == -1) { + index = 0; + } + + const std::vector<TextFormat::ParseLocationRange>* locations = + FindOrNull(locations_, field); + if (locations == nullptr || + index >= static_cast<int64_t>(locations->size())) { + return TextFormat::ParseLocationRange(); + } + + return (*locations)[index]; +} + +TextFormat::ParseInfoTree* TextFormat::ParseInfoTree::GetTreeForNested( + const FieldDescriptor* field, int index) const { + CheckFieldIndex(field, index); + if (index == -1) { + index = 0; + } + + auto it = nested_.find(field); + if (it == nested_.end() || index >= static_cast<int64_t>(it->second.size())) { + return nullptr; + } + + return it->second[index].get(); +} + +namespace { +// These functions implement the behavior of the "default" TextFormat::Finder, +// they are defined as standalone to be called when finder_ is nullptr. +const FieldDescriptor* DefaultFinderFindExtension(Message* message, + const std::string& name) { + const Descriptor* descriptor = message->GetDescriptor(); + return descriptor->file()->pool()->FindExtensionByPrintableName(descriptor, + name); +} + +const FieldDescriptor* DefaultFinderFindExtensionByNumber( + const Descriptor* descriptor, int number) { + return descriptor->file()->pool()->FindExtensionByNumber(descriptor, number); +} + +const Descriptor* DefaultFinderFindAnyType(const Message& message, + const std::string& prefix, + const std::string& name) { + if (prefix != internal::kTypeGoogleApisComPrefix && + prefix != internal::kTypeGoogleProdComPrefix) { + return nullptr; + } + return message.GetDescriptor()->file()->pool()->FindMessageTypeByName(name); +} +} // namespace + +// =========================================================================== +// Internal class for parsing an ASCII representation of a Protocol Message. +// This class makes use of the Protocol Message compiler's tokenizer found +// in //net/proto2/io/public/tokenizer.h. Note that class's Parse +// method is *not* thread-safe and should only be used in a single thread at +// a time. + +// Makes code slightly more readable. The meaning of "DO(foo)" is +// "Execute foo and fail if it fails.", where failure is indicated by +// returning false. Borrowed from parser.cc (Thanks Kenton!). +#define DO(STATEMENT) \ + if (STATEMENT) { \ + } else { \ + return false; \ + } + +class TextFormat::Parser::ParserImpl { + public: + // Determines if repeated values for non-repeated fields and + // oneofs are permitted, e.g., the string "foo: 1 foo: 2" for a + // required/optional field named "foo", or "baz: 1 bar: 2" + // where "baz" and "bar" are members of the same oneof. + enum SingularOverwritePolicy { + ALLOW_SINGULAR_OVERWRITES = 0, // the last value is retained + FORBID_SINGULAR_OVERWRITES = 1, // an error is issued + }; + + ParserImpl(const Descriptor* root_message_type, + io::ZeroCopyInputStream* input_stream, + io::ErrorCollector* error_collector, + const TextFormat::Finder* finder, ParseInfoTree* parse_info_tree, + SingularOverwritePolicy singular_overwrite_policy, + bool allow_case_insensitive_field, bool allow_unknown_field, + bool allow_unknown_extension, bool allow_unknown_enum, + bool allow_field_number, bool allow_relaxed_whitespace, + bool allow_partial, int recursion_limit) + : error_collector_(error_collector), + finder_(finder), + parse_info_tree_(parse_info_tree), + tokenizer_error_collector_(this), + tokenizer_(input_stream, &tokenizer_error_collector_), + root_message_type_(root_message_type), + singular_overwrite_policy_(singular_overwrite_policy), + allow_case_insensitive_field_(allow_case_insensitive_field), + allow_unknown_field_(allow_unknown_field), + allow_unknown_extension_(allow_unknown_extension), + allow_unknown_enum_(allow_unknown_enum), + allow_field_number_(allow_field_number), + allow_partial_(allow_partial), + initial_recursion_limit_(recursion_limit), + recursion_limit_(recursion_limit), + had_silent_marker_(false), + had_errors_(false) { + // For backwards-compatibility with proto1, we need to allow the 'f' suffix + // for floats. + tokenizer_.set_allow_f_after_float(true); + + // '#' starts a comment. + tokenizer_.set_comment_style(io::Tokenizer::SH_COMMENT_STYLE); + + if (allow_relaxed_whitespace) { + tokenizer_.set_require_space_after_number(false); + tokenizer_.set_allow_multiline_strings(true); + } + + // Consume the starting token. + tokenizer_.Next(); + } + ~ParserImpl() {} + + // Parses the ASCII representation specified in input and saves the + // information into the output pointer (a Message). Returns + // false if an error occurs (an error will also be logged to + // GOOGLE_LOG(ERROR)). + bool Parse(Message* output) { + // Consume fields until we cannot do so anymore. + while (true) { + if (LookingAtType(io::Tokenizer::TYPE_END)) { + // Ensures recursion limit properly unwinded, but only for success + // cases. This implicitly avoids the check when `Parse` returns false + // via `DO(...)`. + GOOGLE_DCHECK(had_errors_ || recursion_limit_ == initial_recursion_limit_) + << "Recursion limit at end of parse should be " + << initial_recursion_limit_ << ", but was " << recursion_limit_ + << ". Difference of " << initial_recursion_limit_ - recursion_limit_ + << " stack frames not accounted for stack unwind."; + + return !had_errors_; + } + + DO(ConsumeField(output)); + } + } + + bool ParseField(const FieldDescriptor* field, Message* output) { + bool suc; + if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { + suc = ConsumeFieldMessage(output, output->GetReflection(), field); + } else { + suc = ConsumeFieldValue(output, output->GetReflection(), field); + } + return suc && LookingAtType(io::Tokenizer::TYPE_END); + } + + void ReportError(int line, int col, const std::string& message) { + had_errors_ = true; + if (error_collector_ == nullptr) { + if (line >= 0) { + GOOGLE_LOG(ERROR) << "Error parsing text-format " + << root_message_type_->full_name() << ": " << (line + 1) + << ":" << (col + 1) << ": " << message; + } else { + GOOGLE_LOG(ERROR) << "Error parsing text-format " + << root_message_type_->full_name() << ": " << message; + } + } else { + error_collector_->AddError(line, col, message); + } + } + + void ReportWarning(int line, int col, const std::string& message) { + if (error_collector_ == nullptr) { + if (line >= 0) { + GOOGLE_LOG(WARNING) << "Warning parsing text-format " + << root_message_type_->full_name() << ": " << (line + 1) + << ":" << (col + 1) << ": " << message; + } else { + GOOGLE_LOG(WARNING) << "Warning parsing text-format " + << root_message_type_->full_name() << ": " << message; + } + } else { + error_collector_->AddWarning(line, col, message); + } + } + + private: + static constexpr int32_t kint32max = std::numeric_limits<int32_t>::max(); + static constexpr uint32_t kuint32max = std::numeric_limits<uint32_t>::max(); + static constexpr int64_t kint64min = std::numeric_limits<int64_t>::min(); + static constexpr int64_t kint64max = std::numeric_limits<int64_t>::max(); + static constexpr uint64_t kuint64max = std::numeric_limits<uint64_t>::max(); + + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ParserImpl); + + // Reports an error with the given message with information indicating + // the position (as derived from the current token). + void ReportError(const std::string& message) { + ReportError(tokenizer_.current().line, tokenizer_.current().column, + message); + } + + // Reports a warning with the given message with information indicating + // the position (as derived from the current token). + void ReportWarning(const std::string& message) { + ReportWarning(tokenizer_.current().line, tokenizer_.current().column, + message); + } + + // Consumes the specified message with the given starting delimiter. + // This method checks to see that the end delimiter at the conclusion of + // the consumption matches the starting delimiter passed in here. + bool ConsumeMessage(Message* message, const std::string delimiter) { + while (!LookingAt(">") && !LookingAt("}")) { + DO(ConsumeField(message)); + } + + // Confirm that we have a valid ending delimiter. + DO(Consume(delimiter)); + return true; + } + + // Consume either "<" or "{". + bool ConsumeMessageDelimiter(std::string* delimiter) { + if (TryConsume("<")) { + *delimiter = ">"; + } else { + DO(Consume("{")); + *delimiter = "}"; + } + return true; + } + + + // Consumes the current field (as returned by the tokenizer) on the + // passed in message. + bool ConsumeField(Message* message) { + const Reflection* reflection = message->GetReflection(); + const Descriptor* descriptor = message->GetDescriptor(); + + std::string field_name; + bool reserved_field = false; + const FieldDescriptor* field = nullptr; + int start_line = tokenizer_.current().line; + int start_column = tokenizer_.current().column; + + const FieldDescriptor* any_type_url_field; + const FieldDescriptor* any_value_field; + if (internal::GetAnyFieldDescriptors(*message, &any_type_url_field, + &any_value_field) && + TryConsume("[")) { + std::string full_type_name, prefix; + DO(ConsumeAnyTypeUrl(&full_type_name, &prefix)); + std::string prefix_and_full_type_name = + StrCat(prefix, full_type_name); + DO(ConsumeBeforeWhitespace("]")); + TryConsumeWhitespace(); + // ':' is optional between message labels and values. + if (TryConsumeBeforeWhitespace(":")) { + TryConsumeWhitespace(); + } + std::string serialized_value; + const Descriptor* value_descriptor = + finder_ ? finder_->FindAnyType(*message, prefix, full_type_name) + : DefaultFinderFindAnyType(*message, prefix, full_type_name); + if (value_descriptor == nullptr) { + ReportError("Could not find type \"" + prefix_and_full_type_name + + "\" stored in google.protobuf.Any."); + return false; + } + DO(ConsumeAnyValue(value_descriptor, &serialized_value)); + if (singular_overwrite_policy_ == FORBID_SINGULAR_OVERWRITES) { + // Fail if any_type_url_field has already been specified. + if ((!any_type_url_field->is_repeated() && + reflection->HasField(*message, any_type_url_field)) || + (!any_value_field->is_repeated() && + reflection->HasField(*message, any_value_field))) { + ReportError("Non-repeated Any specified multiple times."); + return false; + } + } + reflection->SetString(message, any_type_url_field, + std::move(prefix_and_full_type_name)); + reflection->SetString(message, any_value_field, + std::move(serialized_value)); + return true; + } + if (TryConsume("[")) { + // Extension. + DO(ConsumeFullTypeName(&field_name)); + DO(ConsumeBeforeWhitespace("]")); + TryConsumeWhitespace(); + + field = finder_ ? finder_->FindExtension(message, field_name) + : DefaultFinderFindExtension(message, field_name); + + if (field == nullptr) { + if (!allow_unknown_field_ && !allow_unknown_extension_) { + ReportError("Extension \"" + field_name + + "\" is not defined or " + "is not an extension of \"" + + descriptor->full_name() + "\"."); + return false; + } else { + ReportWarning("Ignoring extension \"" + field_name + + "\" which is not defined or is not an extension of \"" + + descriptor->full_name() + "\"."); + } + } + } else { + DO(ConsumeIdentifierBeforeWhitespace(&field_name)); + TryConsumeWhitespace(); + + int32_t field_number; + if (allow_field_number_ && safe_strto32(field_name, &field_number)) { + if (descriptor->IsExtensionNumber(field_number)) { + field = finder_ + ? finder_->FindExtensionByNumber(descriptor, field_number) + : DefaultFinderFindExtensionByNumber(descriptor, + field_number); + } else if (descriptor->IsReservedNumber(field_number)) { + reserved_field = true; + } else { + field = descriptor->FindFieldByNumber(field_number); + } + } else { + field = descriptor->FindFieldByName(field_name); + // Group names are expected to be capitalized as they appear in the + // .proto file, which actually matches their type names, not their + // field names. + if (field == nullptr) { + std::string lower_field_name = field_name; + LowerString(&lower_field_name); + field = descriptor->FindFieldByName(lower_field_name); + // If the case-insensitive match worked but the field is NOT a group, + if (field != nullptr && + field->type() != FieldDescriptor::TYPE_GROUP) { + field = nullptr; + } + } + // Again, special-case group names as described above. + if (field != nullptr && field->type() == FieldDescriptor::TYPE_GROUP && + field->message_type()->name() != field_name) { + field = nullptr; + } + + if (field == nullptr && allow_case_insensitive_field_) { + std::string lower_field_name = field_name; + LowerString(&lower_field_name); + field = descriptor->FindFieldByLowercaseName(lower_field_name); + } + + if (field == nullptr) { + reserved_field = descriptor->IsReservedName(field_name); + } + } + + if (field == nullptr && !reserved_field) { + if (!allow_unknown_field_) { + ReportError("Message type \"" + descriptor->full_name() + + "\" has no field named \"" + field_name + "\"."); + return false; + } else { + ReportWarning("Message type \"" + descriptor->full_name() + + "\" has no field named \"" + field_name + "\"."); + } + } + } + + // Skips unknown or reserved fields. + if (field == nullptr) { + GOOGLE_CHECK(allow_unknown_field_ || allow_unknown_extension_ || reserved_field); + + // Try to guess the type of this field. + // If this field is not a message, there should be a ":" between the + // field name and the field value and also the field value should not + // start with "{" or "<" which indicates the beginning of a message body. + // If there is no ":" or there is a "{" or "<" after ":", this field has + // to be a message or the input is ill-formed. + if (TryConsumeBeforeWhitespace(":")) { + TryConsumeWhitespace(); + if (!LookingAt("{") && !LookingAt("<")) { + return SkipFieldValue(); + } + } + return SkipFieldMessage(); + } + + if (singular_overwrite_policy_ == FORBID_SINGULAR_OVERWRITES) { + // Fail if the field is not repeated and it has already been specified. + if (!field->is_repeated() && reflection->HasField(*message, field)) { + ReportError("Non-repeated field \"" + field_name + + "\" is specified multiple times."); + return false; + } + // Fail if the field is a member of a oneof and another member has already + // been specified. + const OneofDescriptor* oneof = field->containing_oneof(); + if (oneof != nullptr && reflection->HasOneof(*message, oneof)) { + const FieldDescriptor* other_field = + reflection->GetOneofFieldDescriptor(*message, oneof); + ReportError("Field \"" + field_name + + "\" is specified along with " + "field \"" + + other_field->name() + + "\", another member " + "of oneof \"" + + oneof->name() + "\"."); + return false; + } + } + + // Perform special handling for embedded message types. + if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { + // ':' is optional here. + bool consumed_semicolon = TryConsumeBeforeWhitespace(":"); + if (consumed_semicolon) { + TryConsumeWhitespace(); + } + if (consumed_semicolon && field->options().weak() && + LookingAtType(io::Tokenizer::TYPE_STRING)) { + // we are getting a bytes string for a weak field. + std::string tmp; + DO(ConsumeString(&tmp)); + MessageFactory* factory = + finder_ ? finder_->FindExtensionFactory(field) : nullptr; + reflection->MutableMessage(message, field, factory) + ->ParseFromString(tmp); + goto label_skip_parsing; + } + } else { + // ':' is required here. + DO(ConsumeBeforeWhitespace(":")); + TryConsumeWhitespace(); + } + + if (field->is_repeated() && TryConsume("[")) { + // Short repeated format, e.g. "foo: [1, 2, 3]". + if (!TryConsume("]")) { + // "foo: []" is treated as empty. + while (true) { + if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { + // Perform special handling for embedded message types. + DO(ConsumeFieldMessage(message, reflection, field)); + } else { + DO(ConsumeFieldValue(message, reflection, field)); + } + if (TryConsume("]")) { + break; + } + DO(Consume(",")); + } + } + } else if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { + DO(ConsumeFieldMessage(message, reflection, field)); + } else { + DO(ConsumeFieldValue(message, reflection, field)); + } + label_skip_parsing: + // For historical reasons, fields may optionally be separated by commas or + // semicolons. + TryConsume(";") || TryConsume(","); + + if (field->options().deprecated()) { + ReportWarning("text format contains deprecated field \"" + field_name + + "\""); + } + + // If a parse info tree exists, add the location for the parsed + // field. + if (parse_info_tree_ != nullptr) { + int end_line = tokenizer_.previous().line; + int end_column = tokenizer_.previous().end_column; + + RecordLocation(parse_info_tree_, field, + ParseLocationRange(ParseLocation(start_line, start_column), + ParseLocation(end_line, end_column))); + } + + return true; + } + + // Skips the next field including the field's name and value. + bool SkipField() { + std::string field_name; + if (TryConsume("[")) { + // Extension name or type URL. + DO(ConsumeTypeUrlOrFullTypeName(&field_name)); + DO(ConsumeBeforeWhitespace("]")); + } else { + DO(ConsumeIdentifierBeforeWhitespace(&field_name)); + } + TryConsumeWhitespace(); + + // Try to guess the type of this field. + // If this field is not a message, there should be a ":" between the + // field name and the field value and also the field value should not + // start with "{" or "<" which indicates the beginning of a message body. + // If there is no ":" or there is a "{" or "<" after ":", this field has + // to be a message or the input is ill-formed. + if (TryConsumeBeforeWhitespace(":")) { + TryConsumeWhitespace(); + if (!LookingAt("{") && !LookingAt("<")) { + DO(SkipFieldValue()); + } else { + DO(SkipFieldMessage()); + } + } else { + DO(SkipFieldMessage()); + } + // For historical reasons, fields may optionally be separated by commas or + // semicolons. + TryConsume(";") || TryConsume(","); + return true; + } + + bool ConsumeFieldMessage(Message* message, const Reflection* reflection, + const FieldDescriptor* field) { + if (--recursion_limit_ < 0) { + ReportError( + StrCat("Message is too deep, the parser exceeded the " + "configured recursion limit of ", + initial_recursion_limit_, ".")); + return false; + } + // If the parse information tree is not nullptr, create a nested one + // for the nested message. + ParseInfoTree* parent = parse_info_tree_; + if (parent != nullptr) { + parse_info_tree_ = CreateNested(parent, field); + } + + std::string delimiter; + DO(ConsumeMessageDelimiter(&delimiter)); + MessageFactory* factory = + finder_ ? finder_->FindExtensionFactory(field) : nullptr; + if (field->is_repeated()) { + DO(ConsumeMessage(reflection->AddMessage(message, field, factory), + delimiter)); + } else { + DO(ConsumeMessage(reflection->MutableMessage(message, field, factory), + delimiter)); + } + + ++recursion_limit_; + + // Reset the parse information tree. + parse_info_tree_ = parent; + return true; + } + + // Skips the whole body of a message including the beginning delimiter and + // the ending delimiter. + bool SkipFieldMessage() { + if (--recursion_limit_ < 0) { + ReportError( + StrCat("Message is too deep, the parser exceeded the " + "configured recursion limit of ", + initial_recursion_limit_, ".")); + return false; + } + + std::string delimiter; + DO(ConsumeMessageDelimiter(&delimiter)); + while (!LookingAt(">") && !LookingAt("}")) { + DO(SkipField()); + } + DO(Consume(delimiter)); + + ++recursion_limit_; + return true; + } + + bool ConsumeFieldValue(Message* message, const Reflection* reflection, + const FieldDescriptor* field) { +// Define an easy to use macro for setting fields. This macro checks +// to see if the field is repeated (in which case we need to use the Add +// methods or not (in which case we need to use the Set methods). +#define SET_FIELD(CPPTYPE, VALUE) \ + if (field->is_repeated()) { \ + reflection->Add##CPPTYPE(message, field, VALUE); \ + } else { \ + reflection->Set##CPPTYPE(message, field, VALUE); \ + } + + switch (field->cpp_type()) { + case FieldDescriptor::CPPTYPE_INT32: { + int64_t value; + DO(ConsumeSignedInteger(&value, kint32max)); + SET_FIELD(Int32, static_cast<int32_t>(value)); + break; + } + + case FieldDescriptor::CPPTYPE_UINT32: { + uint64_t value; + DO(ConsumeUnsignedInteger(&value, kuint32max)); + SET_FIELD(UInt32, static_cast<uint32_t>(value)); + break; + } + + case FieldDescriptor::CPPTYPE_INT64: { + int64_t value; + DO(ConsumeSignedInteger(&value, kint64max)); + SET_FIELD(Int64, value); + break; + } + + case FieldDescriptor::CPPTYPE_UINT64: { + uint64_t value; + DO(ConsumeUnsignedInteger(&value, kuint64max)); + SET_FIELD(UInt64, value); + break; + } + + case FieldDescriptor::CPPTYPE_FLOAT: { + double value; + DO(ConsumeDouble(&value)); + SET_FIELD(Float, io::SafeDoubleToFloat(value)); + break; + } + + case FieldDescriptor::CPPTYPE_DOUBLE: { + double value; + DO(ConsumeDouble(&value)); + SET_FIELD(Double, value); + break; + } + + case FieldDescriptor::CPPTYPE_STRING: { + std::string value; + DO(ConsumeString(&value)); + SET_FIELD(String, std::move(value)); + break; + } + + case FieldDescriptor::CPPTYPE_BOOL: { + if (LookingAtType(io::Tokenizer::TYPE_INTEGER)) { + uint64_t value; + DO(ConsumeUnsignedInteger(&value, 1)); + SET_FIELD(Bool, value); + } else { + std::string value; + DO(ConsumeIdentifier(&value)); + if (value == "true" || value == "True" || value == "t") { + SET_FIELD(Bool, true); + } else if (value == "false" || value == "False" || value == "f") { + SET_FIELD(Bool, false); + } else { + ReportError("Invalid value for boolean field \"" + field->name() + + "\". Value: \"" + value + "\"."); + return false; + } + } + break; + } + + case FieldDescriptor::CPPTYPE_ENUM: { + std::string value; + int64_t int_value = kint64max; + const EnumDescriptor* enum_type = field->enum_type(); + const EnumValueDescriptor* enum_value = nullptr; + + if (LookingAtType(io::Tokenizer::TYPE_IDENTIFIER)) { + DO(ConsumeIdentifier(&value)); + // Find the enumeration value. + enum_value = enum_type->FindValueByName(value); + + } else if (LookingAt("-") || + LookingAtType(io::Tokenizer::TYPE_INTEGER)) { + DO(ConsumeSignedInteger(&int_value, kint32max)); + value = StrCat(int_value); // for error reporting + enum_value = enum_type->FindValueByNumber(int_value); + } else { + ReportError("Expected integer or identifier, got: " + + tokenizer_.current().text); + return false; + } + + if (enum_value == nullptr) { + if (int_value != kint64max && + reflection->SupportsUnknownEnumValues()) { + SET_FIELD(EnumValue, int_value); + return true; + } else if (!allow_unknown_enum_) { + ReportError("Unknown enumeration value of \"" + value + + "\" for " + "field \"" + + field->name() + "\"."); + return false; + } else { + ReportWarning("Unknown enumeration value of \"" + value + + "\" for " + "field \"" + + field->name() + "\"."); + return true; + } + } + + SET_FIELD(Enum, enum_value); + break; + } + + case FieldDescriptor::CPPTYPE_MESSAGE: { + // We should never get here. Put here instead of a default + // so that if new types are added, we get a nice compiler warning. + GOOGLE_LOG(FATAL) << "Reached an unintended state: CPPTYPE_MESSAGE"; + break; + } + } +#undef SET_FIELD + return true; + } + + bool SkipFieldValue() { + if (--recursion_limit_ < 0) { + ReportError( + StrCat("Message is too deep, the parser exceeded the " + "configured recursion limit of ", + initial_recursion_limit_, ".")); + return false; + } + + if (LookingAtType(io::Tokenizer::TYPE_STRING)) { + while (LookingAtType(io::Tokenizer::TYPE_STRING)) { + tokenizer_.Next(); + } + ++recursion_limit_; + return true; + } + if (TryConsume("[")) { + while (true) { + if (!LookingAt("{") && !LookingAt("<")) { + DO(SkipFieldValue()); + } else { + DO(SkipFieldMessage()); + } + if (TryConsume("]")) { + break; + } + DO(Consume(",")); + } + ++recursion_limit_; + return true; + } + // Possible field values other than string: + // 12345 => TYPE_INTEGER + // -12345 => TYPE_SYMBOL + TYPE_INTEGER + // 1.2345 => TYPE_FLOAT + // -1.2345 => TYPE_SYMBOL + TYPE_FLOAT + // inf => TYPE_IDENTIFIER + // -inf => TYPE_SYMBOL + TYPE_IDENTIFIER + // TYPE_INTEGER => TYPE_IDENTIFIER + // Divides them into two group, one with TYPE_SYMBOL + // and the other without: + // Group one: + // 12345 => TYPE_INTEGER + // 1.2345 => TYPE_FLOAT + // inf => TYPE_IDENTIFIER + // TYPE_INTEGER => TYPE_IDENTIFIER + // Group two: + // -12345 => TYPE_SYMBOL + TYPE_INTEGER + // -1.2345 => TYPE_SYMBOL + TYPE_FLOAT + // -inf => TYPE_SYMBOL + TYPE_IDENTIFIER + // As we can see, the field value consists of an optional '-' and one of + // TYPE_INTEGER, TYPE_FLOAT and TYPE_IDENTIFIER. + bool has_minus = TryConsume("-"); + if (!LookingAtType(io::Tokenizer::TYPE_INTEGER) && + !LookingAtType(io::Tokenizer::TYPE_FLOAT) && + !LookingAtType(io::Tokenizer::TYPE_IDENTIFIER)) { + std::string text = tokenizer_.current().text; + ReportError("Cannot skip field value, unexpected token: " + text); + ++recursion_limit_; + return false; + } + // Combination of '-' and TYPE_IDENTIFIER may result in an invalid field + // value while other combinations all generate valid values. + // We check if the value of this combination is valid here. + // TYPE_IDENTIFIER after a '-' should be one of the float values listed + // below: + // inf, inff, infinity, nan + if (has_minus && LookingAtType(io::Tokenizer::TYPE_IDENTIFIER)) { + std::string text = tokenizer_.current().text; + LowerString(&text); + if (text != "inf" && + text != "infinity" && text != "nan") { + ReportError("Invalid float number: " + text); + ++recursion_limit_; + return false; + } + } + tokenizer_.Next(); + ++recursion_limit_; + return true; + } + + // Returns true if the current token's text is equal to that specified. + bool LookingAt(const std::string& text) { + return tokenizer_.current().text == text; + } + + // Returns true if the current token's type is equal to that specified. + bool LookingAtType(io::Tokenizer::TokenType token_type) { + return tokenizer_.current().type == token_type; + } + + // Consumes an identifier and saves its value in the identifier parameter. + // Returns false if the token is not of type IDENTFIER. + bool ConsumeIdentifier(std::string* identifier) { + if (LookingAtType(io::Tokenizer::TYPE_IDENTIFIER)) { + *identifier = tokenizer_.current().text; + tokenizer_.Next(); + return true; + } + + // If allow_field_numer_ or allow_unknown_field_ is true, we should able + // to parse integer identifiers. + if ((allow_field_number_ || allow_unknown_field_ || + allow_unknown_extension_) && + LookingAtType(io::Tokenizer::TYPE_INTEGER)) { + *identifier = tokenizer_.current().text; + tokenizer_.Next(); + return true; + } + + ReportError("Expected identifier, got: " + tokenizer_.current().text); + return false; + } + + // Similar to `ConsumeIdentifier`, but any following whitespace token may + // be reported. + bool ConsumeIdentifierBeforeWhitespace(std::string* identifier) { + tokenizer_.set_report_whitespace(true); + bool result = ConsumeIdentifier(identifier); + tokenizer_.set_report_whitespace(false); + return result; + } + + // Consume a string of form "<id1>.<id2>....<idN>". + bool ConsumeFullTypeName(std::string* name) { + DO(ConsumeIdentifier(name)); + while (TryConsume(".")) { + std::string part; + DO(ConsumeIdentifier(&part)); + *name += "."; + *name += part; + } + return true; + } + + bool ConsumeTypeUrlOrFullTypeName(std::string* name) { + DO(ConsumeIdentifier(name)); + while (true) { + std::string connector; + if (TryConsume(".")) { + connector = "."; + } else if (TryConsume("/")) { + connector = "/"; + } else { + break; + } + std::string part; + DO(ConsumeIdentifier(&part)); + *name += connector; + *name += part; + } + return true; + } + + // Consumes a string and saves its value in the text parameter. + // Returns false if the token is not of type STRING. + bool ConsumeString(std::string* text) { + if (!LookingAtType(io::Tokenizer::TYPE_STRING)) { + ReportError("Expected string, got: " + tokenizer_.current().text); + return false; + } + + text->clear(); + while (LookingAtType(io::Tokenizer::TYPE_STRING)) { + io::Tokenizer::ParseStringAppend(tokenizer_.current().text, text); + + tokenizer_.Next(); + } + + return true; + } + + // Consumes a uint64_t and saves its value in the value parameter. + // Returns false if the token is not of type INTEGER. + bool ConsumeUnsignedInteger(uint64_t* value, uint64_t max_value) { + if (!LookingAtType(io::Tokenizer::TYPE_INTEGER)) { + ReportError("Expected integer, got: " + tokenizer_.current().text); + return false; + } + + if (!io::Tokenizer::ParseInteger(tokenizer_.current().text, max_value, + value)) { + ReportError("Integer out of range (" + tokenizer_.current().text + ")"); + return false; + } + + tokenizer_.Next(); + return true; + } + + // Consumes an int64_t and saves its value in the value parameter. + // Note that since the tokenizer does not support negative numbers, + // we actually may consume an additional token (for the minus sign) in this + // method. Returns false if the token is not an integer + // (signed or otherwise). + bool ConsumeSignedInteger(int64_t* value, uint64_t max_value) { + bool negative = false; + + if (TryConsume("-")) { + negative = true; + // Two's complement always allows one more negative integer than + // positive. + ++max_value; + } + + uint64_t unsigned_value; + + DO(ConsumeUnsignedInteger(&unsigned_value, max_value)); + + if (negative) { + if ((static_cast<uint64_t>(kint64max) + 1) == unsigned_value) { + *value = kint64min; + } else { + *value = -static_cast<int64_t>(unsigned_value); + } + } else { + *value = static_cast<int64_t>(unsigned_value); + } + + return true; + } + + // Consumes a double and saves its value in the value parameter. + // Accepts decimal numbers only, rejects hex or oct numbers. + bool ConsumeUnsignedDecimalAsDouble(double* value, uint64_t max_value) { + if (!LookingAtType(io::Tokenizer::TYPE_INTEGER)) { + ReportError("Expected integer, got: " + tokenizer_.current().text); + return false; + } + + const std::string& text = tokenizer_.current().text; + if (IsHexNumber(text) || IsOctNumber(text)) { + ReportError("Expect a decimal number, got: " + text); + return false; + } + + uint64_t uint64_value; + if (io::Tokenizer::ParseInteger(text, max_value, &uint64_value)) { + *value = static_cast<double>(uint64_value); + } else { + // Uint64 overflow, attempt to parse as a double instead. + *value = io::Tokenizer::ParseFloat(text); + } + + tokenizer_.Next(); + return true; + } + + // Consumes a double and saves its value in the value parameter. + // Note that since the tokenizer does not support negative numbers, + // we actually may consume an additional token (for the minus sign) in this + // method. Returns false if the token is not a double + // (signed or otherwise). + bool ConsumeDouble(double* value) { + bool negative = false; + + if (TryConsume("-")) { + negative = true; + } + + // A double can actually be an integer, according to the tokenizer. + // Therefore, we must check both cases here. + if (LookingAtType(io::Tokenizer::TYPE_INTEGER)) { + // We have found an integer value for the double. + DO(ConsumeUnsignedDecimalAsDouble(value, kuint64max)); + } else if (LookingAtType(io::Tokenizer::TYPE_FLOAT)) { + // We have found a float value for the double. + *value = io::Tokenizer::ParseFloat(tokenizer_.current().text); + + // Mark the current token as consumed. + tokenizer_.Next(); + } else if (LookingAtType(io::Tokenizer::TYPE_IDENTIFIER)) { + std::string text = tokenizer_.current().text; + LowerString(&text); + if (text == "inf" || + text == "infinity") { + *value = std::numeric_limits<double>::infinity(); + tokenizer_.Next(); + } else if (text == "nan") { + *value = std::numeric_limits<double>::quiet_NaN(); + tokenizer_.Next(); + } else { + ReportError("Expected double, got: " + text); + return false; + } + } else { + ReportError("Expected double, got: " + tokenizer_.current().text); + return false; + } + + if (negative) { + *value = -*value; + } + + return true; + } + + // Consumes Any::type_url value, of form "type.googleapis.com/full.type.Name" + // or "type.googleprod.com/full.type.Name" + bool ConsumeAnyTypeUrl(std::string* full_type_name, std::string* prefix) { + // TODO(saito) Extend Consume() to consume multiple tokens at once, so that + // this code can be written as just DO(Consume(kGoogleApisTypePrefix)). + DO(ConsumeIdentifier(prefix)); + while (TryConsume(".")) { + std::string url; + DO(ConsumeIdentifier(&url)); + *prefix += "." + url; + } + DO(Consume("/")); + *prefix += "/"; + DO(ConsumeFullTypeName(full_type_name)); + + return true; + } + + // A helper function for reconstructing Any::value. Consumes a text of + // full_type_name, then serializes it into serialized_value. + bool ConsumeAnyValue(const Descriptor* value_descriptor, + std::string* serialized_value) { + DynamicMessageFactory factory; + const Message* value_prototype = factory.GetPrototype(value_descriptor); + if (value_prototype == nullptr) { + return false; + } + std::unique_ptr<Message> value(value_prototype->New()); + std::string sub_delimiter; + DO(ConsumeMessageDelimiter(&sub_delimiter)); + DO(ConsumeMessage(value.get(), sub_delimiter)); + + if (allow_partial_) { + value->AppendPartialToString(serialized_value); + } else { + if (!value->IsInitialized()) { + ReportError( + "Value of type \"" + value_descriptor->full_name() + + "\" stored in google.protobuf.Any has missing required fields"); + return false; + } + value->AppendToString(serialized_value); + } + return true; + } + + // Consumes a token and confirms that it matches that specified in the + // value parameter. Returns false if the token found does not match that + // which was specified. + bool Consume(const std::string& value) { + const std::string& current_value = tokenizer_.current().text; + + if (current_value != value) { + ReportError("Expected \"" + value + "\", found \"" + current_value + + "\"."); + return false; + } + + tokenizer_.Next(); + + return true; + } + + // Similar to `Consume`, but the following token may be tokenized as + // TYPE_WHITESPACE. + bool ConsumeBeforeWhitespace(const std::string& value) { + // Report whitespace after this token, but only once. + tokenizer_.set_report_whitespace(true); + bool result = Consume(value); + tokenizer_.set_report_whitespace(false); + return result; + } + + // Attempts to consume the supplied value. Returns false if a the + // token found does not match the value specified. + bool TryConsume(const std::string& value) { + if (tokenizer_.current().text == value) { + tokenizer_.Next(); + return true; + } else { + return false; + } + } + + // Similar to `TryConsume`, but the following token may be tokenized as + // TYPE_WHITESPACE. + bool TryConsumeBeforeWhitespace(const std::string& value) { + // Report whitespace after this token, but only once. + tokenizer_.set_report_whitespace(true); + bool result = TryConsume(value); + tokenizer_.set_report_whitespace(false); + return result; + } + + bool TryConsumeWhitespace() { + had_silent_marker_ = false; + if (LookingAtType(io::Tokenizer::TYPE_WHITESPACE)) { + if (tokenizer_.current().text == + StrCat(" ", internal::kDebugStringSilentMarkerForDetection)) { + had_silent_marker_ = true; + } + tokenizer_.Next(); + return true; + } + return false; + } + + // An internal instance of the Tokenizer's error collector, used to + // collect any base-level parse errors and feed them to the ParserImpl. + class ParserErrorCollector : public io::ErrorCollector { + public: + explicit ParserErrorCollector(TextFormat::Parser::ParserImpl* parser) + : parser_(parser) {} + + ~ParserErrorCollector() override {} + + void AddError(int line, int column, const std::string& message) override { + parser_->ReportError(line, column, message); + } + + void AddWarning(int line, int column, const std::string& message) override { + parser_->ReportWarning(line, column, message); + } + + private: + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ParserErrorCollector); + TextFormat::Parser::ParserImpl* parser_; + }; + + io::ErrorCollector* error_collector_; + const TextFormat::Finder* finder_; + ParseInfoTree* parse_info_tree_; + ParserErrorCollector tokenizer_error_collector_; + io::Tokenizer tokenizer_; + const Descriptor* root_message_type_; + SingularOverwritePolicy singular_overwrite_policy_; + const bool allow_case_insensitive_field_; + const bool allow_unknown_field_; + const bool allow_unknown_extension_; + const bool allow_unknown_enum_; + const bool allow_field_number_; + const bool allow_partial_; + const int initial_recursion_limit_; + int recursion_limit_; + bool had_silent_marker_; + bool had_errors_; +}; + +// =========================================================================== +// Internal class for writing text to the io::ZeroCopyOutputStream. Adapted +// from the Printer found in //net/proto2/io/public/printer.h +class TextFormat::Printer::TextGenerator + : public TextFormat::BaseTextGenerator { + public: + explicit TextGenerator(io::ZeroCopyOutputStream* output, + int initial_indent_level) + : output_(output), + buffer_(nullptr), + buffer_size_(0), + at_start_of_line_(true), + failed_(false), + insert_silent_marker_(false), + indent_level_(initial_indent_level), + initial_indent_level_(initial_indent_level) {} + + explicit TextGenerator(io::ZeroCopyOutputStream* output, + bool insert_silent_marker, int initial_indent_level) + : output_(output), + buffer_(nullptr), + buffer_size_(0), + at_start_of_line_(true), + failed_(false), + insert_silent_marker_(insert_silent_marker), + indent_level_(initial_indent_level), + initial_indent_level_(initial_indent_level) {} + + ~TextGenerator() override { + // Only BackUp() if we're sure we've successfully called Next() at least + // once. + if (!failed_) { + output_->BackUp(buffer_size_); + } + } + + // Indent text by two spaces. After calling Indent(), two spaces will be + // inserted at the beginning of each line of text. Indent() may be called + // multiple times to produce deeper indents. + void Indent() override { ++indent_level_; } + + // Reduces the current indent level by two spaces, or crashes if the indent + // level is zero. + void Outdent() override { + if (indent_level_ == 0 || indent_level_ < initial_indent_level_) { + GOOGLE_LOG(DFATAL) << " Outdent() without matching Indent()."; + return; + } + + --indent_level_; + } + + size_t GetCurrentIndentationSize() const override { + return 2 * indent_level_; + } + + // Print text to the output stream. + void Print(const char* text, size_t size) override { + if (indent_level_ > 0) { + size_t pos = 0; // The number of bytes we've written so far. + for (size_t i = 0; i < size; i++) { + if (text[i] == '\n') { + // Saw newline. If there is more text, we may need to insert an + // indent here. So, write what we have so far, including the '\n'. + Write(text + pos, i - pos + 1); + pos = i + 1; + + // Setting this true will cause the next Write() to insert an indent + // first. + at_start_of_line_ = true; + } + } + // Write the rest. + Write(text + pos, size - pos); + } else { + Write(text, size); + if (size > 0 && text[size - 1] == '\n') { + at_start_of_line_ = true; + } + } + } + + // True if any write to the underlying stream failed. (We don't just + // crash in this case because this is an I/O failure, not a programming + // error.) + bool failed() const { return failed_; } + + void PrintMaybeWithMarker(StringPiece text) { + Print(text.data(), text.size()); + if (ConsumeInsertSilentMarker()) { + PrintLiteral(internal::kDebugStringSilentMarker); + } + } + + void PrintMaybeWithMarker(StringPiece text_head, + StringPiece text_tail) { + Print(text_head.data(), text_head.size()); + if (ConsumeInsertSilentMarker()) { + PrintLiteral(internal::kDebugStringSilentMarker); + } + Print(text_tail.data(), text_tail.size()); + } + + private: + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(TextGenerator); + + void Write(const char* data, size_t size) { + if (failed_) return; + if (size == 0) return; + + if (at_start_of_line_) { + // Insert an indent. + at_start_of_line_ = false; + WriteIndent(); + if (failed_) return; + } + + while (static_cast<int64_t>(size) > buffer_size_) { + // Data exceeds space in the buffer. Copy what we can and request a + // new buffer. + if (buffer_size_ > 0) { + memcpy(buffer_, data, buffer_size_); + data += buffer_size_; + size -= buffer_size_; + } + void* void_buffer = nullptr; + failed_ = !output_->Next(&void_buffer, &buffer_size_); + if (failed_) return; + buffer_ = reinterpret_cast<char*>(void_buffer); + } + + // Buffer is big enough to receive the data; copy it. + memcpy(buffer_, data, size); + buffer_ += size; + buffer_size_ -= size; + } + + void WriteIndent() { + if (indent_level_ == 0) { + return; + } + GOOGLE_DCHECK(!failed_); + int size = GetCurrentIndentationSize(); + + while (size > buffer_size_) { + // Data exceeds space in the buffer. Write what we can and request a new + // buffer. + if (buffer_size_ > 0) { + memset(buffer_, ' ', buffer_size_); + } + size -= buffer_size_; + void* void_buffer; + failed_ = !output_->Next(&void_buffer, &buffer_size_); + if (failed_) return; + buffer_ = reinterpret_cast<char*>(void_buffer); + } + + // Buffer is big enough to receive the data; copy it. + memset(buffer_, ' ', size); + buffer_ += size; + buffer_size_ -= size; + } + + // Return the current value of insert_silent_marker_. If it is true, set it + // to false as we assume that a silent marker is inserted after a call to this + // function. + bool ConsumeInsertSilentMarker() { + if (insert_silent_marker_) { + insert_silent_marker_ = false; + return true; + } + return false; + } + + io::ZeroCopyOutputStream* const output_; + char* buffer_; + int buffer_size_; + bool at_start_of_line_; + bool failed_; + // This flag is false when inserting silent marker is disabled or a silent + // marker has been inserted. + bool insert_silent_marker_; + + int indent_level_; + int initial_indent_level_; +}; + +// =========================================================================== +// An internal field value printer that may insert a silent marker in +// DebugStrings. +class TextFormat::Printer::DebugStringFieldValuePrinter + : public TextFormat::FastFieldValuePrinter { + public: + void PrintMessageStart(const Message& /*message*/, int /*field_index*/, + int /*field_count*/, bool single_line_mode, + BaseTextGenerator* generator) const override { + // This is safe as only TextGenerator is used with + // DebugStringFieldValuePrinter. + TextGenerator* text_generator = static_cast<TextGenerator*>(generator); + if (single_line_mode) { + text_generator->PrintMaybeWithMarker(" ", "{ "); + } else { + text_generator->PrintMaybeWithMarker(" ", "{\n"); + } + } +}; + +// =========================================================================== +// An internal field value printer that escape UTF8 strings. +class TextFormat::Printer::FastFieldValuePrinterUtf8Escaping + : public TextFormat::Printer::DebugStringFieldValuePrinter { + public: + void PrintString(const std::string& val, + TextFormat::BaseTextGenerator* generator) const override { + generator->PrintLiteral("\""); + generator->PrintString(strings::Utf8SafeCEscape(val)); + generator->PrintLiteral("\""); + } + void PrintBytes(const std::string& val, + TextFormat::BaseTextGenerator* generator) const override { + return FastFieldValuePrinter::PrintString(val, generator); + } +}; + +// =========================================================================== +// Implementation of the default Finder for extensions. +TextFormat::Finder::~Finder() {} + +const FieldDescriptor* TextFormat::Finder::FindExtension( + Message* message, const std::string& name) const { + return DefaultFinderFindExtension(message, name); +} + +const FieldDescriptor* TextFormat::Finder::FindExtensionByNumber( + const Descriptor* descriptor, int number) const { + return DefaultFinderFindExtensionByNumber(descriptor, number); +} + +const Descriptor* TextFormat::Finder::FindAnyType( + const Message& message, const std::string& prefix, + const std::string& name) const { + return DefaultFinderFindAnyType(message, prefix, name); +} + +MessageFactory* TextFormat::Finder::FindExtensionFactory( + const FieldDescriptor* /*field*/) const { + return nullptr; +} + +// =========================================================================== + +TextFormat::Parser::Parser() + : error_collector_(nullptr), + finder_(nullptr), + parse_info_tree_(nullptr), + allow_partial_(false), + allow_case_insensitive_field_(false), + allow_unknown_field_(false), + allow_unknown_extension_(false), + allow_unknown_enum_(false), + allow_field_number_(false), + allow_relaxed_whitespace_(false), + allow_singular_overwrites_(false), + recursion_limit_(std::numeric_limits<int>::max()) {} + +TextFormat::Parser::~Parser() {} + +namespace { + +bool CheckParseInputSize(StringPiece input, + io::ErrorCollector* error_collector) { + if (input.size() > INT_MAX) { + error_collector->AddError( + -1, 0, + StrCat( + "Input size too large: ", static_cast<int64_t>(input.size()), + " bytes", " > ", INT_MAX, " bytes.")); + return false; + } + return true; +} + +} // namespace + +bool TextFormat::Parser::Parse(io::ZeroCopyInputStream* input, + Message* output) { + output->Clear(); + + ParserImpl::SingularOverwritePolicy overwrites_policy = + allow_singular_overwrites_ ? ParserImpl::ALLOW_SINGULAR_OVERWRITES + : ParserImpl::FORBID_SINGULAR_OVERWRITES; + + ParserImpl parser(output->GetDescriptor(), input, error_collector_, finder_, + parse_info_tree_, overwrites_policy, + allow_case_insensitive_field_, allow_unknown_field_, + allow_unknown_extension_, allow_unknown_enum_, + allow_field_number_, allow_relaxed_whitespace_, + allow_partial_, recursion_limit_); + return MergeUsingImpl(input, output, &parser); +} + +bool TextFormat::Parser::ParseFromString(ConstStringParam input, + Message* output) { + DO(CheckParseInputSize(input, error_collector_)); + io::ArrayInputStream input_stream(input.data(), input.size()); + return Parse(&input_stream, output); +} + +bool TextFormat::Parser::Merge(io::ZeroCopyInputStream* input, + Message* output) { + ParserImpl parser(output->GetDescriptor(), input, error_collector_, finder_, + parse_info_tree_, ParserImpl::ALLOW_SINGULAR_OVERWRITES, + allow_case_insensitive_field_, allow_unknown_field_, + allow_unknown_extension_, allow_unknown_enum_, + allow_field_number_, allow_relaxed_whitespace_, + allow_partial_, recursion_limit_); + return MergeUsingImpl(input, output, &parser); +} + +bool TextFormat::Parser::MergeFromString(ConstStringParam input, + Message* output) { + DO(CheckParseInputSize(input, error_collector_)); + io::ArrayInputStream input_stream(input.data(), input.size()); + return Merge(&input_stream, output); +} + +bool TextFormat::Parser::MergeUsingImpl(io::ZeroCopyInputStream* /* input */, + Message* output, + ParserImpl* parser_impl) { + if (!parser_impl->Parse(output)) return false; + if (!allow_partial_ && !output->IsInitialized()) { + std::vector<std::string> missing_fields; + output->FindInitializationErrors(&missing_fields); + parser_impl->ReportError(-1, 0, + "Message missing required fields: " + + Join(missing_fields, ", ")); + return false; + } + return true; +} + +bool TextFormat::Parser::ParseFieldValueFromString(const std::string& input, + const FieldDescriptor* field, + Message* output) { + io::ArrayInputStream input_stream(input.data(), input.size()); + ParserImpl parser( + output->GetDescriptor(), &input_stream, error_collector_, finder_, + parse_info_tree_, ParserImpl::ALLOW_SINGULAR_OVERWRITES, + allow_case_insensitive_field_, allow_unknown_field_, + allow_unknown_extension_, allow_unknown_enum_, allow_field_number_, + allow_relaxed_whitespace_, allow_partial_, recursion_limit_); + return parser.ParseField(field, output); +} + +/* static */ bool TextFormat::Parse(io::ZeroCopyInputStream* input, + Message* output) { + return Parser().Parse(input, output); +} + +/* static */ bool TextFormat::Merge(io::ZeroCopyInputStream* input, + Message* output) { + return Parser().Merge(input, output); +} + +/* static */ bool TextFormat::ParseFromString(ConstStringParam input, + Message* output) { + return Parser().ParseFromString(input, output); +} + +/* static */ bool TextFormat::MergeFromString(ConstStringParam input, + Message* output) { + return Parser().MergeFromString(input, output); +} + +#undef DO + +// =========================================================================== + +TextFormat::BaseTextGenerator::~BaseTextGenerator() {} + +namespace { + +// A BaseTextGenerator that writes to a string. +class StringBaseTextGenerator : public TextFormat::BaseTextGenerator { + public: + void Print(const char* text, size_t size) override { + output_.append(text, size); + } + +// Some compilers do not support ref-qualifiers even in C++11 mode. +// Disable the optimization for now and revisit it later. +#if 0 // LANG_CXX11 + std::string Consume() && { return std::move(output_); } +#else // !LANG_CXX11 + const std::string& Get() { return output_; } +#endif // LANG_CXX11 + + private: + std::string output_; +}; + +} // namespace + +// The default implementation for FieldValuePrinter. We just delegate the +// implementation to the default FastFieldValuePrinter to avoid duplicating the +// logic. +TextFormat::FieldValuePrinter::FieldValuePrinter() {} +TextFormat::FieldValuePrinter::~FieldValuePrinter() {} + +#if 0 // LANG_CXX11 +#define FORWARD_IMPL(fn, ...) \ + StringBaseTextGenerator generator; \ + delegate_.fn(__VA_ARGS__, &generator); \ + return std::move(generator).Consume() +#else // !LANG_CXX11 +#define FORWARD_IMPL(fn, ...) \ + StringBaseTextGenerator generator; \ + delegate_.fn(__VA_ARGS__, &generator); \ + return generator.Get() +#endif // LANG_CXX11 + +std::string TextFormat::FieldValuePrinter::PrintBool(bool val) const { + FORWARD_IMPL(PrintBool, val); +} +std::string TextFormat::FieldValuePrinter::PrintInt32(int32_t val) const { + FORWARD_IMPL(PrintInt32, val); +} +std::string TextFormat::FieldValuePrinter::PrintUInt32(uint32_t val) const { + FORWARD_IMPL(PrintUInt32, val); +} +std::string TextFormat::FieldValuePrinter::PrintInt64(int64_t val) const { + FORWARD_IMPL(PrintInt64, val); +} +std::string TextFormat::FieldValuePrinter::PrintUInt64(uint64_t val) const { + FORWARD_IMPL(PrintUInt64, val); +} +std::string TextFormat::FieldValuePrinter::PrintFloat(float val) const { + FORWARD_IMPL(PrintFloat, val); +} +std::string TextFormat::FieldValuePrinter::PrintDouble(double val) const { + FORWARD_IMPL(PrintDouble, val); +} +std::string TextFormat::FieldValuePrinter::PrintString( + const std::string& val) const { + FORWARD_IMPL(PrintString, val); +} +std::string TextFormat::FieldValuePrinter::PrintBytes( + const std::string& val) const { + return PrintString(val); +} +std::string TextFormat::FieldValuePrinter::PrintEnum( + int32_t val, const std::string& name) const { + FORWARD_IMPL(PrintEnum, val, name); +} +std::string TextFormat::FieldValuePrinter::PrintFieldName( + const Message& message, const Reflection* reflection, + const FieldDescriptor* field) const { + FORWARD_IMPL(PrintFieldName, message, reflection, field); +} +std::string TextFormat::FieldValuePrinter::PrintMessageStart( + const Message& message, int field_index, int field_count, + bool single_line_mode) const { + FORWARD_IMPL(PrintMessageStart, message, field_index, field_count, + single_line_mode); +} +std::string TextFormat::FieldValuePrinter::PrintMessageEnd( + const Message& message, int field_index, int field_count, + bool single_line_mode) const { + FORWARD_IMPL(PrintMessageEnd, message, field_index, field_count, + single_line_mode); +} +#undef FORWARD_IMPL + +TextFormat::FastFieldValuePrinter::FastFieldValuePrinter() {} +TextFormat::FastFieldValuePrinter::~FastFieldValuePrinter() {} +void TextFormat::FastFieldValuePrinter::PrintBool( + bool val, BaseTextGenerator* generator) const { + if (val) { + generator->PrintLiteral("true"); + } else { + generator->PrintLiteral("false"); + } +} +void TextFormat::FastFieldValuePrinter::PrintInt32( + int32_t val, BaseTextGenerator* generator) const { + generator->PrintString(StrCat(val)); +} +void TextFormat::FastFieldValuePrinter::PrintUInt32( + uint32_t val, BaseTextGenerator* generator) const { + generator->PrintString(StrCat(val)); +} +void TextFormat::FastFieldValuePrinter::PrintInt64( + int64_t val, BaseTextGenerator* generator) const { + generator->PrintString(StrCat(val)); +} +void TextFormat::FastFieldValuePrinter::PrintUInt64( + uint64_t val, BaseTextGenerator* generator) const { + generator->PrintString(StrCat(val)); +} +void TextFormat::FastFieldValuePrinter::PrintFloat( + float val, BaseTextGenerator* generator) const { + generator->PrintString(!std::isnan(val) ? SimpleFtoa(val) : "nan"); +} +void TextFormat::FastFieldValuePrinter::PrintDouble( + double val, BaseTextGenerator* generator) const { + generator->PrintString(!std::isnan(val) ? SimpleDtoa(val) : "nan"); +} +void TextFormat::FastFieldValuePrinter::PrintEnum( + int32_t /*val*/, const std::string& name, + BaseTextGenerator* generator) const { + generator->PrintString(name); +} + +void TextFormat::FastFieldValuePrinter::PrintString( + const std::string& val, BaseTextGenerator* generator) const { + generator->PrintLiteral("\""); + generator->PrintString(CEscape(val)); + generator->PrintLiteral("\""); +} +void TextFormat::FastFieldValuePrinter::PrintBytes( + const std::string& val, BaseTextGenerator* generator) const { + PrintString(val, generator); +} +void TextFormat::FastFieldValuePrinter::PrintFieldName( + const Message& message, int /*field_index*/, int /*field_count*/, + const Reflection* reflection, const FieldDescriptor* field, + BaseTextGenerator* generator) const { + PrintFieldName(message, reflection, field, generator); +} +void TextFormat::FastFieldValuePrinter::PrintFieldName( + const Message& /*message*/, const Reflection* /*reflection*/, + const FieldDescriptor* field, BaseTextGenerator* generator) const { + if (field->is_extension()) { + generator->PrintLiteral("["); + generator->PrintString(field->PrintableNameForExtension()); + generator->PrintLiteral("]"); + } else if (field->type() == FieldDescriptor::TYPE_GROUP) { + // Groups must be serialized with their original capitalization. + generator->PrintString(field->message_type()->name()); + } else { + generator->PrintString(field->name()); + } +} +void TextFormat::FastFieldValuePrinter::PrintMessageStart( + const Message& /*message*/, int /*field_index*/, int /*field_count*/, + bool single_line_mode, BaseTextGenerator* generator) const { + if (single_line_mode) { + generator->PrintLiteral(" { "); + } else { + generator->PrintLiteral(" {\n"); + } +} +bool TextFormat::FastFieldValuePrinter::PrintMessageContent( + const Message& /*message*/, int /*field_index*/, int /*field_count*/, + bool /*single_line_mode*/, BaseTextGenerator* /*generator*/) const { + return false; // Use the default printing function. +} +void TextFormat::FastFieldValuePrinter::PrintMessageEnd( + const Message& /*message*/, int /*field_index*/, int /*field_count*/, + bool single_line_mode, BaseTextGenerator* generator) const { + if (single_line_mode) { + generator->PrintLiteral("} "); + } else { + generator->PrintLiteral("}\n"); + } +} + +namespace { + +// A legacy compatibility wrapper. Takes ownership of the delegate. +class FieldValuePrinterWrapper : public TextFormat::FastFieldValuePrinter { + public: + explicit FieldValuePrinterWrapper( + const TextFormat::FieldValuePrinter* delegate) + : delegate_(delegate) {} + + void SetDelegate(const TextFormat::FieldValuePrinter* delegate) { + delegate_.reset(delegate); + } + + void PrintBool(bool val, + TextFormat::BaseTextGenerator* generator) const override { + generator->PrintString(delegate_->PrintBool(val)); + } + void PrintInt32(int32_t val, + TextFormat::BaseTextGenerator* generator) const override { + generator->PrintString(delegate_->PrintInt32(val)); + } + void PrintUInt32(uint32_t val, + TextFormat::BaseTextGenerator* generator) const override { + generator->PrintString(delegate_->PrintUInt32(val)); + } + void PrintInt64(int64_t val, + TextFormat::BaseTextGenerator* generator) const override { + generator->PrintString(delegate_->PrintInt64(val)); + } + void PrintUInt64(uint64_t val, + TextFormat::BaseTextGenerator* generator) const override { + generator->PrintString(delegate_->PrintUInt64(val)); + } + void PrintFloat(float val, + TextFormat::BaseTextGenerator* generator) const override { + generator->PrintString(delegate_->PrintFloat(val)); + } + void PrintDouble(double val, + TextFormat::BaseTextGenerator* generator) const override { + generator->PrintString(delegate_->PrintDouble(val)); + } + void PrintString(const std::string& val, + TextFormat::BaseTextGenerator* generator) const override { + generator->PrintString(delegate_->PrintString(val)); + } + void PrintBytes(const std::string& val, + TextFormat::BaseTextGenerator* generator) const override { + generator->PrintString(delegate_->PrintBytes(val)); + } + void PrintEnum(int32_t val, const std::string& name, + TextFormat::BaseTextGenerator* generator) const override { + generator->PrintString(delegate_->PrintEnum(val, name)); + } + void PrintFieldName(const Message& message, int /*field_index*/, + int /*field_count*/, const Reflection* reflection, + const FieldDescriptor* field, + TextFormat::BaseTextGenerator* generator) const override { + generator->PrintString( + delegate_->PrintFieldName(message, reflection, field)); + } + void PrintFieldName(const Message& message, const Reflection* reflection, + const FieldDescriptor* field, + TextFormat::BaseTextGenerator* generator) const override { + generator->PrintString( + delegate_->PrintFieldName(message, reflection, field)); + } + void PrintMessageStart( + const Message& message, int field_index, int field_count, + bool single_line_mode, + TextFormat::BaseTextGenerator* generator) const override { + generator->PrintString(delegate_->PrintMessageStart( + message, field_index, field_count, single_line_mode)); + } + void PrintMessageEnd( + const Message& message, int field_index, int field_count, + bool single_line_mode, + TextFormat::BaseTextGenerator* generator) const override { + generator->PrintString(delegate_->PrintMessageEnd( + message, field_index, field_count, single_line_mode)); + } + + private: + std::unique_ptr<const TextFormat::FieldValuePrinter> delegate_; +}; + +} // namespace + +const char* const TextFormat::Printer::kDoNotParse = + "DO NOT PARSE: fields may be stripped and missing.\n"; + +TextFormat::Printer::Printer() + : initial_indent_level_(0), + single_line_mode_(false), + use_field_number_(false), + use_short_repeated_primitives_(false), + insert_silent_marker_(false), + hide_unknown_fields_(false), + print_message_fields_in_index_order_(false), + expand_any_(false), + truncate_string_field_longer_than_(0LL), + finder_(nullptr) { + SetUseUtf8StringEscaping(false); +} + +void TextFormat::Printer::SetUseUtf8StringEscaping(bool as_utf8) { + SetDefaultFieldValuePrinter(as_utf8 ? new FastFieldValuePrinterUtf8Escaping() + : new DebugStringFieldValuePrinter()); +} + +void TextFormat::Printer::SetDefaultFieldValuePrinter( + const FieldValuePrinter* printer) { + default_field_value_printer_.reset(new FieldValuePrinterWrapper(printer)); +} + +void TextFormat::Printer::SetDefaultFieldValuePrinter( + const FastFieldValuePrinter* printer) { + default_field_value_printer_.reset(printer); +} + +bool TextFormat::Printer::RegisterFieldValuePrinter( + const FieldDescriptor* field, const FieldValuePrinter* printer) { + if (field == nullptr || printer == nullptr) { + return false; + } + std::unique_ptr<FieldValuePrinterWrapper> wrapper( + new FieldValuePrinterWrapper(nullptr)); + auto pair = custom_printers_.insert(std::make_pair(field, nullptr)); + if (pair.second) { + wrapper->SetDelegate(printer); + pair.first->second = std::move(wrapper); + return true; + } else { + return false; + } +} + +bool TextFormat::Printer::RegisterFieldValuePrinter( + const FieldDescriptor* field, const FastFieldValuePrinter* printer) { + if (field == nullptr || printer == nullptr) { + return false; + } + auto pair = custom_printers_.insert(std::make_pair(field, nullptr)); + if (pair.second) { + pair.first->second.reset(printer); + return true; + } else { + return false; + } +} + +bool TextFormat::Printer::RegisterMessagePrinter( + const Descriptor* descriptor, const MessagePrinter* printer) { + if (descriptor == nullptr || printer == nullptr) { + return false; + } + auto pair = + custom_message_printers_.insert(std::make_pair(descriptor, nullptr)); + if (pair.second) { + pair.first->second.reset(printer); + return true; + } else { + return false; + } +} + +bool TextFormat::Printer::PrintToString(const Message& message, + std::string* output) const { + GOOGLE_DCHECK(output) << "output specified is nullptr"; + + output->clear(); + io::StringOutputStream output_stream(output); + + return Print(message, &output_stream); +} + +bool TextFormat::Printer::PrintUnknownFieldsToString( + const UnknownFieldSet& unknown_fields, std::string* output) const { + GOOGLE_DCHECK(output) << "output specified is nullptr"; + + output->clear(); + io::StringOutputStream output_stream(output); + return PrintUnknownFields(unknown_fields, &output_stream); +} + +bool TextFormat::Printer::Print(const Message& message, + io::ZeroCopyOutputStream* output) const { + TextGenerator generator(output, insert_silent_marker_, initial_indent_level_); + + Print(message, &generator); + + // Output false if the generator failed internally. + return !generator.failed(); +} + +// Maximum recursion depth for heuristically printing out length-delimited +// unknown fields as messages. +static constexpr int kUnknownFieldRecursionLimit = 10; + +bool TextFormat::Printer::PrintUnknownFields( + const UnknownFieldSet& unknown_fields, + io::ZeroCopyOutputStream* output) const { + TextGenerator generator(output, initial_indent_level_); + + PrintUnknownFields(unknown_fields, &generator, kUnknownFieldRecursionLimit); + + // Output false if the generator failed internally. + return !generator.failed(); +} + +namespace { +// Comparison functor for sorting FieldDescriptors by field index. +// Normal fields have higher precedence than extensions. +struct FieldIndexSorter { + bool operator()(const FieldDescriptor* left, + const FieldDescriptor* right) const { + if (left->is_extension() && right->is_extension()) { + return left->number() < right->number(); + } else if (left->is_extension()) { + return false; + } else if (right->is_extension()) { + return true; + } else { + return left->index() < right->index(); + } + } +}; + +} // namespace + +bool TextFormat::Printer::PrintAny(const Message& message, + TextGenerator* generator) const { + const FieldDescriptor* type_url_field; + const FieldDescriptor* value_field; + if (!internal::GetAnyFieldDescriptors(message, &type_url_field, + &value_field)) { + return false; + } + + const Reflection* reflection = message.GetReflection(); + + // Extract the full type name from the type_url field. + const std::string& type_url = reflection->GetString(message, type_url_field); + std::string url_prefix; + std::string full_type_name; + if (!internal::ParseAnyTypeUrl(type_url, &url_prefix, &full_type_name)) { + return false; + } + + // Print the "value" in text. + const Descriptor* value_descriptor = + finder_ ? finder_->FindAnyType(message, url_prefix, full_type_name) + : DefaultFinderFindAnyType(message, url_prefix, full_type_name); + if (value_descriptor == nullptr) { + GOOGLE_LOG(WARNING) << "Can't print proto content: proto type " << type_url + << " not found"; + return false; + } + DynamicMessageFactory factory; + std::unique_ptr<Message> value_message( + factory.GetPrototype(value_descriptor)->New()); + std::string serialized_value = reflection->GetString(message, value_field); + if (!value_message->ParseFromString(serialized_value)) { + GOOGLE_LOG(WARNING) << type_url << ": failed to parse contents"; + return false; + } + generator->PrintLiteral("["); + generator->PrintString(type_url); + generator->PrintLiteral("]"); + const FastFieldValuePrinter* printer = GetFieldPrinter(value_field); + printer->PrintMessageStart(message, -1, 0, single_line_mode_, generator); + generator->Indent(); + Print(*value_message, generator); + generator->Outdent(); + printer->PrintMessageEnd(message, -1, 0, single_line_mode_, generator); + return true; +} + +void TextFormat::Printer::Print(const Message& message, + TextGenerator* generator) const { + const Reflection* reflection = message.GetReflection(); + if (!reflection) { + // This message does not provide any way to describe its structure. + // Parse it again in an UnknownFieldSet, and display this instead. + UnknownFieldSet unknown_fields; + { + std::string serialized = message.SerializeAsString(); + io::ArrayInputStream input(serialized.data(), serialized.size()); + unknown_fields.ParseFromZeroCopyStream(&input); + } + PrintUnknownFields(unknown_fields, generator, kUnknownFieldRecursionLimit); + return; + } + const Descriptor* descriptor = message.GetDescriptor(); + auto itr = custom_message_printers_.find(descriptor); + if (itr != custom_message_printers_.end()) { + itr->second->Print(message, single_line_mode_, generator); + return; + } + if (descriptor->full_name() == internal::kAnyFullTypeName && expand_any_ && + PrintAny(message, generator)) { + return; + } + std::vector<const FieldDescriptor*> fields; + if (descriptor->options().map_entry()) { + fields.push_back(descriptor->field(0)); + fields.push_back(descriptor->field(1)); + } else { + reflection->ListFieldsOmitStripped(message, &fields); + if (reflection->IsMessageStripped(message.GetDescriptor())) { + generator->Print(kDoNotParse, std::strlen(kDoNotParse)); + } + } + + if (print_message_fields_in_index_order_) { + std::sort(fields.begin(), fields.end(), FieldIndexSorter()); + } + for (const FieldDescriptor* field : fields) { + PrintField(message, reflection, field, generator); + } + if (!hide_unknown_fields_) { + PrintUnknownFields(reflection->GetUnknownFields(message), generator, + kUnknownFieldRecursionLimit); + } +} + +void TextFormat::Printer::PrintFieldValueToString(const Message& message, + const FieldDescriptor* field, + int index, + std::string* output) const { + GOOGLE_DCHECK(output) << "output specified is nullptr"; + + output->clear(); + io::StringOutputStream output_stream(output); + TextGenerator generator(&output_stream, initial_indent_level_); + + PrintFieldValue(message, message.GetReflection(), field, index, &generator); +} + +class MapEntryMessageComparator { + public: + explicit MapEntryMessageComparator(const Descriptor* descriptor) + : field_(descriptor->field(0)) {} + + bool operator()(const Message* a, const Message* b) { + const Reflection* reflection = a->GetReflection(); + switch (field_->cpp_type()) { + case FieldDescriptor::CPPTYPE_BOOL: { + bool first = reflection->GetBool(*a, field_); + bool second = reflection->GetBool(*b, field_); + return first < second; + } + case FieldDescriptor::CPPTYPE_INT32: { + int32_t first = reflection->GetInt32(*a, field_); + int32_t second = reflection->GetInt32(*b, field_); + return first < second; + } + case FieldDescriptor::CPPTYPE_INT64: { + int64_t first = reflection->GetInt64(*a, field_); + int64_t second = reflection->GetInt64(*b, field_); + return first < second; + } + case FieldDescriptor::CPPTYPE_UINT32: { + uint32_t first = reflection->GetUInt32(*a, field_); + uint32_t second = reflection->GetUInt32(*b, field_); + return first < second; + } + case FieldDescriptor::CPPTYPE_UINT64: { + uint64_t first = reflection->GetUInt64(*a, field_); + uint64_t second = reflection->GetUInt64(*b, field_); + return first < second; + } + case FieldDescriptor::CPPTYPE_STRING: { + std::string first = reflection->GetString(*a, field_); + std::string second = reflection->GetString(*b, field_); + return first < second; + } + default: + GOOGLE_LOG(DFATAL) << "Invalid key for map field."; + return true; + } + } + + private: + const FieldDescriptor* field_; +}; + +namespace internal { +class MapFieldPrinterHelper { + public: + // DynamicMapSorter::Sort cannot be used because it enfores syncing with + // repeated field. + static bool SortMap(const Message& message, const Reflection* reflection, + const FieldDescriptor* field, + std::vector<const Message*>* sorted_map_field); + static void CopyKey(const MapKey& key, Message* message, + const FieldDescriptor* field_desc); + static void CopyValue(const MapValueRef& value, Message* message, + const FieldDescriptor* field_desc); +}; + +// Returns true if elements contained in sorted_map_field need to be released. +bool MapFieldPrinterHelper::SortMap( + const Message& message, const Reflection* reflection, + const FieldDescriptor* field, + std::vector<const Message*>* sorted_map_field) { + bool need_release = false; + const MapFieldBase& base = *reflection->GetMapData(message, field); + + if (base.IsRepeatedFieldValid()) { + const RepeatedPtrField<Message>& map_field = + reflection->GetRepeatedPtrFieldInternal<Message>(message, field); + for (int i = 0; i < map_field.size(); ++i) { + sorted_map_field->push_back( + const_cast<RepeatedPtrField<Message>*>(&map_field)->Mutable(i)); + } + } else { + // TODO(teboring): For performance, instead of creating map entry message + // for each element, just store map keys and sort them. + const Descriptor* map_entry_desc = field->message_type(); + const Message* prototype = + reflection->GetMessageFactory()->GetPrototype(map_entry_desc); + for (MapIterator iter = + reflection->MapBegin(const_cast<Message*>(&message), field); + iter != reflection->MapEnd(const_cast<Message*>(&message), field); + ++iter) { + Message* map_entry_message = prototype->New(); + CopyKey(iter.GetKey(), map_entry_message, map_entry_desc->field(0)); + CopyValue(iter.GetValueRef(), map_entry_message, + map_entry_desc->field(1)); + sorted_map_field->push_back(map_entry_message); + } + need_release = true; + } + + MapEntryMessageComparator comparator(field->message_type()); + std::stable_sort(sorted_map_field->begin(), sorted_map_field->end(), + comparator); + return need_release; +} + +void MapFieldPrinterHelper::CopyKey(const MapKey& key, Message* message, + const FieldDescriptor* field_desc) { + const Reflection* reflection = message->GetReflection(); + switch (field_desc->cpp_type()) { + case FieldDescriptor::CPPTYPE_DOUBLE: + case FieldDescriptor::CPPTYPE_FLOAT: + case FieldDescriptor::CPPTYPE_ENUM: + case FieldDescriptor::CPPTYPE_MESSAGE: + GOOGLE_LOG(ERROR) << "Not supported."; + break; + case FieldDescriptor::CPPTYPE_STRING: + reflection->SetString(message, field_desc, key.GetStringValue()); + return; + case FieldDescriptor::CPPTYPE_INT64: + reflection->SetInt64(message, field_desc, key.GetInt64Value()); + return; + case FieldDescriptor::CPPTYPE_INT32: + reflection->SetInt32(message, field_desc, key.GetInt32Value()); + return; + case FieldDescriptor::CPPTYPE_UINT64: + reflection->SetUInt64(message, field_desc, key.GetUInt64Value()); + return; + case FieldDescriptor::CPPTYPE_UINT32: + reflection->SetUInt32(message, field_desc, key.GetUInt32Value()); + return; + case FieldDescriptor::CPPTYPE_BOOL: + reflection->SetBool(message, field_desc, key.GetBoolValue()); + return; + } +} + +void MapFieldPrinterHelper::CopyValue(const MapValueRef& value, + Message* message, + const FieldDescriptor* field_desc) { + const Reflection* reflection = message->GetReflection(); + switch (field_desc->cpp_type()) { + case FieldDescriptor::CPPTYPE_DOUBLE: + reflection->SetDouble(message, field_desc, value.GetDoubleValue()); + return; + case FieldDescriptor::CPPTYPE_FLOAT: + reflection->SetFloat(message, field_desc, value.GetFloatValue()); + return; + case FieldDescriptor::CPPTYPE_ENUM: + reflection->SetEnumValue(message, field_desc, value.GetEnumValue()); + return; + case FieldDescriptor::CPPTYPE_MESSAGE: { + Message* sub_message = value.GetMessageValue().New(); + sub_message->CopyFrom(value.GetMessageValue()); + reflection->SetAllocatedMessage(message, sub_message, field_desc); + return; + } + case FieldDescriptor::CPPTYPE_STRING: + reflection->SetString(message, field_desc, value.GetStringValue()); + return; + case FieldDescriptor::CPPTYPE_INT64: + reflection->SetInt64(message, field_desc, value.GetInt64Value()); + return; + case FieldDescriptor::CPPTYPE_INT32: + reflection->SetInt32(message, field_desc, value.GetInt32Value()); + return; + case FieldDescriptor::CPPTYPE_UINT64: + reflection->SetUInt64(message, field_desc, value.GetUInt64Value()); + return; + case FieldDescriptor::CPPTYPE_UINT32: + reflection->SetUInt32(message, field_desc, value.GetUInt32Value()); + return; + case FieldDescriptor::CPPTYPE_BOOL: + reflection->SetBool(message, field_desc, value.GetBoolValue()); + return; + } +} +} // namespace internal + +void TextFormat::Printer::PrintField(const Message& message, + const Reflection* reflection, + const FieldDescriptor* field, + TextGenerator* generator) const { + if (use_short_repeated_primitives_ && field->is_repeated() && + field->cpp_type() != FieldDescriptor::CPPTYPE_STRING && + field->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE) { + PrintShortRepeatedField(message, reflection, field, generator); + return; + } + + int count = 0; + + if (field->is_repeated()) { + count = reflection->FieldSize(message, field); + } else if (reflection->HasField(message, field) || + field->containing_type()->options().map_entry()) { + count = 1; + } + + std::vector<const Message*> sorted_map_field; + bool need_release = false; + bool is_map = field->is_map(); + if (is_map) { + need_release = internal::MapFieldPrinterHelper::SortMap( + message, reflection, field, &sorted_map_field); + } + + for (int j = 0; j < count; ++j) { + const int field_index = field->is_repeated() ? j : -1; + + PrintFieldName(message, field_index, count, reflection, field, generator); + + if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { + const FastFieldValuePrinter* printer = GetFieldPrinter(field); + const Message& sub_message = + field->is_repeated() + ? (is_map ? *sorted_map_field[j] + : reflection->GetRepeatedMessage(message, field, j)) + : reflection->GetMessage(message, field); + printer->PrintMessageStart(sub_message, field_index, count, + single_line_mode_, generator); + generator->Indent(); + if (!printer->PrintMessageContent(sub_message, field_index, count, + single_line_mode_, generator)) { + Print(sub_message, generator); + } + generator->Outdent(); + printer->PrintMessageEnd(sub_message, field_index, count, + single_line_mode_, generator); + } else { + generator->PrintMaybeWithMarker(": "); + // Write the field value. + PrintFieldValue(message, reflection, field, field_index, generator); + if (single_line_mode_) { + generator->PrintLiteral(" "); + } else { + generator->PrintLiteral("\n"); + } + } + } + + if (need_release) { + for (const Message* message_to_delete : sorted_map_field) { + delete message_to_delete; + } + } +} + +void TextFormat::Printer::PrintShortRepeatedField( + const Message& message, const Reflection* reflection, + const FieldDescriptor* field, TextGenerator* generator) const { + // Print primitive repeated field in short form. + int size = reflection->FieldSize(message, field); + PrintFieldName(message, /*field_index=*/-1, /*field_count=*/size, reflection, + field, generator); + generator->PrintMaybeWithMarker(": ", "["); + for (int i = 0; i < size; i++) { + if (i > 0) generator->PrintLiteral(", "); + PrintFieldValue(message, reflection, field, i, generator); + } + if (single_line_mode_) { + generator->PrintLiteral("] "); + } else { + generator->PrintLiteral("]\n"); + } +} + +void TextFormat::Printer::PrintFieldName(const Message& message, + int field_index, int field_count, + const Reflection* reflection, + const FieldDescriptor* field, + TextGenerator* generator) const { + // if use_field_number_ is true, prints field number instead + // of field name. + if (use_field_number_) { + generator->PrintString(StrCat(field->number())); + return; + } + + const FastFieldValuePrinter* printer = GetFieldPrinter(field); + printer->PrintFieldName(message, field_index, field_count, reflection, field, + generator); +} + +void TextFormat::Printer::PrintFieldValue(const Message& message, + const Reflection* reflection, + const FieldDescriptor* field, + int index, + TextGenerator* generator) const { + GOOGLE_DCHECK(field->is_repeated() || (index == -1)) + << "Index must be -1 for non-repeated fields"; + + const FastFieldValuePrinter* printer = GetFieldPrinter(field); + + switch (field->cpp_type()) { +#define OUTPUT_FIELD(CPPTYPE, METHOD) \ + case FieldDescriptor::CPPTYPE_##CPPTYPE: \ + printer->Print##METHOD( \ + field->is_repeated() \ + ? reflection->GetRepeated##METHOD(message, field, index) \ + : reflection->Get##METHOD(message, field), \ + generator); \ + break + + OUTPUT_FIELD(INT32, Int32); + OUTPUT_FIELD(INT64, Int64); + OUTPUT_FIELD(UINT32, UInt32); + OUTPUT_FIELD(UINT64, UInt64); + OUTPUT_FIELD(FLOAT, Float); + OUTPUT_FIELD(DOUBLE, Double); + OUTPUT_FIELD(BOOL, Bool); +#undef OUTPUT_FIELD + + case FieldDescriptor::CPPTYPE_STRING: { + std::string scratch; + const std::string& value = + field->is_repeated() + ? reflection->GetRepeatedStringReference(message, field, index, + &scratch) + : reflection->GetStringReference(message, field, &scratch); + const std::string* value_to_print = &value; + std::string truncated_value; + if (truncate_string_field_longer_than_ > 0 && + static_cast<size_t>(truncate_string_field_longer_than_) < + value.size()) { + truncated_value = value.substr(0, truncate_string_field_longer_than_) + + "...<truncated>..."; + value_to_print = &truncated_value; + } + if (field->type() == FieldDescriptor::TYPE_STRING) { + printer->PrintString(*value_to_print, generator); + } else { + GOOGLE_DCHECK_EQ(field->type(), FieldDescriptor::TYPE_BYTES); + printer->PrintBytes(*value_to_print, generator); + } + break; + } + + case FieldDescriptor::CPPTYPE_ENUM: { + int enum_value = + field->is_repeated() + ? reflection->GetRepeatedEnumValue(message, field, index) + : reflection->GetEnumValue(message, field); + const EnumValueDescriptor* enum_desc = + field->enum_type()->FindValueByNumber(enum_value); + if (enum_desc != nullptr) { + printer->PrintEnum(enum_value, enum_desc->name(), generator); + } else { + // Ordinarily, enum_desc should not be null, because proto2 has the + // invariant that set enum field values must be in-range, but with the + // new integer-based API for enums (or the RepeatedField<int> loophole), + // it is possible for the user to force an unknown integer value. So we + // simply use the integer value itself as the enum value name in this + // case. + printer->PrintEnum(enum_value, StrCat(enum_value), generator); + } + break; + } + + case FieldDescriptor::CPPTYPE_MESSAGE: + Print(field->is_repeated() + ? reflection->GetRepeatedMessage(message, field, index) + : reflection->GetMessage(message, field), + generator); + break; + } +} + +/* static */ bool TextFormat::Print(const Message& message, + io::ZeroCopyOutputStream* output) { + return Printer().Print(message, output); +} + +/* static */ bool TextFormat::PrintUnknownFields( + const UnknownFieldSet& unknown_fields, io::ZeroCopyOutputStream* output) { + return Printer().PrintUnknownFields(unknown_fields, output); +} + +/* static */ bool TextFormat::PrintToString(const Message& message, + std::string* output) { + return Printer().PrintToString(message, output); +} + +/* static */ bool TextFormat::PrintUnknownFieldsToString( + const UnknownFieldSet& unknown_fields, std::string* output) { + return Printer().PrintUnknownFieldsToString(unknown_fields, output); +} + +/* static */ void TextFormat::PrintFieldValueToString( + const Message& message, const FieldDescriptor* field, int index, + std::string* output) { + return Printer().PrintFieldValueToString(message, field, index, output); +} + +/* static */ bool TextFormat::ParseFieldValueFromString( + const std::string& input, const FieldDescriptor* field, Message* message) { + return Parser().ParseFieldValueFromString(input, field, message); +} + +void TextFormat::Printer::PrintUnknownFields( + const UnknownFieldSet& unknown_fields, TextGenerator* generator, + int recursion_budget) const { + for (int i = 0; i < unknown_fields.field_count(); i++) { + const UnknownField& field = unknown_fields.field(i); + std::string field_number = StrCat(field.number()); + + switch (field.type()) { + case UnknownField::TYPE_VARINT: + generator->PrintString(field_number); + generator->PrintMaybeWithMarker(": "); + generator->PrintString(StrCat(field.varint())); + if (single_line_mode_) { + generator->PrintLiteral(" "); + } else { + generator->PrintLiteral("\n"); + } + break; + case UnknownField::TYPE_FIXED32: { + generator->PrintString(field_number); + generator->PrintMaybeWithMarker(": ", "0x"); + generator->PrintString( + StrCat(strings::Hex(field.fixed32(), strings::ZERO_PAD_8))); + if (single_line_mode_) { + generator->PrintLiteral(" "); + } else { + generator->PrintLiteral("\n"); + } + break; + } + case UnknownField::TYPE_FIXED64: { + generator->PrintString(field_number); + generator->PrintMaybeWithMarker(": ", "0x"); + generator->PrintString( + StrCat(strings::Hex(field.fixed64(), strings::ZERO_PAD_16))); + if (single_line_mode_) { + generator->PrintLiteral(" "); + } else { + generator->PrintLiteral("\n"); + } + break; + } + case UnknownField::TYPE_LENGTH_DELIMITED: { + generator->PrintString(field_number); + const std::string& value = field.length_delimited(); + // We create a CodedInputStream so that we can adhere to our recursion + // budget when we attempt to parse the data. UnknownFieldSet parsing is + // recursive because of groups. + io::CodedInputStream input_stream( + reinterpret_cast<const uint8_t*>(value.data()), value.size()); + input_stream.SetRecursionLimit(recursion_budget); + UnknownFieldSet embedded_unknown_fields; + if (!value.empty() && recursion_budget > 0 && + embedded_unknown_fields.ParseFromCodedStream(&input_stream)) { + // This field is parseable as a Message. + // So it is probably an embedded message. + if (single_line_mode_) { + generator->PrintMaybeWithMarker(" ", "{ "); + } else { + generator->PrintMaybeWithMarker(" ", "{\n"); + generator->Indent(); + } + PrintUnknownFields(embedded_unknown_fields, generator, + recursion_budget - 1); + if (single_line_mode_) { + generator->PrintLiteral("} "); + } else { + generator->Outdent(); + generator->PrintLiteral("}\n"); + } + } else { + // This field is not parseable as a Message (or we ran out of + // recursion budget). So it is probably just a plain string. + generator->PrintMaybeWithMarker(": ", "\""); + generator->PrintString(CEscape(value)); + if (single_line_mode_) { + generator->PrintLiteral("\" "); + } else { + generator->PrintLiteral("\"\n"); + } + } + break; + } + case UnknownField::TYPE_GROUP: + generator->PrintString(field_number); + if (single_line_mode_) { + generator->PrintMaybeWithMarker(" ", "{ "); + } else { + generator->PrintMaybeWithMarker(" ", "{\n"); + generator->Indent(); + } + // For groups, we recurse without checking the budget. This is OK, + // because if the groups were too deeply nested then we would have + // already rejected the message when we originally parsed it. + PrintUnknownFields(field.group(), generator, recursion_budget - 1); + if (single_line_mode_) { + generator->PrintLiteral("} "); + } else { + generator->Outdent(); + generator->PrintLiteral("}\n"); + } + break; + } + } +} + +} // namespace protobuf +} // namespace google + +#include <google/protobuf/port_undef.inc> diff --git a/toolkit/components/protobuf/src/google/protobuf/text_format.h b/toolkit/components/protobuf/src/google/protobuf/text_format.h new file mode 100644 index 0000000000..e10bef7ddf --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/text_format.h @@ -0,0 +1,693 @@ +// 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. + +// Author: jschorr@google.com (Joseph Schorr) +// Based on original Protocol Buffers design by +// Sanjay Ghemawat, Jeff Dean, and others. +// +// Utilities for printing and parsing protocol messages in a human-readable, +// text-based format. + +#ifndef GOOGLE_PROTOBUF_TEXT_FORMAT_H__ +#define GOOGLE_PROTOBUF_TEXT_FORMAT_H__ + + +#include <map> +#include <memory> +#include <string> +#include <vector> + +#include <google/protobuf/stubs/common.h> +#include <google/protobuf/port.h> +#include <google/protobuf/descriptor.h> +#include <google/protobuf/message.h> +#include <google/protobuf/message_lite.h> + +// Must be included last. +#include <google/protobuf/port_def.inc> + +#ifdef SWIG +#error "You cannot SWIG proto headers" +#endif + +namespace google { +namespace protobuf { + +namespace internal { +PROTOBUF_EXPORT extern const char kDebugStringSilentMarker[1]; +PROTOBUF_EXPORT extern const char kDebugStringSilentMarkerForDetection[3]; +} // namespace internal + +namespace io { +class ErrorCollector; // tokenizer.h +} + +// This class implements protocol buffer text format, colloquially known as text +// proto. Printing and parsing protocol messages in text format is useful for +// debugging and human editing of messages. +// +// This class is really a namespace that contains only static methods. +class PROTOBUF_EXPORT TextFormat { + public: + // Outputs a textual representation of the given message to the given + // output stream. Returns false if printing fails. + static bool Print(const Message& message, io::ZeroCopyOutputStream* output); + + // Print the fields in an UnknownFieldSet. They are printed by tag number + // only. Embedded messages are heuristically identified by attempting to + // parse them. Returns false if printing fails. + static bool PrintUnknownFields(const UnknownFieldSet& unknown_fields, + io::ZeroCopyOutputStream* output); + + // Like Print(), but outputs directly to a string. + // Note: output will be cleared prior to printing, and will be left empty + // even if printing fails. Returns false if printing fails. + static bool PrintToString(const Message& message, std::string* output); + + // Like PrintUnknownFields(), but outputs directly to a string. Returns + // false if printing fails. + static bool PrintUnknownFieldsToString(const UnknownFieldSet& unknown_fields, + std::string* output); + + // Outputs a textual representation of the value of the field supplied on + // the message supplied. For non-repeated fields, an index of -1 must + // be supplied. Note that this method will print the default value for a + // field if it is not set. + static void PrintFieldValueToString(const Message& message, + const FieldDescriptor* field, int index, + std::string* output); + + class PROTOBUF_EXPORT BaseTextGenerator { + public: + virtual ~BaseTextGenerator(); + + virtual void Indent() {} + virtual void Outdent() {} + // Returns the current indentation size in characters. + virtual size_t GetCurrentIndentationSize() const { return 0; } + + // Print text to the output stream. + virtual void Print(const char* text, size_t size) = 0; + + void PrintString(const std::string& str) { Print(str.data(), str.size()); } + + template <size_t n> + void PrintLiteral(const char (&text)[n]) { + Print(text, n - 1); // n includes the terminating zero character. + } + }; + + // The default printer that converts scalar values from fields into their + // string representation. + // You can derive from this FastFieldValuePrinter if you want to have fields + // to be printed in a different way and register it at the Printer. + class PROTOBUF_EXPORT FastFieldValuePrinter { + public: + FastFieldValuePrinter(); + virtual ~FastFieldValuePrinter(); + virtual void PrintBool(bool val, BaseTextGenerator* generator) const; + virtual void PrintInt32(int32_t val, BaseTextGenerator* generator) const; + virtual void PrintUInt32(uint32_t val, BaseTextGenerator* generator) const; + virtual void PrintInt64(int64_t val, BaseTextGenerator* generator) const; + virtual void PrintUInt64(uint64_t val, BaseTextGenerator* generator) const; + virtual void PrintFloat(float val, BaseTextGenerator* generator) const; + virtual void PrintDouble(double val, BaseTextGenerator* generator) const; + virtual void PrintString(const std::string& val, + BaseTextGenerator* generator) const; + virtual void PrintBytes(const std::string& val, + BaseTextGenerator* generator) const; + virtual void PrintEnum(int32_t val, const std::string& name, + BaseTextGenerator* generator) const; + virtual void PrintFieldName(const Message& message, int field_index, + int field_count, const Reflection* reflection, + const FieldDescriptor* field, + BaseTextGenerator* generator) const; + virtual void PrintFieldName(const Message& message, + const Reflection* reflection, + const FieldDescriptor* field, + BaseTextGenerator* generator) const; + virtual void PrintMessageStart(const Message& message, int field_index, + int field_count, bool single_line_mode, + BaseTextGenerator* generator) const; + // Allows to override the logic on how to print the content of a message. + // Return false to use the default printing logic. Note that it is legal for + // this function to print something and then return false to use the default + // content printing (although at that point it would behave similarly to + // PrintMessageStart). + virtual bool PrintMessageContent(const Message& message, int field_index, + int field_count, bool single_line_mode, + BaseTextGenerator* generator) const; + virtual void PrintMessageEnd(const Message& message, int field_index, + int field_count, bool single_line_mode, + BaseTextGenerator* generator) const; + + private: + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FastFieldValuePrinter); + }; + + // Deprecated: please use FastFieldValuePrinter instead. + class PROTOBUF_EXPORT FieldValuePrinter { + public: + FieldValuePrinter(); + virtual ~FieldValuePrinter(); + virtual std::string PrintBool(bool val) const; + virtual std::string PrintInt32(int32_t val) const; + virtual std::string PrintUInt32(uint32_t val) const; + virtual std::string PrintInt64(int64_t val) const; + virtual std::string PrintUInt64(uint64_t val) const; + virtual std::string PrintFloat(float val) const; + virtual std::string PrintDouble(double val) const; + virtual std::string PrintString(const std::string& val) const; + virtual std::string PrintBytes(const std::string& val) const; + virtual std::string PrintEnum(int32_t val, const std::string& name) const; + virtual std::string PrintFieldName(const Message& message, + const Reflection* reflection, + const FieldDescriptor* field) const; + virtual std::string PrintMessageStart(const Message& message, + int field_index, int field_count, + bool single_line_mode) const; + virtual std::string PrintMessageEnd(const Message& message, int field_index, + int field_count, + bool single_line_mode) const; + + private: + FastFieldValuePrinter delegate_; + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FieldValuePrinter); + }; + + class PROTOBUF_EXPORT MessagePrinter { + public: + MessagePrinter() {} + virtual ~MessagePrinter() {} + virtual void Print(const Message& message, bool single_line_mode, + BaseTextGenerator* generator) const = 0; + + private: + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessagePrinter); + }; + + // Interface that Printers or Parsers can use to find extensions, or types + // referenced in Any messages. + class PROTOBUF_EXPORT Finder { + public: + virtual ~Finder(); + + // Try to find an extension of *message by fully-qualified field + // name. Returns nullptr if no extension is known for this name or number. + // The base implementation uses the extensions already known by the message. + virtual const FieldDescriptor* FindExtension(Message* message, + const std::string& name) const; + + // Similar to FindExtension, but uses a Descriptor and the extension number + // instead of using a Message and the name when doing the look up. + virtual const FieldDescriptor* FindExtensionByNumber( + const Descriptor* descriptor, int number) const; + + // Find the message type for an Any proto. + // Returns nullptr if no message is known for this name. + // The base implementation only accepts prefixes of type.googleprod.com/ or + // type.googleapis.com/, and searches the DescriptorPool of the parent + // message. + virtual const Descriptor* FindAnyType(const Message& message, + const std::string& prefix, + const std::string& name) const; + + // Find the message factory for the given extension field. This can be used + // to generalize the Parser to add extension fields to a message in the same + // way as the "input" message for the Parser. + virtual MessageFactory* FindExtensionFactory( + const FieldDescriptor* field) const; + }; + + // Class for those users which require more fine-grained control over how + // a protobuffer message is printed out. + class PROTOBUF_EXPORT Printer { + public: + Printer(); + + // Like TextFormat::Print + bool Print(const Message& message, io::ZeroCopyOutputStream* output) const; + // Like TextFormat::PrintUnknownFields + bool PrintUnknownFields(const UnknownFieldSet& unknown_fields, + io::ZeroCopyOutputStream* output) const; + // Like TextFormat::PrintToString + bool PrintToString(const Message& message, std::string* output) const; + // Like TextFormat::PrintUnknownFieldsToString + bool PrintUnknownFieldsToString(const UnknownFieldSet& unknown_fields, + std::string* output) const; + // Like TextFormat::PrintFieldValueToString + void PrintFieldValueToString(const Message& message, + const FieldDescriptor* field, int index, + std::string* output) const; + + // Adjust the initial indent level of all output. Each indent level is + // equal to two spaces. + void SetInitialIndentLevel(int indent_level) { + initial_indent_level_ = indent_level; + } + + // If printing in single line mode, then the entire message will be output + // on a single line with no line breaks. + void SetSingleLineMode(bool single_line_mode) { + single_line_mode_ = single_line_mode; + } + + bool IsInSingleLineMode() const { return single_line_mode_; } + + // If use_field_number is true, uses field number instead of field name. + void SetUseFieldNumber(bool use_field_number) { + use_field_number_ = use_field_number; + } + + // Set true to print repeated primitives in a format like: + // field_name: [1, 2, 3, 4] + // instead of printing each value on its own line. Short format applies + // only to primitive values -- i.e. everything except strings and + // sub-messages/groups. + void SetUseShortRepeatedPrimitives(bool use_short_repeated_primitives) { + use_short_repeated_primitives_ = use_short_repeated_primitives; + } + + // Set true to output UTF-8 instead of ASCII. The only difference + // is that bytes >= 0x80 in string fields will not be escaped, + // because they are assumed to be part of UTF-8 multi-byte + // sequences. This will change the default FastFieldValuePrinter. + void SetUseUtf8StringEscaping(bool as_utf8); + + // Set the default FastFieldValuePrinter that is used for all fields that + // don't have a field-specific printer registered. + // Takes ownership of the printer. + void SetDefaultFieldValuePrinter(const FastFieldValuePrinter* printer); + + PROTOBUF_DEPRECATED_MSG("Please use FastFieldValuePrinter") + void SetDefaultFieldValuePrinter(const FieldValuePrinter* printer); + + // Sets whether we want to hide unknown fields or not. + // Usually unknown fields are printed in a generic way that includes the + // tag number of the field instead of field name. However, sometimes it + // is useful to be able to print the message without unknown fields (e.g. + // for the python protobuf version to maintain consistency between its pure + // python and c++ implementations). + void SetHideUnknownFields(bool hide) { hide_unknown_fields_ = hide; } + + // If print_message_fields_in_index_order is true, fields of a proto message + // will be printed using the order defined in source code instead of the + // field number, extensions will be printed at the end of the message + // and their relative order is determined by the extension number. + // By default, use the field number order. + void SetPrintMessageFieldsInIndexOrder( + bool print_message_fields_in_index_order) { + print_message_fields_in_index_order_ = + print_message_fields_in_index_order; + } + + // If expand==true, expand google.protobuf.Any payloads. The output + // will be of form + // [type_url] { <value_printed_in_text> } + // + // If expand==false, print Any using the default printer. The output will + // look like + // type_url: "<type_url>" value: "serialized_content" + void SetExpandAny(bool expand) { expand_any_ = expand; } + + // Set how parser finds message for Any payloads. + void SetFinder(const Finder* finder) { finder_ = finder; } + + // If non-zero, we truncate all string fields that are longer than + // this threshold. This is useful when the proto message has very long + // strings, e.g., dump of encoded image file. + // + // NOTE(hfgong): Setting a non-zero value breaks round-trip safe + // property of TextFormat::Printer. That is, from the printed message, we + // cannot fully recover the original string field any more. + void SetTruncateStringFieldLongerThan( + const int64_t truncate_string_field_longer_than) { + truncate_string_field_longer_than_ = truncate_string_field_longer_than; + } + + // Register a custom field-specific FastFieldValuePrinter for fields + // with a particular FieldDescriptor. + // Returns "true" if the registration succeeded, or "false", if there is + // already a printer for that FieldDescriptor. + // Takes ownership of the printer on successful registration. + bool RegisterFieldValuePrinter(const FieldDescriptor* field, + const FastFieldValuePrinter* printer); + + PROTOBUF_DEPRECATED_MSG("Please use FastFieldValuePrinter") + bool RegisterFieldValuePrinter(const FieldDescriptor* field, + const FieldValuePrinter* printer); + + // Register a custom message-specific MessagePrinter for messages with a + // particular Descriptor. + // Returns "true" if the registration succeeded, or "false" if there is + // already a printer for that Descriptor. + bool RegisterMessagePrinter(const Descriptor* descriptor, + const MessagePrinter* printer); + + private: + friend std::string Message::DebugString() const; + friend std::string Message::ShortDebugString() const; + friend std::string Message::Utf8DebugString() const; + + // Sets whether *DebugString should insert a silent marker. + void SetInsertSilentMarker(bool v) { insert_silent_marker_ = v; } + + // Forward declaration of an internal class used to print the text + // output to the OutputStream (see text_format.cc for implementation). + class TextGenerator; + + // Forward declaration of an internal class used to print field values for + // DebugString APIs (see text_format.cc for implementation). + class DebugStringFieldValuePrinter; + + // Forward declaration of an internal class used to print UTF-8 escaped + // strings (see text_format.cc for implementation). + class FastFieldValuePrinterUtf8Escaping; + + static const char* const kDoNotParse; + + // Internal Print method, used for writing to the OutputStream via + // the TextGenerator class. + void Print(const Message& message, TextGenerator* generator) const; + + // Print a single field. + void PrintField(const Message& message, const Reflection* reflection, + const FieldDescriptor* field, + TextGenerator* generator) const; + + // Print a repeated primitive field in short form. + void PrintShortRepeatedField(const Message& message, + const Reflection* reflection, + const FieldDescriptor* field, + TextGenerator* generator) const; + + // Print the name of a field -- i.e. everything that comes before the + // ':' for a single name/value pair. + void PrintFieldName(const Message& message, int field_index, + int field_count, const Reflection* reflection, + const FieldDescriptor* field, + TextGenerator* generator) const; + + // Outputs a textual representation of the value of the field supplied on + // the message supplied or the default value if not set. + void PrintFieldValue(const Message& message, const Reflection* reflection, + const FieldDescriptor* field, int index, + TextGenerator* generator) const; + + // Print the fields in an UnknownFieldSet. They are printed by tag number + // only. Embedded messages are heuristically identified by attempting to + // parse them (subject to the recursion budget). + void PrintUnknownFields(const UnknownFieldSet& unknown_fields, + TextGenerator* generator, + int recursion_budget) const; + + bool PrintAny(const Message& message, TextGenerator* generator) const; + + const FastFieldValuePrinter* GetFieldPrinter( + const FieldDescriptor* field) const { + auto it = custom_printers_.find(field); + return it == custom_printers_.end() ? default_field_value_printer_.get() + : it->second.get(); + } + + int initial_indent_level_; + bool single_line_mode_; + bool use_field_number_; + bool use_short_repeated_primitives_; + bool insert_silent_marker_; + bool hide_unknown_fields_; + bool print_message_fields_in_index_order_; + bool expand_any_; + int64_t truncate_string_field_longer_than_; + + std::unique_ptr<const FastFieldValuePrinter> default_field_value_printer_; + typedef std::map<const FieldDescriptor*, + std::unique_ptr<const FastFieldValuePrinter>> + CustomPrinterMap; + CustomPrinterMap custom_printers_; + + typedef std::map<const Descriptor*, std::unique_ptr<const MessagePrinter>> + CustomMessagePrinterMap; + CustomMessagePrinterMap custom_message_printers_; + + const Finder* finder_; + }; + + // Parses a text-format protocol message from the given input stream to + // the given message object. This function parses the human-readable + // serialization format written by Print(). Returns true on success. The + // message is cleared first, even if the function fails -- See Merge() to + // avoid this behavior. + // + // Example input: "user {\n id: 123 extra { gender: MALE language: 'en' }\n}" + // + // One common use for this function is parsing handwritten strings in test + // code. + // + // If you would like to read a protocol buffer serialized in the + // (non-human-readable) binary wire format, see + // google::protobuf::MessageLite::ParseFromString(). + static bool Parse(io::ZeroCopyInputStream* input, Message* output); + // Like Parse(), but reads directly from a string. + static bool ParseFromString(ConstStringParam input, Message* output); + + // Like Parse(), but the data is merged into the given message, as if + // using Message::MergeFrom(). + static bool Merge(io::ZeroCopyInputStream* input, Message* output); + // Like Merge(), but reads directly from a string. + static bool MergeFromString(ConstStringParam input, Message* output); + + // Parse the given text as a single field value and store it into the + // given field of the given message. If the field is a repeated field, + // the new value will be added to the end + static bool ParseFieldValueFromString(const std::string& input, + const FieldDescriptor* field, + Message* message); + + // A location in the parsed text. + struct ParseLocation { + int line; + int column; + + ParseLocation() : line(-1), column(-1) {} + ParseLocation(int line_param, int column_param) + : line(line_param), column(column_param) {} + }; + + // A range of locations in the parsed text, including `start` and excluding + // `end`. + struct ParseLocationRange { + ParseLocation start; + ParseLocation end; + ParseLocationRange() : start(), end() {} + ParseLocationRange(ParseLocation start_param, ParseLocation end_param) + : start(start_param), end(end_param) {} + }; + + // Data structure which is populated with the locations of each field + // value parsed from the text. + class PROTOBUF_EXPORT ParseInfoTree { + public: + ParseInfoTree() = default; + ParseInfoTree(const ParseInfoTree&) = delete; + ParseInfoTree& operator=(const ParseInfoTree&) = delete; + + // Returns the parse location range for index-th value of the field in + // the parsed text. If none exists, returns a location with start and end + // line -1. Index should be -1 for not-repeated fields. + ParseLocationRange GetLocationRange(const FieldDescriptor* field, + int index) const; + + // Returns the starting parse location for index-th value of the field in + // the parsed text. If none exists, returns a location with line = -1. Index + // should be -1 for not-repeated fields. + ParseLocation GetLocation(const FieldDescriptor* field, int index) const { + return GetLocationRange(field, index).start; + } + + // Returns the parse info tree for the given field, which must be a message + // type. The nested information tree is owned by the root tree and will be + // deleted when it is deleted. + ParseInfoTree* GetTreeForNested(const FieldDescriptor* field, + int index) const; + + private: + // Allow the text format parser to record information into the tree. + friend class TextFormat; + + // Records the starting and ending locations of a single value for a field. + void RecordLocation(const FieldDescriptor* field, ParseLocationRange range); + + // Create and records a nested tree for a nested message field. + ParseInfoTree* CreateNested(const FieldDescriptor* field); + + // Defines the map from the index-th field descriptor to its parse location. + typedef std::map<const FieldDescriptor*, std::vector<ParseLocationRange>> + LocationMap; + + // Defines the map from the index-th field descriptor to the nested parse + // info tree. + typedef std::map<const FieldDescriptor*, + std::vector<std::unique_ptr<ParseInfoTree>>> + NestedMap; + + LocationMap locations_; + NestedMap nested_; + }; + + // For more control over parsing, use this class. + class PROTOBUF_EXPORT Parser { + public: + Parser(); + ~Parser(); + + // Like TextFormat::Parse(). + bool Parse(io::ZeroCopyInputStream* input, Message* output); + // Like TextFormat::ParseFromString(). + bool ParseFromString(ConstStringParam input, Message* output); + // Like TextFormat::Merge(). + bool Merge(io::ZeroCopyInputStream* input, Message* output); + // Like TextFormat::MergeFromString(). + bool MergeFromString(ConstStringParam input, Message* output); + + // Set where to report parse errors. If nullptr (the default), errors will + // be printed to stderr. + void RecordErrorsTo(io::ErrorCollector* error_collector) { + error_collector_ = error_collector; + } + + // Set how parser finds extensions. If nullptr (the default), the + // parser will use the standard Reflection object associated with + // the message being parsed. + void SetFinder(const Finder* finder) { finder_ = finder; } + + // Sets where location information about the parse will be written. If + // nullptr + // (the default), then no location will be written. + void WriteLocationsTo(ParseInfoTree* tree) { parse_info_tree_ = tree; } + + // Normally parsing fails if, after parsing, output->IsInitialized() + // returns false. Call AllowPartialMessage(true) to skip this check. + void AllowPartialMessage(bool allow) { allow_partial_ = allow; } + + // Allow field names to be matched case-insensitively. + // This is not advisable if there are fields that only differ in case, or + // if you want to enforce writing in the canonical form. + // This is 'false' by default. + void AllowCaseInsensitiveField(bool allow) { + allow_case_insensitive_field_ = allow; + } + + // Like TextFormat::ParseFieldValueFromString + bool ParseFieldValueFromString(const std::string& input, + const FieldDescriptor* field, + Message* output); + + // When an unknown extension is met, parsing will fail if this option is + // set to false (the default). If true, unknown extensions will be ignored + // and a warning message will be generated. + // Beware! Setting this option true may hide some errors (e.g. spelling + // error on extension name). This allows data loss; unlike binary format, + // text format cannot preserve unknown extensions. Avoid using this option + // if possible. + void AllowUnknownExtension(bool allow) { allow_unknown_extension_ = allow; } + + // When an unknown field is met, parsing will fail if this option is set + // to false (the default). If true, unknown fields will be ignored and + // a warning message will be generated. + // Beware! Setting this option true may hide some errors (e.g. spelling + // error on field name). This allows data loss; unlike binary format, text + // format cannot preserve unknown fields. Avoid using this option + // if possible. + void AllowUnknownField(bool allow) { allow_unknown_field_ = allow; } + + + void AllowFieldNumber(bool allow) { allow_field_number_ = allow; } + + // Sets maximum recursion depth which parser can use. This is effectively + // the maximum allowed nesting of proto messages. + void SetRecursionLimit(int limit) { recursion_limit_ = limit; } + + private: + // Forward declaration of an internal class used to parse text + // representations (see text_format.cc for implementation). + class ParserImpl; + + // Like TextFormat::Merge(). The provided implementation is used + // to do the parsing. + bool MergeUsingImpl(io::ZeroCopyInputStream* input, Message* output, + ParserImpl* parser_impl); + + io::ErrorCollector* error_collector_; + const Finder* finder_; + ParseInfoTree* parse_info_tree_; + bool allow_partial_; + bool allow_case_insensitive_field_; + bool allow_unknown_field_; + bool allow_unknown_extension_; + bool allow_unknown_enum_; + bool allow_field_number_; + bool allow_relaxed_whitespace_; + bool allow_singular_overwrites_; + int recursion_limit_; + }; + + + private: + // Hack: ParseInfoTree declares TextFormat as a friend which should extend + // the friendship to TextFormat::Parser::ParserImpl, but unfortunately some + // old compilers (e.g. GCC 3.4.6) don't implement this correctly. We provide + // helpers for ParserImpl to call methods of ParseInfoTree. + static inline void RecordLocation(ParseInfoTree* info_tree, + const FieldDescriptor* field, + ParseLocationRange location); + static inline ParseInfoTree* CreateNested(ParseInfoTree* info_tree, + const FieldDescriptor* field); + + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(TextFormat); +}; + +inline void TextFormat::RecordLocation(ParseInfoTree* info_tree, + const FieldDescriptor* field, + ParseLocationRange location) { + info_tree->RecordLocation(field, location); +} + +inline TextFormat::ParseInfoTree* TextFormat::CreateNested( + ParseInfoTree* info_tree, const FieldDescriptor* field) { + return info_tree->CreateNested(field); +} + +} // namespace protobuf +} // namespace google + +#include <google/protobuf/port_undef.inc> + +#endif // GOOGLE_PROTOBUF_TEXT_FORMAT_H__ diff --git a/toolkit/components/protobuf/src/google/protobuf/timestamp.pb.cc b/toolkit/components/protobuf/src/google/protobuf/timestamp.pb.cc new file mode 100644 index 0000000000..728a004389 --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/timestamp.pb.cc @@ -0,0 +1,307 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: google/protobuf/timestamp.proto + +#include <google/protobuf/timestamp.pb.h> + +#include <algorithm> + +#include <google/protobuf/io/coded_stream.h> +#include <google/protobuf/extension_set.h> +#include <google/protobuf/wire_format_lite.h> +#include <google/protobuf/descriptor.h> +#include <google/protobuf/generated_message_reflection.h> +#include <google/protobuf/reflection_ops.h> +#include <google/protobuf/wire_format.h> +// @@protoc_insertion_point(includes) +#include <google/protobuf/port_def.inc> + +PROTOBUF_PRAGMA_INIT_SEG + +namespace _pb = ::PROTOBUF_NAMESPACE_ID; +namespace _pbi = _pb::internal; + +PROTOBUF_NAMESPACE_OPEN +PROTOBUF_CONSTEXPR Timestamp::Timestamp( + ::_pbi::ConstantInitialized): _impl_{ + /*decltype(_impl_.seconds_)*/int64_t{0} + , /*decltype(_impl_.nanos_)*/0 + , /*decltype(_impl_._cached_size_)*/{}} {} +struct TimestampDefaultTypeInternal { + PROTOBUF_CONSTEXPR TimestampDefaultTypeInternal() + : _instance(::_pbi::ConstantInitialized{}) {} + ~TimestampDefaultTypeInternal() {} + union { + Timestamp _instance; + }; +}; +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 TimestampDefaultTypeInternal _Timestamp_default_instance_; +PROTOBUF_NAMESPACE_CLOSE +static ::_pb::Metadata file_level_metadata_google_2fprotobuf_2ftimestamp_2eproto[1]; +static constexpr ::_pb::EnumDescriptor const** file_level_enum_descriptors_google_2fprotobuf_2ftimestamp_2eproto = nullptr; +static constexpr ::_pb::ServiceDescriptor const** file_level_service_descriptors_google_2fprotobuf_2ftimestamp_2eproto = nullptr; + +const uint32_t TableStruct_google_2fprotobuf_2ftimestamp_2eproto::offsets[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = { + ~0u, // no _has_bits_ + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Timestamp, _internal_metadata_), + ~0u, // no _extensions_ + ~0u, // no _oneof_case_ + ~0u, // no _weak_field_map_ + ~0u, // no _inlined_string_donated_ + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Timestamp, _impl_.seconds_), + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Timestamp, _impl_.nanos_), +}; +static const ::_pbi::MigrationSchema schemas[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = { + { 0, -1, -1, sizeof(::PROTOBUF_NAMESPACE_ID::Timestamp)}, +}; + +static const ::_pb::Message* const file_default_instances[] = { + &::PROTOBUF_NAMESPACE_ID::_Timestamp_default_instance_._instance, +}; + +const char descriptor_table_protodef_google_2fprotobuf_2ftimestamp_2eproto[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = + "\n\037google/protobuf/timestamp.proto\022\017googl" + "e.protobuf\"+\n\tTimestamp\022\017\n\007seconds\030\001 \001(\003" + "\022\r\n\005nanos\030\002 \001(\005B\205\001\n\023com.google.protobufB" + "\016TimestampProtoP\001Z2google.golang.org/pro" + "tobuf/types/known/timestamppb\370\001\001\242\002\003GPB\252\002" + "\036Google.Protobuf.WellKnownTypesb\006proto3" + ; +static ::_pbi::once_flag descriptor_table_google_2fprotobuf_2ftimestamp_2eproto_once; +const ::_pbi::DescriptorTable descriptor_table_google_2fprotobuf_2ftimestamp_2eproto = { + false, false, 239, descriptor_table_protodef_google_2fprotobuf_2ftimestamp_2eproto, + "google/protobuf/timestamp.proto", + &descriptor_table_google_2fprotobuf_2ftimestamp_2eproto_once, nullptr, 0, 1, + schemas, file_default_instances, TableStruct_google_2fprotobuf_2ftimestamp_2eproto::offsets, + file_level_metadata_google_2fprotobuf_2ftimestamp_2eproto, file_level_enum_descriptors_google_2fprotobuf_2ftimestamp_2eproto, + file_level_service_descriptors_google_2fprotobuf_2ftimestamp_2eproto, +}; +PROTOBUF_ATTRIBUTE_WEAK const ::_pbi::DescriptorTable* descriptor_table_google_2fprotobuf_2ftimestamp_2eproto_getter() { + return &descriptor_table_google_2fprotobuf_2ftimestamp_2eproto; +} + +// Force running AddDescriptors() at dynamic initialization time. +PROTOBUF_ATTRIBUTE_INIT_PRIORITY2 static ::_pbi::AddDescriptorsRunner dynamic_init_dummy_google_2fprotobuf_2ftimestamp_2eproto(&descriptor_table_google_2fprotobuf_2ftimestamp_2eproto); +PROTOBUF_NAMESPACE_OPEN + +// =================================================================== + +class Timestamp::_Internal { + public: +}; + +Timestamp::Timestamp(::PROTOBUF_NAMESPACE_ID::Arena* arena, + bool is_message_owned) + : ::PROTOBUF_NAMESPACE_ID::Message(arena, is_message_owned) { + SharedCtor(arena, is_message_owned); + // @@protoc_insertion_point(arena_constructor:google.protobuf.Timestamp) +} +Timestamp::Timestamp(const Timestamp& from) + : ::PROTOBUF_NAMESPACE_ID::Message() { + Timestamp* const _this = this; (void)_this; + new (&_impl_) Impl_{ + decltype(_impl_.seconds_){} + , decltype(_impl_.nanos_){} + , /*decltype(_impl_._cached_size_)*/{}}; + + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); + ::memcpy(&_impl_.seconds_, &from._impl_.seconds_, + static_cast<size_t>(reinterpret_cast<char*>(&_impl_.nanos_) - + reinterpret_cast<char*>(&_impl_.seconds_)) + sizeof(_impl_.nanos_)); + // @@protoc_insertion_point(copy_constructor:google.protobuf.Timestamp) +} + +inline void Timestamp::SharedCtor( + ::_pb::Arena* arena, bool is_message_owned) { + (void)arena; + (void)is_message_owned; + new (&_impl_) Impl_{ + decltype(_impl_.seconds_){int64_t{0}} + , decltype(_impl_.nanos_){0} + , /*decltype(_impl_._cached_size_)*/{} + }; +} + +Timestamp::~Timestamp() { + // @@protoc_insertion_point(destructor:google.protobuf.Timestamp) + if (auto *arena = _internal_metadata_.DeleteReturnArena<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>()) { + (void)arena; + return; + } + SharedDtor(); +} + +inline void Timestamp::SharedDtor() { + GOOGLE_DCHECK(GetArenaForAllocation() == nullptr); +} + +void Timestamp::SetCachedSize(int size) const { + _impl_._cached_size_.Set(size); +} + +void Timestamp::Clear() { +// @@protoc_insertion_point(message_clear_start:google.protobuf.Timestamp) + uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + ::memset(&_impl_.seconds_, 0, static_cast<size_t>( + reinterpret_cast<char*>(&_impl_.nanos_) - + reinterpret_cast<char*>(&_impl_.seconds_)) + sizeof(_impl_.nanos_)); + _internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); +} + +const char* Timestamp::_InternalParse(const char* ptr, ::_pbi::ParseContext* ctx) { +#define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure + while (!ctx->Done(&ptr)) { + uint32_t tag; + ptr = ::_pbi::ReadTag(ptr, &tag); + switch (tag >> 3) { + // int64 seconds = 1; + case 1: + if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 8)) { + _impl_.seconds_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr); + CHK_(ptr); + } else + goto handle_unusual; + continue; + // int32 nanos = 2; + case 2: + if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 16)) { + _impl_.nanos_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint32(&ptr); + CHK_(ptr); + } else + goto handle_unusual; + continue; + default: + goto handle_unusual; + } // switch + handle_unusual: + if ((tag == 0) || ((tag & 7) == 4)) { + CHK_(ptr); + ctx->SetLastTag(tag); + goto message_done; + } + ptr = UnknownFieldParse( + tag, + _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(), + ptr, ctx); + CHK_(ptr != nullptr); + } // while +message_done: + return ptr; +failure: + ptr = nullptr; + goto message_done; +#undef CHK_ +} + +uint8_t* Timestamp::_InternalSerialize( + uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const { + // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.Timestamp) + uint32_t cached_has_bits = 0; + (void) cached_has_bits; + + // int64 seconds = 1; + if (this->_internal_seconds() != 0) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteInt64ToArray(1, this->_internal_seconds(), target); + } + + // int32 nanos = 2; + if (this->_internal_nanos() != 0) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteInt32ToArray(2, this->_internal_nanos(), target); + } + + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + target = ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( + _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.Timestamp) + return target; +} + +size_t Timestamp::ByteSizeLong() const { +// @@protoc_insertion_point(message_byte_size_start:google.protobuf.Timestamp) + size_t total_size = 0; + + uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + // int64 seconds = 1; + if (this->_internal_seconds() != 0) { + total_size += ::_pbi::WireFormatLite::Int64SizePlusOne(this->_internal_seconds()); + } + + // int32 nanos = 2; + if (this->_internal_nanos() != 0) { + total_size += ::_pbi::WireFormatLite::Int32SizePlusOne(this->_internal_nanos()); + } + + return MaybeComputeUnknownFieldsSize(total_size, &_impl_._cached_size_); +} + +const ::PROTOBUF_NAMESPACE_ID::Message::ClassData Timestamp::_class_data_ = { + ::PROTOBUF_NAMESPACE_ID::Message::CopyWithSourceCheck, + Timestamp::MergeImpl +}; +const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*Timestamp::GetClassData() const { return &_class_data_; } + + +void Timestamp::MergeImpl(::PROTOBUF_NAMESPACE_ID::Message& to_msg, const ::PROTOBUF_NAMESPACE_ID::Message& from_msg) { + auto* const _this = static_cast<Timestamp*>(&to_msg); + auto& from = static_cast<const Timestamp&>(from_msg); + // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.Timestamp) + GOOGLE_DCHECK_NE(&from, _this); + uint32_t cached_has_bits = 0; + (void) cached_has_bits; + + if (from._internal_seconds() != 0) { + _this->_internal_set_seconds(from._internal_seconds()); + } + if (from._internal_nanos() != 0) { + _this->_internal_set_nanos(from._internal_nanos()); + } + _this->_internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); +} + +void Timestamp::CopyFrom(const Timestamp& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.Timestamp) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool Timestamp::IsInitialized() const { + return true; +} + +void Timestamp::InternalSwap(Timestamp* other) { + using std::swap; + _internal_metadata_.InternalSwap(&other->_internal_metadata_); + ::PROTOBUF_NAMESPACE_ID::internal::memswap< + PROTOBUF_FIELD_OFFSET(Timestamp, _impl_.nanos_) + + sizeof(Timestamp::_impl_.nanos_) + - PROTOBUF_FIELD_OFFSET(Timestamp, _impl_.seconds_)>( + reinterpret_cast<char*>(&_impl_.seconds_), + reinterpret_cast<char*>(&other->_impl_.seconds_)); +} + +::PROTOBUF_NAMESPACE_ID::Metadata Timestamp::GetMetadata() const { + return ::_pbi::AssignDescriptors( + &descriptor_table_google_2fprotobuf_2ftimestamp_2eproto_getter, &descriptor_table_google_2fprotobuf_2ftimestamp_2eproto_once, + file_level_metadata_google_2fprotobuf_2ftimestamp_2eproto[0]); +} + +// @@protoc_insertion_point(namespace_scope) +PROTOBUF_NAMESPACE_CLOSE +PROTOBUF_NAMESPACE_OPEN +template<> PROTOBUF_NOINLINE ::PROTOBUF_NAMESPACE_ID::Timestamp* +Arena::CreateMaybeMessage< ::PROTOBUF_NAMESPACE_ID::Timestamp >(Arena* arena) { + return Arena::CreateMessageInternal< ::PROTOBUF_NAMESPACE_ID::Timestamp >(arena); +} +PROTOBUF_NAMESPACE_CLOSE + +// @@protoc_insertion_point(global_scope) +#include <google/protobuf/port_undef.inc> diff --git a/toolkit/components/protobuf/src/google/protobuf/timestamp.pb.h b/toolkit/components/protobuf/src/google/protobuf/timestamp.pb.h new file mode 100644 index 0000000000..6633822791 --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/timestamp.pb.h @@ -0,0 +1,278 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: google/protobuf/timestamp.proto + +#ifndef GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2ftimestamp_2eproto +#define GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2ftimestamp_2eproto + +#include <limits> +#include <string> + +#include <google/protobuf/port_def.inc> +#if PROTOBUF_VERSION < 3021000 +#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 3021006 < 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. +#endif + +#include <google/protobuf/port_undef.inc> +#include <google/protobuf/io/coded_stream.h> +#include <google/protobuf/arena.h> +#include <google/protobuf/arenastring.h> +#include <google/protobuf/generated_message_util.h> +#include <google/protobuf/metadata_lite.h> +#include <google/protobuf/generated_message_reflection.h> +#include <google/protobuf/message.h> +#include <google/protobuf/repeated_field.h> // IWYU pragma: export +#include <google/protobuf/extension_set.h> // IWYU pragma: export +#include <google/protobuf/unknown_field_set.h> +// @@protoc_insertion_point(includes) +#include <google/protobuf/port_def.inc> +#define PROTOBUF_INTERNAL_EXPORT_google_2fprotobuf_2ftimestamp_2eproto PROTOBUF_EXPORT +PROTOBUF_NAMESPACE_OPEN +namespace internal { +class AnyMetadata; +} // namespace internal +PROTOBUF_NAMESPACE_CLOSE + +// Internal implementation detail -- do not use these members. +struct PROTOBUF_EXPORT TableStruct_google_2fprotobuf_2ftimestamp_2eproto { + static const uint32_t offsets[]; +}; +PROTOBUF_EXPORT extern const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable descriptor_table_google_2fprotobuf_2ftimestamp_2eproto; +PROTOBUF_NAMESPACE_OPEN +class Timestamp; +struct TimestampDefaultTypeInternal; +PROTOBUF_EXPORT extern TimestampDefaultTypeInternal _Timestamp_default_instance_; +PROTOBUF_NAMESPACE_CLOSE +PROTOBUF_NAMESPACE_OPEN +template<> PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::Timestamp* Arena::CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::Timestamp>(Arena*); +PROTOBUF_NAMESPACE_CLOSE +PROTOBUF_NAMESPACE_OPEN + +// =================================================================== + +class PROTOBUF_EXPORT Timestamp final : + public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.Timestamp) */ { + public: + inline Timestamp() : Timestamp(nullptr) {} + ~Timestamp() override; + explicit PROTOBUF_CONSTEXPR Timestamp(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized); + + Timestamp(const Timestamp& from); + Timestamp(Timestamp&& from) noexcept + : Timestamp() { + *this = ::std::move(from); + } + + inline Timestamp& operator=(const Timestamp& from) { + CopyFrom(from); + return *this; + } + inline Timestamp& operator=(Timestamp&& from) noexcept { + if (this == &from) return *this; + if (GetOwningArena() == from.GetOwningArena() + #ifdef PROTOBUF_FORCE_COPY_IN_MOVE + && GetOwningArena() != nullptr + #endif // !PROTOBUF_FORCE_COPY_IN_MOVE + ) { + InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* descriptor() { + return GetDescriptor(); + } + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() { + return default_instance().GetMetadata().descriptor; + } + static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() { + return default_instance().GetMetadata().reflection; + } + static const Timestamp& default_instance() { + return *internal_default_instance(); + } + static inline const Timestamp* internal_default_instance() { + return reinterpret_cast<const Timestamp*>( + &_Timestamp_default_instance_); + } + static constexpr int kIndexInFileMessages = + 0; + + friend void swap(Timestamp& a, Timestamp& b) { + a.Swap(&b); + } + inline void Swap(Timestamp* other) { + if (other == this) return; + #ifdef PROTOBUF_FORCE_COPY_IN_SWAP + if (GetOwningArena() != nullptr && + GetOwningArena() == other->GetOwningArena()) { + #else // PROTOBUF_FORCE_COPY_IN_SWAP + if (GetOwningArena() == other->GetOwningArena()) { + #endif // !PROTOBUF_FORCE_COPY_IN_SWAP + InternalSwap(other); + } else { + ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(Timestamp* other) { + if (other == this) return; + GOOGLE_DCHECK(GetOwningArena() == other->GetOwningArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + Timestamp* New(::PROTOBUF_NAMESPACE_ID::Arena* arena = nullptr) const final { + return CreateMaybeMessage<Timestamp>(arena); + } + using ::PROTOBUF_NAMESPACE_ID::Message::CopyFrom; + void CopyFrom(const Timestamp& from); + using ::PROTOBUF_NAMESPACE_ID::Message::MergeFrom; + void MergeFrom( const Timestamp& from) { + Timestamp::MergeImpl(*this, from); + } + private: + static void MergeImpl(::PROTOBUF_NAMESPACE_ID::Message& to_msg, const ::PROTOBUF_NAMESPACE_ID::Message& from_msg); + public: + PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + bool IsInitialized() const final; + + size_t ByteSizeLong() const final; + const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final; + uint8_t* _InternalSerialize( + uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final; + int GetCachedSize() const final { return _impl_._cached_size_.Get(); } + + private: + void SharedCtor(::PROTOBUF_NAMESPACE_ID::Arena* arena, bool is_message_owned); + void SharedDtor(); + void SetCachedSize(int size) const final; + void InternalSwap(Timestamp* other); + + private: + friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata; + static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() { + return "google.protobuf.Timestamp"; + } + protected: + explicit Timestamp(::PROTOBUF_NAMESPACE_ID::Arena* arena, + bool is_message_owned = false); + public: + + static const ClassData _class_data_; + const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*GetClassData() const final; + + ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final; + + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + + enum : int { + kSecondsFieldNumber = 1, + kNanosFieldNumber = 2, + }; + // int64 seconds = 1; + void clear_seconds(); + int64_t seconds() const; + void set_seconds(int64_t value); + private: + int64_t _internal_seconds() const; + void _internal_set_seconds(int64_t value); + public: + + // int32 nanos = 2; + void clear_nanos(); + int32_t nanos() const; + void set_nanos(int32_t value); + private: + int32_t _internal_nanos() const; + void _internal_set_nanos(int32_t value); + public: + + // @@protoc_insertion_point(class_scope:google.protobuf.Timestamp) + private: + class _Internal; + + template <typename T> friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper; + typedef void InternalArenaConstructable_; + typedef void DestructorSkippable_; + struct Impl_ { + int64_t seconds_; + int32_t nanos_; + mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_; + }; + union { Impl_ _impl_; }; + friend struct ::TableStruct_google_2fprotobuf_2ftimestamp_2eproto; +}; +// =================================================================== + + +// =================================================================== + +#ifdef __GNUC__ + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wstrict-aliasing" +#endif // __GNUC__ +// Timestamp + +// int64 seconds = 1; +inline void Timestamp::clear_seconds() { + _impl_.seconds_ = int64_t{0}; +} +inline int64_t Timestamp::_internal_seconds() const { + return _impl_.seconds_; +} +inline int64_t Timestamp::seconds() const { + // @@protoc_insertion_point(field_get:google.protobuf.Timestamp.seconds) + return _internal_seconds(); +} +inline void Timestamp::_internal_set_seconds(int64_t value) { + + _impl_.seconds_ = value; +} +inline void Timestamp::set_seconds(int64_t value) { + _internal_set_seconds(value); + // @@protoc_insertion_point(field_set:google.protobuf.Timestamp.seconds) +} + +// int32 nanos = 2; +inline void Timestamp::clear_nanos() { + _impl_.nanos_ = 0; +} +inline int32_t Timestamp::_internal_nanos() const { + return _impl_.nanos_; +} +inline int32_t Timestamp::nanos() const { + // @@protoc_insertion_point(field_get:google.protobuf.Timestamp.nanos) + return _internal_nanos(); +} +inline void Timestamp::_internal_set_nanos(int32_t value) { + + _impl_.nanos_ = value; +} +inline void Timestamp::set_nanos(int32_t value) { + _internal_set_nanos(value); + // @@protoc_insertion_point(field_set:google.protobuf.Timestamp.nanos) +} + +#ifdef __GNUC__ + #pragma GCC diagnostic pop +#endif // __GNUC__ + +// @@protoc_insertion_point(namespace_scope) + +PROTOBUF_NAMESPACE_CLOSE + +// @@protoc_insertion_point(global_scope) + +#include <google/protobuf/port_undef.inc> +#endif // GOOGLE_PROTOBUF_INCLUDED_GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2ftimestamp_2eproto diff --git a/toolkit/components/protobuf/src/google/protobuf/timestamp.proto b/toolkit/components/protobuf/src/google/protobuf/timestamp.proto new file mode 100644 index 0000000000..3b2df6d911 --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/timestamp.proto @@ -0,0 +1,147 @@ +// 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. + +syntax = "proto3"; + +package google.protobuf; + +option csharp_namespace = "Google.Protobuf.WellKnownTypes"; +option cc_enable_arenas = true; +option go_package = "google.golang.org/protobuf/types/known/timestamppb"; +option java_package = "com.google.protobuf"; +option java_outer_classname = "TimestampProto"; +option java_multiple_files = true; +option objc_class_prefix = "GPB"; + +// A Timestamp represents a point in time independent of any time zone or local +// calendar, encoded as a count of seconds and fractions of seconds at +// nanosecond resolution. The count is relative to an epoch at UTC midnight on +// January 1, 1970, in the proleptic Gregorian calendar which extends the +// Gregorian calendar backwards to year one. +// +// All minutes are 60 seconds long. Leap seconds are "smeared" so that no leap +// second table is needed for interpretation, using a [24-hour linear +// smear](https://developers.google.com/time/smear). +// +// The range is from 0001-01-01T00:00:00Z to 9999-12-31T23:59:59.999999999Z. By +// restricting to that range, we ensure that we can convert to and from [RFC +// 3339](https://www.ietf.org/rfc/rfc3339.txt) date strings. +// +// # Examples +// +// Example 1: Compute Timestamp from POSIX `time()`. +// +// Timestamp timestamp; +// timestamp.set_seconds(time(NULL)); +// timestamp.set_nanos(0); +// +// Example 2: Compute Timestamp from POSIX `gettimeofday()`. +// +// struct timeval tv; +// gettimeofday(&tv, NULL); +// +// Timestamp timestamp; +// timestamp.set_seconds(tv.tv_sec); +// timestamp.set_nanos(tv.tv_usec * 1000); +// +// Example 3: Compute Timestamp from Win32 `GetSystemTimeAsFileTime()`. +// +// FILETIME ft; +// GetSystemTimeAsFileTime(&ft); +// UINT64 ticks = (((UINT64)ft.dwHighDateTime) << 32) | ft.dwLowDateTime; +// +// // A Windows tick is 100 nanoseconds. Windows epoch 1601-01-01T00:00:00Z +// // is 11644473600 seconds before Unix epoch 1970-01-01T00:00:00Z. +// Timestamp timestamp; +// timestamp.set_seconds((INT64) ((ticks / 10000000) - 11644473600LL)); +// timestamp.set_nanos((INT32) ((ticks % 10000000) * 100)); +// +// Example 4: Compute Timestamp from Java `System.currentTimeMillis()`. +// +// long millis = System.currentTimeMillis(); +// +// Timestamp timestamp = Timestamp.newBuilder().setSeconds(millis / 1000) +// .setNanos((int) ((millis % 1000) * 1000000)).build(); +// +// +// Example 5: Compute Timestamp from Java `Instant.now()`. +// +// Instant now = Instant.now(); +// +// Timestamp timestamp = +// Timestamp.newBuilder().setSeconds(now.getEpochSecond()) +// .setNanos(now.getNano()).build(); +// +// +// Example 6: Compute Timestamp from current time in Python. +// +// timestamp = Timestamp() +// timestamp.GetCurrentTime() +// +// # JSON Mapping +// +// In JSON format, the Timestamp type is encoded as a string in the +// [RFC 3339](https://www.ietf.org/rfc/rfc3339.txt) format. That is, the +// format is "{year}-{month}-{day}T{hour}:{min}:{sec}[.{frac_sec}]Z" +// where {year} is always expressed using four digits while {month}, {day}, +// {hour}, {min}, and {sec} are zero-padded to two digits each. The fractional +// seconds, which can go up to 9 digits (i.e. up to 1 nanosecond resolution), +// are optional. The "Z" suffix indicates the timezone ("UTC"); the timezone +// is required. A proto3 JSON serializer should always use UTC (as indicated by +// "Z") when printing the Timestamp type and a proto3 JSON parser should be +// able to accept both UTC and other timezones (as indicated by an offset). +// +// For example, "2017-01-15T01:30:15.01Z" encodes 15.01 seconds past +// 01:30 UTC on January 15, 2017. +// +// In JavaScript, one can convert a Date object to this format using the +// standard +// [toISOString()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toISOString) +// method. In Python, a standard `datetime.datetime` object can be converted +// to this format using +// [`strftime`](https://docs.python.org/2/library/time.html#time.strftime) with +// the time format spec '%Y-%m-%dT%H:%M:%S.%fZ'. Likewise, in Java, one can use +// the Joda Time's [`ISODateTimeFormat.dateTime()`]( +// http://www.joda.org/joda-time/apidocs/org/joda/time/format/ISODateTimeFormat.html#dateTime%2D%2D +// ) to obtain a formatter capable of generating timestamps in this format. +// +// +message Timestamp { + // Represents seconds of UTC time since Unix epoch + // 1970-01-01T00:00:00Z. Must be from 0001-01-01T00:00:00Z to + // 9999-12-31T23:59:59Z inclusive. + int64 seconds = 1; + + // Non-negative fractions of a second at nanosecond resolution. Negative + // second values with fractions must still have non-negative nanos values + // that count forward in time. Must be from 0 to 999,999,999 + // inclusive. + int32 nanos = 2; +} diff --git a/toolkit/components/protobuf/src/google/protobuf/type.pb.cc b/toolkit/components/protobuf/src/google/protobuf/type.pb.cc new file mode 100644 index 0000000000..e29bbb83a1 --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/type.pb.cc @@ -0,0 +1,2157 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: google/protobuf/type.proto + +#include <google/protobuf/type.pb.h> + +#include <algorithm> + +#include <google/protobuf/io/coded_stream.h> +#include <google/protobuf/extension_set.h> +#include <google/protobuf/wire_format_lite.h> +#include <google/protobuf/descriptor.h> +#include <google/protobuf/generated_message_reflection.h> +#include <google/protobuf/reflection_ops.h> +#include <google/protobuf/wire_format.h> +// @@protoc_insertion_point(includes) +#include <google/protobuf/port_def.inc> + +PROTOBUF_PRAGMA_INIT_SEG + +namespace _pb = ::PROTOBUF_NAMESPACE_ID; +namespace _pbi = _pb::internal; + +PROTOBUF_NAMESPACE_OPEN +PROTOBUF_CONSTEXPR Type::Type( + ::_pbi::ConstantInitialized): _impl_{ + /*decltype(_impl_.fields_)*/{} + , /*decltype(_impl_.oneofs_)*/{} + , /*decltype(_impl_.options_)*/{} + , /*decltype(_impl_.name_)*/{&::_pbi::fixed_address_empty_string, ::_pbi::ConstantInitialized{}} + , /*decltype(_impl_.source_context_)*/nullptr + , /*decltype(_impl_.syntax_)*/0 + , /*decltype(_impl_._cached_size_)*/{}} {} +struct TypeDefaultTypeInternal { + PROTOBUF_CONSTEXPR TypeDefaultTypeInternal() + : _instance(::_pbi::ConstantInitialized{}) {} + ~TypeDefaultTypeInternal() {} + union { + Type _instance; + }; +}; +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 TypeDefaultTypeInternal _Type_default_instance_; +PROTOBUF_CONSTEXPR Field::Field( + ::_pbi::ConstantInitialized): _impl_{ + /*decltype(_impl_.options_)*/{} + , /*decltype(_impl_.name_)*/{&::_pbi::fixed_address_empty_string, ::_pbi::ConstantInitialized{}} + , /*decltype(_impl_.type_url_)*/{&::_pbi::fixed_address_empty_string, ::_pbi::ConstantInitialized{}} + , /*decltype(_impl_.json_name_)*/{&::_pbi::fixed_address_empty_string, ::_pbi::ConstantInitialized{}} + , /*decltype(_impl_.default_value_)*/{&::_pbi::fixed_address_empty_string, ::_pbi::ConstantInitialized{}} + , /*decltype(_impl_.kind_)*/0 + , /*decltype(_impl_.cardinality_)*/0 + , /*decltype(_impl_.number_)*/0 + , /*decltype(_impl_.oneof_index_)*/0 + , /*decltype(_impl_.packed_)*/false + , /*decltype(_impl_._cached_size_)*/{}} {} +struct FieldDefaultTypeInternal { + PROTOBUF_CONSTEXPR FieldDefaultTypeInternal() + : _instance(::_pbi::ConstantInitialized{}) {} + ~FieldDefaultTypeInternal() {} + union { + Field _instance; + }; +}; +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 FieldDefaultTypeInternal _Field_default_instance_; +PROTOBUF_CONSTEXPR Enum::Enum( + ::_pbi::ConstantInitialized): _impl_{ + /*decltype(_impl_.enumvalue_)*/{} + , /*decltype(_impl_.options_)*/{} + , /*decltype(_impl_.name_)*/{&::_pbi::fixed_address_empty_string, ::_pbi::ConstantInitialized{}} + , /*decltype(_impl_.source_context_)*/nullptr + , /*decltype(_impl_.syntax_)*/0 + , /*decltype(_impl_._cached_size_)*/{}} {} +struct EnumDefaultTypeInternal { + PROTOBUF_CONSTEXPR EnumDefaultTypeInternal() + : _instance(::_pbi::ConstantInitialized{}) {} + ~EnumDefaultTypeInternal() {} + union { + Enum _instance; + }; +}; +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 EnumDefaultTypeInternal _Enum_default_instance_; +PROTOBUF_CONSTEXPR EnumValue::EnumValue( + ::_pbi::ConstantInitialized): _impl_{ + /*decltype(_impl_.options_)*/{} + , /*decltype(_impl_.name_)*/{&::_pbi::fixed_address_empty_string, ::_pbi::ConstantInitialized{}} + , /*decltype(_impl_.number_)*/0 + , /*decltype(_impl_._cached_size_)*/{}} {} +struct EnumValueDefaultTypeInternal { + PROTOBUF_CONSTEXPR EnumValueDefaultTypeInternal() + : _instance(::_pbi::ConstantInitialized{}) {} + ~EnumValueDefaultTypeInternal() {} + union { + EnumValue _instance; + }; +}; +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 EnumValueDefaultTypeInternal _EnumValue_default_instance_; +PROTOBUF_CONSTEXPR Option::Option( + ::_pbi::ConstantInitialized): _impl_{ + /*decltype(_impl_.name_)*/{&::_pbi::fixed_address_empty_string, ::_pbi::ConstantInitialized{}} + , /*decltype(_impl_.value_)*/nullptr + , /*decltype(_impl_._cached_size_)*/{}} {} +struct OptionDefaultTypeInternal { + PROTOBUF_CONSTEXPR OptionDefaultTypeInternal() + : _instance(::_pbi::ConstantInitialized{}) {} + ~OptionDefaultTypeInternal() {} + union { + Option _instance; + }; +}; +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 OptionDefaultTypeInternal _Option_default_instance_; +PROTOBUF_NAMESPACE_CLOSE +static ::_pb::Metadata file_level_metadata_google_2fprotobuf_2ftype_2eproto[5]; +static const ::_pb::EnumDescriptor* file_level_enum_descriptors_google_2fprotobuf_2ftype_2eproto[3]; +static constexpr ::_pb::ServiceDescriptor const** file_level_service_descriptors_google_2fprotobuf_2ftype_2eproto = nullptr; + +const uint32_t TableStruct_google_2fprotobuf_2ftype_2eproto::offsets[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = { + ~0u, // no _has_bits_ + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Type, _internal_metadata_), + ~0u, // no _extensions_ + ~0u, // no _oneof_case_ + ~0u, // no _weak_field_map_ + ~0u, // no _inlined_string_donated_ + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Type, _impl_.name_), + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Type, _impl_.fields_), + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Type, _impl_.oneofs_), + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Type, _impl_.options_), + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Type, _impl_.source_context_), + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Type, _impl_.syntax_), + ~0u, // no _has_bits_ + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Field, _internal_metadata_), + ~0u, // no _extensions_ + ~0u, // no _oneof_case_ + ~0u, // no _weak_field_map_ + ~0u, // no _inlined_string_donated_ + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Field, _impl_.kind_), + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Field, _impl_.cardinality_), + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Field, _impl_.number_), + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Field, _impl_.name_), + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Field, _impl_.type_url_), + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Field, _impl_.oneof_index_), + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Field, _impl_.packed_), + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Field, _impl_.options_), + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Field, _impl_.json_name_), + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Field, _impl_.default_value_), + ~0u, // no _has_bits_ + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Enum, _internal_metadata_), + ~0u, // no _extensions_ + ~0u, // no _oneof_case_ + ~0u, // no _weak_field_map_ + ~0u, // no _inlined_string_donated_ + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Enum, _impl_.name_), + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Enum, _impl_.enumvalue_), + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Enum, _impl_.options_), + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Enum, _impl_.source_context_), + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Enum, _impl_.syntax_), + ~0u, // no _has_bits_ + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::EnumValue, _internal_metadata_), + ~0u, // no _extensions_ + ~0u, // no _oneof_case_ + ~0u, // no _weak_field_map_ + ~0u, // no _inlined_string_donated_ + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::EnumValue, _impl_.name_), + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::EnumValue, _impl_.number_), + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::EnumValue, _impl_.options_), + ~0u, // no _has_bits_ + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Option, _internal_metadata_), + ~0u, // no _extensions_ + ~0u, // no _oneof_case_ + ~0u, // no _weak_field_map_ + ~0u, // no _inlined_string_donated_ + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Option, _impl_.name_), + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Option, _impl_.value_), +}; +static const ::_pbi::MigrationSchema schemas[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = { + { 0, -1, -1, sizeof(::PROTOBUF_NAMESPACE_ID::Type)}, + { 12, -1, -1, sizeof(::PROTOBUF_NAMESPACE_ID::Field)}, + { 28, -1, -1, sizeof(::PROTOBUF_NAMESPACE_ID::Enum)}, + { 39, -1, -1, sizeof(::PROTOBUF_NAMESPACE_ID::EnumValue)}, + { 48, -1, -1, sizeof(::PROTOBUF_NAMESPACE_ID::Option)}, +}; + +static const ::_pb::Message* const file_default_instances[] = { + &::PROTOBUF_NAMESPACE_ID::_Type_default_instance_._instance, + &::PROTOBUF_NAMESPACE_ID::_Field_default_instance_._instance, + &::PROTOBUF_NAMESPACE_ID::_Enum_default_instance_._instance, + &::PROTOBUF_NAMESPACE_ID::_EnumValue_default_instance_._instance, + &::PROTOBUF_NAMESPACE_ID::_Option_default_instance_._instance, +}; + +const char descriptor_table_protodef_google_2fprotobuf_2ftype_2eproto[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = + "\n\032google/protobuf/type.proto\022\017google.pro" + "tobuf\032\031google/protobuf/any.proto\032$google" + "/protobuf/source_context.proto\"\327\001\n\004Type\022" + "\014\n\004name\030\001 \001(\t\022&\n\006fields\030\002 \003(\0132\026.google.p" + "rotobuf.Field\022\016\n\006oneofs\030\003 \003(\t\022(\n\007options" + "\030\004 \003(\0132\027.google.protobuf.Option\0226\n\016sourc" + "e_context\030\005 \001(\0132\036.google.protobuf.Source" + "Context\022\'\n\006syntax\030\006 \001(\0162\027.google.protobu" + "f.Syntax\"\325\005\n\005Field\022)\n\004kind\030\001 \001(\0162\033.googl" + "e.protobuf.Field.Kind\0227\n\013cardinality\030\002 \001" + "(\0162\".google.protobuf.Field.Cardinality\022\016" + "\n\006number\030\003 \001(\005\022\014\n\004name\030\004 \001(\t\022\020\n\010type_url" + "\030\006 \001(\t\022\023\n\013oneof_index\030\007 \001(\005\022\016\n\006packed\030\010 " + "\001(\010\022(\n\007options\030\t \003(\0132\027.google.protobuf.O" + "ption\022\021\n\tjson_name\030\n \001(\t\022\025\n\rdefault_valu" + "e\030\013 \001(\t\"\310\002\n\004Kind\022\020\n\014TYPE_UNKNOWN\020\000\022\017\n\013TY" + "PE_DOUBLE\020\001\022\016\n\nTYPE_FLOAT\020\002\022\016\n\nTYPE_INT6" + "4\020\003\022\017\n\013TYPE_UINT64\020\004\022\016\n\nTYPE_INT32\020\005\022\020\n\014" + "TYPE_FIXED64\020\006\022\020\n\014TYPE_FIXED32\020\007\022\r\n\tTYPE" + "_BOOL\020\010\022\017\n\013TYPE_STRING\020\t\022\016\n\nTYPE_GROUP\020\n" + "\022\020\n\014TYPE_MESSAGE\020\013\022\016\n\nTYPE_BYTES\020\014\022\017\n\013TY" + "PE_UINT32\020\r\022\r\n\tTYPE_ENUM\020\016\022\021\n\rTYPE_SFIXE" + "D32\020\017\022\021\n\rTYPE_SFIXED64\020\020\022\017\n\013TYPE_SINT32\020" + "\021\022\017\n\013TYPE_SINT64\020\022\"t\n\013Cardinality\022\027\n\023CAR" + "DINALITY_UNKNOWN\020\000\022\030\n\024CARDINALITY_OPTION" + "AL\020\001\022\030\n\024CARDINALITY_REQUIRED\020\002\022\030\n\024CARDIN" + "ALITY_REPEATED\020\003\"\316\001\n\004Enum\022\014\n\004name\030\001 \001(\t\022" + "-\n\tenumvalue\030\002 \003(\0132\032.google.protobuf.Enu" + "mValue\022(\n\007options\030\003 \003(\0132\027.google.protobu" + "f.Option\0226\n\016source_context\030\004 \001(\0132\036.googl" + "e.protobuf.SourceContext\022\'\n\006syntax\030\005 \001(\016" + "2\027.google.protobuf.Syntax\"S\n\tEnumValue\022\014" + "\n\004name\030\001 \001(\t\022\016\n\006number\030\002 \001(\005\022(\n\007options\030" + "\003 \003(\0132\027.google.protobuf.Option\";\n\006Option" + "\022\014\n\004name\030\001 \001(\t\022#\n\005value\030\002 \001(\0132\024.google.p" + "rotobuf.Any*.\n\006Syntax\022\021\n\rSYNTAX_PROTO2\020\000" + "\022\021\n\rSYNTAX_PROTO3\020\001B{\n\023com.google.protob" + "ufB\tTypeProtoP\001Z-google.golang.org/proto" + "buf/types/known/typepb\370\001\001\242\002\003GPB\252\002\036Google" + ".Protobuf.WellKnownTypesb\006proto3" + ; +static const ::_pbi::DescriptorTable* const descriptor_table_google_2fprotobuf_2ftype_2eproto_deps[2] = { + &::descriptor_table_google_2fprotobuf_2fany_2eproto, + &::descriptor_table_google_2fprotobuf_2fsource_5fcontext_2eproto, +}; +static ::_pbi::once_flag descriptor_table_google_2fprotobuf_2ftype_2eproto_once; +const ::_pbi::DescriptorTable descriptor_table_google_2fprotobuf_2ftype_2eproto = { + false, false, 1592, descriptor_table_protodef_google_2fprotobuf_2ftype_2eproto, + "google/protobuf/type.proto", + &descriptor_table_google_2fprotobuf_2ftype_2eproto_once, descriptor_table_google_2fprotobuf_2ftype_2eproto_deps, 2, 5, + schemas, file_default_instances, TableStruct_google_2fprotobuf_2ftype_2eproto::offsets, + file_level_metadata_google_2fprotobuf_2ftype_2eproto, file_level_enum_descriptors_google_2fprotobuf_2ftype_2eproto, + file_level_service_descriptors_google_2fprotobuf_2ftype_2eproto, +}; +PROTOBUF_ATTRIBUTE_WEAK const ::_pbi::DescriptorTable* descriptor_table_google_2fprotobuf_2ftype_2eproto_getter() { + return &descriptor_table_google_2fprotobuf_2ftype_2eproto; +} + +// Force running AddDescriptors() at dynamic initialization time. +PROTOBUF_ATTRIBUTE_INIT_PRIORITY2 static ::_pbi::AddDescriptorsRunner dynamic_init_dummy_google_2fprotobuf_2ftype_2eproto(&descriptor_table_google_2fprotobuf_2ftype_2eproto); +PROTOBUF_NAMESPACE_OPEN +const ::PROTOBUF_NAMESPACE_ID::EnumDescriptor* Field_Kind_descriptor() { + ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&descriptor_table_google_2fprotobuf_2ftype_2eproto); + return file_level_enum_descriptors_google_2fprotobuf_2ftype_2eproto[0]; +} +bool Field_Kind_IsValid(int value) { + switch (value) { + case 0: + case 1: + case 2: + case 3: + case 4: + case 5: + case 6: + case 7: + case 8: + case 9: + case 10: + case 11: + case 12: + case 13: + case 14: + case 15: + case 16: + case 17: + case 18: + return true; + default: + return false; + } +} + +#if (__cplusplus < 201703) && (!defined(_MSC_VER) || (_MSC_VER >= 1900 && _MSC_VER < 1912)) +constexpr Field_Kind Field::TYPE_UNKNOWN; +constexpr Field_Kind Field::TYPE_DOUBLE; +constexpr Field_Kind Field::TYPE_FLOAT; +constexpr Field_Kind Field::TYPE_INT64; +constexpr Field_Kind Field::TYPE_UINT64; +constexpr Field_Kind Field::TYPE_INT32; +constexpr Field_Kind Field::TYPE_FIXED64; +constexpr Field_Kind Field::TYPE_FIXED32; +constexpr Field_Kind Field::TYPE_BOOL; +constexpr Field_Kind Field::TYPE_STRING; +constexpr Field_Kind Field::TYPE_GROUP; +constexpr Field_Kind Field::TYPE_MESSAGE; +constexpr Field_Kind Field::TYPE_BYTES; +constexpr Field_Kind Field::TYPE_UINT32; +constexpr Field_Kind Field::TYPE_ENUM; +constexpr Field_Kind Field::TYPE_SFIXED32; +constexpr Field_Kind Field::TYPE_SFIXED64; +constexpr Field_Kind Field::TYPE_SINT32; +constexpr Field_Kind Field::TYPE_SINT64; +constexpr Field_Kind Field::Kind_MIN; +constexpr Field_Kind Field::Kind_MAX; +constexpr int Field::Kind_ARRAYSIZE; +#endif // (__cplusplus < 201703) && (!defined(_MSC_VER) || (_MSC_VER >= 1900 && _MSC_VER < 1912)) +const ::PROTOBUF_NAMESPACE_ID::EnumDescriptor* Field_Cardinality_descriptor() { + ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&descriptor_table_google_2fprotobuf_2ftype_2eproto); + return file_level_enum_descriptors_google_2fprotobuf_2ftype_2eproto[1]; +} +bool Field_Cardinality_IsValid(int value) { + switch (value) { + case 0: + case 1: + case 2: + case 3: + return true; + default: + return false; + } +} + +#if (__cplusplus < 201703) && (!defined(_MSC_VER) || (_MSC_VER >= 1900 && _MSC_VER < 1912)) +constexpr Field_Cardinality Field::CARDINALITY_UNKNOWN; +constexpr Field_Cardinality Field::CARDINALITY_OPTIONAL; +constexpr Field_Cardinality Field::CARDINALITY_REQUIRED; +constexpr Field_Cardinality Field::CARDINALITY_REPEATED; +constexpr Field_Cardinality Field::Cardinality_MIN; +constexpr Field_Cardinality Field::Cardinality_MAX; +constexpr int Field::Cardinality_ARRAYSIZE; +#endif // (__cplusplus < 201703) && (!defined(_MSC_VER) || (_MSC_VER >= 1900 && _MSC_VER < 1912)) +const ::PROTOBUF_NAMESPACE_ID::EnumDescriptor* Syntax_descriptor() { + ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&descriptor_table_google_2fprotobuf_2ftype_2eproto); + return file_level_enum_descriptors_google_2fprotobuf_2ftype_2eproto[2]; +} +bool Syntax_IsValid(int value) { + switch (value) { + case 0: + case 1: + return true; + default: + return false; + } +} + + +// =================================================================== + +class Type::_Internal { + public: + static const ::PROTOBUF_NAMESPACE_ID::SourceContext& source_context(const Type* msg); +}; + +const ::PROTOBUF_NAMESPACE_ID::SourceContext& +Type::_Internal::source_context(const Type* msg) { + return *msg->_impl_.source_context_; +} +void Type::clear_source_context() { + if (GetArenaForAllocation() == nullptr && _impl_.source_context_ != nullptr) { + delete _impl_.source_context_; + } + _impl_.source_context_ = nullptr; +} +Type::Type(::PROTOBUF_NAMESPACE_ID::Arena* arena, + bool is_message_owned) + : ::PROTOBUF_NAMESPACE_ID::Message(arena, is_message_owned) { + SharedCtor(arena, is_message_owned); + // @@protoc_insertion_point(arena_constructor:google.protobuf.Type) +} +Type::Type(const Type& from) + : ::PROTOBUF_NAMESPACE_ID::Message() { + Type* const _this = this; (void)_this; + new (&_impl_) Impl_{ + decltype(_impl_.fields_){from._impl_.fields_} + , decltype(_impl_.oneofs_){from._impl_.oneofs_} + , decltype(_impl_.options_){from._impl_.options_} + , decltype(_impl_.name_){} + , decltype(_impl_.source_context_){nullptr} + , decltype(_impl_.syntax_){} + , /*decltype(_impl_._cached_size_)*/{}}; + + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); + _impl_.name_.InitDefault(); + #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + _impl_.name_.Set("", GetArenaForAllocation()); + #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (!from._internal_name().empty()) { + _this->_impl_.name_.Set(from._internal_name(), + _this->GetArenaForAllocation()); + } + if (from._internal_has_source_context()) { + _this->_impl_.source_context_ = new ::PROTOBUF_NAMESPACE_ID::SourceContext(*from._impl_.source_context_); + } + _this->_impl_.syntax_ = from._impl_.syntax_; + // @@protoc_insertion_point(copy_constructor:google.protobuf.Type) +} + +inline void Type::SharedCtor( + ::_pb::Arena* arena, bool is_message_owned) { + (void)arena; + (void)is_message_owned; + new (&_impl_) Impl_{ + decltype(_impl_.fields_){arena} + , decltype(_impl_.oneofs_){arena} + , decltype(_impl_.options_){arena} + , decltype(_impl_.name_){} + , decltype(_impl_.source_context_){nullptr} + , decltype(_impl_.syntax_){0} + , /*decltype(_impl_._cached_size_)*/{} + }; + _impl_.name_.InitDefault(); + #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + _impl_.name_.Set("", GetArenaForAllocation()); + #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING +} + +Type::~Type() { + // @@protoc_insertion_point(destructor:google.protobuf.Type) + if (auto *arena = _internal_metadata_.DeleteReturnArena<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>()) { + (void)arena; + return; + } + SharedDtor(); +} + +inline void Type::SharedDtor() { + GOOGLE_DCHECK(GetArenaForAllocation() == nullptr); + _impl_.fields_.~RepeatedPtrField(); + _impl_.oneofs_.~RepeatedPtrField(); + _impl_.options_.~RepeatedPtrField(); + _impl_.name_.Destroy(); + if (this != internal_default_instance()) delete _impl_.source_context_; +} + +void Type::SetCachedSize(int size) const { + _impl_._cached_size_.Set(size); +} + +void Type::Clear() { +// @@protoc_insertion_point(message_clear_start:google.protobuf.Type) + uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + _impl_.fields_.Clear(); + _impl_.oneofs_.Clear(); + _impl_.options_.Clear(); + _impl_.name_.ClearToEmpty(); + if (GetArenaForAllocation() == nullptr && _impl_.source_context_ != nullptr) { + delete _impl_.source_context_; + } + _impl_.source_context_ = nullptr; + _impl_.syntax_ = 0; + _internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); +} + +const char* Type::_InternalParse(const char* ptr, ::_pbi::ParseContext* ctx) { +#define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure + while (!ctx->Done(&ptr)) { + uint32_t tag; + ptr = ::_pbi::ReadTag(ptr, &tag); + switch (tag >> 3) { + // string name = 1; + case 1: + if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 10)) { + auto str = _internal_mutable_name(); + ptr = ::_pbi::InlineGreedyStringParser(str, ptr, ctx); + CHK_(ptr); + CHK_(::_pbi::VerifyUTF8(str, "google.protobuf.Type.name")); + } else + goto handle_unusual; + continue; + // repeated .google.protobuf.Field fields = 2; + case 2: + if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 18)) { + ptr -= 1; + do { + ptr += 1; + ptr = ctx->ParseMessage(_internal_add_fields(), ptr); + CHK_(ptr); + if (!ctx->DataAvailable(ptr)) break; + } while (::PROTOBUF_NAMESPACE_ID::internal::ExpectTag<18>(ptr)); + } else + goto handle_unusual; + continue; + // repeated string oneofs = 3; + case 3: + if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 26)) { + ptr -= 1; + do { + ptr += 1; + auto str = _internal_add_oneofs(); + ptr = ::_pbi::InlineGreedyStringParser(str, ptr, ctx); + CHK_(ptr); + CHK_(::_pbi::VerifyUTF8(str, "google.protobuf.Type.oneofs")); + if (!ctx->DataAvailable(ptr)) break; + } while (::PROTOBUF_NAMESPACE_ID::internal::ExpectTag<26>(ptr)); + } else + goto handle_unusual; + continue; + // repeated .google.protobuf.Option options = 4; + case 4: + if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 34)) { + ptr -= 1; + do { + ptr += 1; + ptr = ctx->ParseMessage(_internal_add_options(), ptr); + CHK_(ptr); + if (!ctx->DataAvailable(ptr)) break; + } while (::PROTOBUF_NAMESPACE_ID::internal::ExpectTag<34>(ptr)); + } else + goto handle_unusual; + continue; + // .google.protobuf.SourceContext source_context = 5; + case 5: + if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 42)) { + ptr = ctx->ParseMessage(_internal_mutable_source_context(), ptr); + CHK_(ptr); + } else + goto handle_unusual; + continue; + // .google.protobuf.Syntax syntax = 6; + case 6: + if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 48)) { + uint64_t val = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr); + CHK_(ptr); + _internal_set_syntax(static_cast<::PROTOBUF_NAMESPACE_ID::Syntax>(val)); + } else + goto handle_unusual; + continue; + default: + goto handle_unusual; + } // switch + handle_unusual: + if ((tag == 0) || ((tag & 7) == 4)) { + CHK_(ptr); + ctx->SetLastTag(tag); + goto message_done; + } + ptr = UnknownFieldParse( + tag, + _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(), + ptr, ctx); + CHK_(ptr != nullptr); + } // while +message_done: + return ptr; +failure: + ptr = nullptr; + goto message_done; +#undef CHK_ +} + +uint8_t* Type::_InternalSerialize( + uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const { + // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.Type) + uint32_t cached_has_bits = 0; + (void) cached_has_bits; + + // string name = 1; + if (!this->_internal_name().empty()) { + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::VerifyUtf8String( + this->_internal_name().data(), static_cast<int>(this->_internal_name().length()), + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::SERIALIZE, + "google.protobuf.Type.name"); + target = stream->WriteStringMaybeAliased( + 1, this->_internal_name(), target); + } + + // repeated .google.protobuf.Field fields = 2; + for (unsigned i = 0, + n = static_cast<unsigned>(this->_internal_fields_size()); i < n; i++) { + const auto& repfield = this->_internal_fields(i); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite:: + InternalWriteMessage(2, repfield, repfield.GetCachedSize(), target, stream); + } + + // repeated string oneofs = 3; + for (int i = 0, n = this->_internal_oneofs_size(); i < n; i++) { + const auto& s = this->_internal_oneofs(i); + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::VerifyUtf8String( + s.data(), static_cast<int>(s.length()), + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::SERIALIZE, + "google.protobuf.Type.oneofs"); + target = stream->WriteString(3, s, target); + } + + // repeated .google.protobuf.Option options = 4; + for (unsigned i = 0, + n = static_cast<unsigned>(this->_internal_options_size()); i < n; i++) { + const auto& repfield = this->_internal_options(i); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite:: + InternalWriteMessage(4, repfield, repfield.GetCachedSize(), target, stream); + } + + // .google.protobuf.SourceContext source_context = 5; + if (this->_internal_has_source_context()) { + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite:: + InternalWriteMessage(5, _Internal::source_context(this), + _Internal::source_context(this).GetCachedSize(), target, stream); + } + + // .google.protobuf.Syntax syntax = 6; + if (this->_internal_syntax() != 0) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteEnumToArray( + 6, this->_internal_syntax(), target); + } + + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + target = ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( + _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.Type) + return target; +} + +size_t Type::ByteSizeLong() const { +// @@protoc_insertion_point(message_byte_size_start:google.protobuf.Type) + size_t total_size = 0; + + uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + // repeated .google.protobuf.Field fields = 2; + total_size += 1UL * this->_internal_fields_size(); + for (const auto& msg : this->_impl_.fields_) { + total_size += + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::MessageSize(msg); + } + + // repeated string oneofs = 3; + total_size += 1 * + ::PROTOBUF_NAMESPACE_ID::internal::FromIntSize(_impl_.oneofs_.size()); + for (int i = 0, n = _impl_.oneofs_.size(); i < n; i++) { + total_size += ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize( + _impl_.oneofs_.Get(i)); + } + + // repeated .google.protobuf.Option options = 4; + total_size += 1UL * this->_internal_options_size(); + for (const auto& msg : this->_impl_.options_) { + total_size += + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::MessageSize(msg); + } + + // string name = 1; + if (!this->_internal_name().empty()) { + total_size += 1 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize( + this->_internal_name()); + } + + // .google.protobuf.SourceContext source_context = 5; + if (this->_internal_has_source_context()) { + total_size += 1 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::MessageSize( + *_impl_.source_context_); + } + + // .google.protobuf.Syntax syntax = 6; + if (this->_internal_syntax() != 0) { + total_size += 1 + + ::_pbi::WireFormatLite::EnumSize(this->_internal_syntax()); + } + + return MaybeComputeUnknownFieldsSize(total_size, &_impl_._cached_size_); +} + +const ::PROTOBUF_NAMESPACE_ID::Message::ClassData Type::_class_data_ = { + ::PROTOBUF_NAMESPACE_ID::Message::CopyWithSourceCheck, + Type::MergeImpl +}; +const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*Type::GetClassData() const { return &_class_data_; } + + +void Type::MergeImpl(::PROTOBUF_NAMESPACE_ID::Message& to_msg, const ::PROTOBUF_NAMESPACE_ID::Message& from_msg) { + auto* const _this = static_cast<Type*>(&to_msg); + auto& from = static_cast<const Type&>(from_msg); + // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.Type) + GOOGLE_DCHECK_NE(&from, _this); + uint32_t cached_has_bits = 0; + (void) cached_has_bits; + + _this->_impl_.fields_.MergeFrom(from._impl_.fields_); + _this->_impl_.oneofs_.MergeFrom(from._impl_.oneofs_); + _this->_impl_.options_.MergeFrom(from._impl_.options_); + if (!from._internal_name().empty()) { + _this->_internal_set_name(from._internal_name()); + } + if (from._internal_has_source_context()) { + _this->_internal_mutable_source_context()->::PROTOBUF_NAMESPACE_ID::SourceContext::MergeFrom( + from._internal_source_context()); + } + if (from._internal_syntax() != 0) { + _this->_internal_set_syntax(from._internal_syntax()); + } + _this->_internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); +} + +void Type::CopyFrom(const Type& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.Type) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool Type::IsInitialized() const { + return true; +} + +void Type::InternalSwap(Type* other) { + using std::swap; + auto* lhs_arena = GetArenaForAllocation(); + auto* rhs_arena = other->GetArenaForAllocation(); + _internal_metadata_.InternalSwap(&other->_internal_metadata_); + _impl_.fields_.InternalSwap(&other->_impl_.fields_); + _impl_.oneofs_.InternalSwap(&other->_impl_.oneofs_); + _impl_.options_.InternalSwap(&other->_impl_.options_); + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::InternalSwap( + &_impl_.name_, lhs_arena, + &other->_impl_.name_, rhs_arena + ); + ::PROTOBUF_NAMESPACE_ID::internal::memswap< + PROTOBUF_FIELD_OFFSET(Type, _impl_.syntax_) + + sizeof(Type::_impl_.syntax_) + - PROTOBUF_FIELD_OFFSET(Type, _impl_.source_context_)>( + reinterpret_cast<char*>(&_impl_.source_context_), + reinterpret_cast<char*>(&other->_impl_.source_context_)); +} + +::PROTOBUF_NAMESPACE_ID::Metadata Type::GetMetadata() const { + return ::_pbi::AssignDescriptors( + &descriptor_table_google_2fprotobuf_2ftype_2eproto_getter, &descriptor_table_google_2fprotobuf_2ftype_2eproto_once, + file_level_metadata_google_2fprotobuf_2ftype_2eproto[0]); +} + +// =================================================================== + +class Field::_Internal { + public: +}; + +Field::Field(::PROTOBUF_NAMESPACE_ID::Arena* arena, + bool is_message_owned) + : ::PROTOBUF_NAMESPACE_ID::Message(arena, is_message_owned) { + SharedCtor(arena, is_message_owned); + // @@protoc_insertion_point(arena_constructor:google.protobuf.Field) +} +Field::Field(const Field& from) + : ::PROTOBUF_NAMESPACE_ID::Message() { + Field* const _this = this; (void)_this; + new (&_impl_) Impl_{ + decltype(_impl_.options_){from._impl_.options_} + , decltype(_impl_.name_){} + , decltype(_impl_.type_url_){} + , decltype(_impl_.json_name_){} + , decltype(_impl_.default_value_){} + , decltype(_impl_.kind_){} + , decltype(_impl_.cardinality_){} + , decltype(_impl_.number_){} + , decltype(_impl_.oneof_index_){} + , decltype(_impl_.packed_){} + , /*decltype(_impl_._cached_size_)*/{}}; + + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); + _impl_.name_.InitDefault(); + #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + _impl_.name_.Set("", GetArenaForAllocation()); + #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (!from._internal_name().empty()) { + _this->_impl_.name_.Set(from._internal_name(), + _this->GetArenaForAllocation()); + } + _impl_.type_url_.InitDefault(); + #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + _impl_.type_url_.Set("", GetArenaForAllocation()); + #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (!from._internal_type_url().empty()) { + _this->_impl_.type_url_.Set(from._internal_type_url(), + _this->GetArenaForAllocation()); + } + _impl_.json_name_.InitDefault(); + #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + _impl_.json_name_.Set("", GetArenaForAllocation()); + #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (!from._internal_json_name().empty()) { + _this->_impl_.json_name_.Set(from._internal_json_name(), + _this->GetArenaForAllocation()); + } + _impl_.default_value_.InitDefault(); + #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + _impl_.default_value_.Set("", GetArenaForAllocation()); + #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (!from._internal_default_value().empty()) { + _this->_impl_.default_value_.Set(from._internal_default_value(), + _this->GetArenaForAllocation()); + } + ::memcpy(&_impl_.kind_, &from._impl_.kind_, + static_cast<size_t>(reinterpret_cast<char*>(&_impl_.packed_) - + reinterpret_cast<char*>(&_impl_.kind_)) + sizeof(_impl_.packed_)); + // @@protoc_insertion_point(copy_constructor:google.protobuf.Field) +} + +inline void Field::SharedCtor( + ::_pb::Arena* arena, bool is_message_owned) { + (void)arena; + (void)is_message_owned; + new (&_impl_) Impl_{ + decltype(_impl_.options_){arena} + , decltype(_impl_.name_){} + , decltype(_impl_.type_url_){} + , decltype(_impl_.json_name_){} + , decltype(_impl_.default_value_){} + , decltype(_impl_.kind_){0} + , decltype(_impl_.cardinality_){0} + , decltype(_impl_.number_){0} + , decltype(_impl_.oneof_index_){0} + , decltype(_impl_.packed_){false} + , /*decltype(_impl_._cached_size_)*/{} + }; + _impl_.name_.InitDefault(); + #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + _impl_.name_.Set("", GetArenaForAllocation()); + #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + _impl_.type_url_.InitDefault(); + #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + _impl_.type_url_.Set("", GetArenaForAllocation()); + #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + _impl_.json_name_.InitDefault(); + #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + _impl_.json_name_.Set("", GetArenaForAllocation()); + #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + _impl_.default_value_.InitDefault(); + #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + _impl_.default_value_.Set("", GetArenaForAllocation()); + #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING +} + +Field::~Field() { + // @@protoc_insertion_point(destructor:google.protobuf.Field) + if (auto *arena = _internal_metadata_.DeleteReturnArena<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>()) { + (void)arena; + return; + } + SharedDtor(); +} + +inline void Field::SharedDtor() { + GOOGLE_DCHECK(GetArenaForAllocation() == nullptr); + _impl_.options_.~RepeatedPtrField(); + _impl_.name_.Destroy(); + _impl_.type_url_.Destroy(); + _impl_.json_name_.Destroy(); + _impl_.default_value_.Destroy(); +} + +void Field::SetCachedSize(int size) const { + _impl_._cached_size_.Set(size); +} + +void Field::Clear() { +// @@protoc_insertion_point(message_clear_start:google.protobuf.Field) + uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + _impl_.options_.Clear(); + _impl_.name_.ClearToEmpty(); + _impl_.type_url_.ClearToEmpty(); + _impl_.json_name_.ClearToEmpty(); + _impl_.default_value_.ClearToEmpty(); + ::memset(&_impl_.kind_, 0, static_cast<size_t>( + reinterpret_cast<char*>(&_impl_.packed_) - + reinterpret_cast<char*>(&_impl_.kind_)) + sizeof(_impl_.packed_)); + _internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); +} + +const char* Field::_InternalParse(const char* ptr, ::_pbi::ParseContext* ctx) { +#define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure + while (!ctx->Done(&ptr)) { + uint32_t tag; + ptr = ::_pbi::ReadTag(ptr, &tag); + switch (tag >> 3) { + // .google.protobuf.Field.Kind kind = 1; + case 1: + if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 8)) { + uint64_t val = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr); + CHK_(ptr); + _internal_set_kind(static_cast<::PROTOBUF_NAMESPACE_ID::Field_Kind>(val)); + } else + goto handle_unusual; + continue; + // .google.protobuf.Field.Cardinality cardinality = 2; + case 2: + if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 16)) { + uint64_t val = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr); + CHK_(ptr); + _internal_set_cardinality(static_cast<::PROTOBUF_NAMESPACE_ID::Field_Cardinality>(val)); + } else + goto handle_unusual; + continue; + // int32 number = 3; + case 3: + if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 24)) { + _impl_.number_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint32(&ptr); + CHK_(ptr); + } else + goto handle_unusual; + continue; + // string name = 4; + case 4: + if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 34)) { + auto str = _internal_mutable_name(); + ptr = ::_pbi::InlineGreedyStringParser(str, ptr, ctx); + CHK_(ptr); + CHK_(::_pbi::VerifyUTF8(str, "google.protobuf.Field.name")); + } else + goto handle_unusual; + continue; + // string type_url = 6; + case 6: + if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 50)) { + auto str = _internal_mutable_type_url(); + ptr = ::_pbi::InlineGreedyStringParser(str, ptr, ctx); + CHK_(ptr); + CHK_(::_pbi::VerifyUTF8(str, "google.protobuf.Field.type_url")); + } else + goto handle_unusual; + continue; + // int32 oneof_index = 7; + case 7: + if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 56)) { + _impl_.oneof_index_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint32(&ptr); + CHK_(ptr); + } else + goto handle_unusual; + continue; + // bool packed = 8; + case 8: + if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 64)) { + _impl_.packed_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr); + CHK_(ptr); + } else + goto handle_unusual; + continue; + // repeated .google.protobuf.Option options = 9; + case 9: + if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 74)) { + ptr -= 1; + do { + ptr += 1; + ptr = ctx->ParseMessage(_internal_add_options(), ptr); + CHK_(ptr); + if (!ctx->DataAvailable(ptr)) break; + } while (::PROTOBUF_NAMESPACE_ID::internal::ExpectTag<74>(ptr)); + } else + goto handle_unusual; + continue; + // string json_name = 10; + case 10: + if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 82)) { + auto str = _internal_mutable_json_name(); + ptr = ::_pbi::InlineGreedyStringParser(str, ptr, ctx); + CHK_(ptr); + CHK_(::_pbi::VerifyUTF8(str, "google.protobuf.Field.json_name")); + } else + goto handle_unusual; + continue; + // string default_value = 11; + case 11: + if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 90)) { + auto str = _internal_mutable_default_value(); + ptr = ::_pbi::InlineGreedyStringParser(str, ptr, ctx); + CHK_(ptr); + CHK_(::_pbi::VerifyUTF8(str, "google.protobuf.Field.default_value")); + } else + goto handle_unusual; + continue; + default: + goto handle_unusual; + } // switch + handle_unusual: + if ((tag == 0) || ((tag & 7) == 4)) { + CHK_(ptr); + ctx->SetLastTag(tag); + goto message_done; + } + ptr = UnknownFieldParse( + tag, + _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(), + ptr, ctx); + CHK_(ptr != nullptr); + } // while +message_done: + return ptr; +failure: + ptr = nullptr; + goto message_done; +#undef CHK_ +} + +uint8_t* Field::_InternalSerialize( + uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const { + // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.Field) + uint32_t cached_has_bits = 0; + (void) cached_has_bits; + + // .google.protobuf.Field.Kind kind = 1; + if (this->_internal_kind() != 0) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteEnumToArray( + 1, this->_internal_kind(), target); + } + + // .google.protobuf.Field.Cardinality cardinality = 2; + if (this->_internal_cardinality() != 0) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteEnumToArray( + 2, this->_internal_cardinality(), target); + } + + // int32 number = 3; + if (this->_internal_number() != 0) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteInt32ToArray(3, this->_internal_number(), target); + } + + // string name = 4; + if (!this->_internal_name().empty()) { + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::VerifyUtf8String( + this->_internal_name().data(), static_cast<int>(this->_internal_name().length()), + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::SERIALIZE, + "google.protobuf.Field.name"); + target = stream->WriteStringMaybeAliased( + 4, this->_internal_name(), target); + } + + // string type_url = 6; + if (!this->_internal_type_url().empty()) { + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::VerifyUtf8String( + this->_internal_type_url().data(), static_cast<int>(this->_internal_type_url().length()), + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::SERIALIZE, + "google.protobuf.Field.type_url"); + target = stream->WriteStringMaybeAliased( + 6, this->_internal_type_url(), target); + } + + // int32 oneof_index = 7; + if (this->_internal_oneof_index() != 0) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteInt32ToArray(7, this->_internal_oneof_index(), target); + } + + // bool packed = 8; + if (this->_internal_packed() != 0) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteBoolToArray(8, this->_internal_packed(), target); + } + + // repeated .google.protobuf.Option options = 9; + for (unsigned i = 0, + n = static_cast<unsigned>(this->_internal_options_size()); i < n; i++) { + const auto& repfield = this->_internal_options(i); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite:: + InternalWriteMessage(9, repfield, repfield.GetCachedSize(), target, stream); + } + + // string json_name = 10; + if (!this->_internal_json_name().empty()) { + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::VerifyUtf8String( + this->_internal_json_name().data(), static_cast<int>(this->_internal_json_name().length()), + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::SERIALIZE, + "google.protobuf.Field.json_name"); + target = stream->WriteStringMaybeAliased( + 10, this->_internal_json_name(), target); + } + + // string default_value = 11; + if (!this->_internal_default_value().empty()) { + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::VerifyUtf8String( + this->_internal_default_value().data(), static_cast<int>(this->_internal_default_value().length()), + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::SERIALIZE, + "google.protobuf.Field.default_value"); + target = stream->WriteStringMaybeAliased( + 11, this->_internal_default_value(), target); + } + + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + target = ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( + _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.Field) + return target; +} + +size_t Field::ByteSizeLong() const { +// @@protoc_insertion_point(message_byte_size_start:google.protobuf.Field) + size_t total_size = 0; + + uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + // repeated .google.protobuf.Option options = 9; + total_size += 1UL * this->_internal_options_size(); + for (const auto& msg : this->_impl_.options_) { + total_size += + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::MessageSize(msg); + } + + // string name = 4; + if (!this->_internal_name().empty()) { + total_size += 1 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize( + this->_internal_name()); + } + + // string type_url = 6; + if (!this->_internal_type_url().empty()) { + total_size += 1 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize( + this->_internal_type_url()); + } + + // string json_name = 10; + if (!this->_internal_json_name().empty()) { + total_size += 1 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize( + this->_internal_json_name()); + } + + // string default_value = 11; + if (!this->_internal_default_value().empty()) { + total_size += 1 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize( + this->_internal_default_value()); + } + + // .google.protobuf.Field.Kind kind = 1; + if (this->_internal_kind() != 0) { + total_size += 1 + + ::_pbi::WireFormatLite::EnumSize(this->_internal_kind()); + } + + // .google.protobuf.Field.Cardinality cardinality = 2; + if (this->_internal_cardinality() != 0) { + total_size += 1 + + ::_pbi::WireFormatLite::EnumSize(this->_internal_cardinality()); + } + + // int32 number = 3; + if (this->_internal_number() != 0) { + total_size += ::_pbi::WireFormatLite::Int32SizePlusOne(this->_internal_number()); + } + + // int32 oneof_index = 7; + if (this->_internal_oneof_index() != 0) { + total_size += ::_pbi::WireFormatLite::Int32SizePlusOne(this->_internal_oneof_index()); + } + + // bool packed = 8; + if (this->_internal_packed() != 0) { + total_size += 1 + 1; + } + + return MaybeComputeUnknownFieldsSize(total_size, &_impl_._cached_size_); +} + +const ::PROTOBUF_NAMESPACE_ID::Message::ClassData Field::_class_data_ = { + ::PROTOBUF_NAMESPACE_ID::Message::CopyWithSourceCheck, + Field::MergeImpl +}; +const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*Field::GetClassData() const { return &_class_data_; } + + +void Field::MergeImpl(::PROTOBUF_NAMESPACE_ID::Message& to_msg, const ::PROTOBUF_NAMESPACE_ID::Message& from_msg) { + auto* const _this = static_cast<Field*>(&to_msg); + auto& from = static_cast<const Field&>(from_msg); + // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.Field) + GOOGLE_DCHECK_NE(&from, _this); + uint32_t cached_has_bits = 0; + (void) cached_has_bits; + + _this->_impl_.options_.MergeFrom(from._impl_.options_); + if (!from._internal_name().empty()) { + _this->_internal_set_name(from._internal_name()); + } + if (!from._internal_type_url().empty()) { + _this->_internal_set_type_url(from._internal_type_url()); + } + if (!from._internal_json_name().empty()) { + _this->_internal_set_json_name(from._internal_json_name()); + } + if (!from._internal_default_value().empty()) { + _this->_internal_set_default_value(from._internal_default_value()); + } + if (from._internal_kind() != 0) { + _this->_internal_set_kind(from._internal_kind()); + } + if (from._internal_cardinality() != 0) { + _this->_internal_set_cardinality(from._internal_cardinality()); + } + if (from._internal_number() != 0) { + _this->_internal_set_number(from._internal_number()); + } + if (from._internal_oneof_index() != 0) { + _this->_internal_set_oneof_index(from._internal_oneof_index()); + } + if (from._internal_packed() != 0) { + _this->_internal_set_packed(from._internal_packed()); + } + _this->_internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); +} + +void Field::CopyFrom(const Field& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.Field) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool Field::IsInitialized() const { + return true; +} + +void Field::InternalSwap(Field* other) { + using std::swap; + auto* lhs_arena = GetArenaForAllocation(); + auto* rhs_arena = other->GetArenaForAllocation(); + _internal_metadata_.InternalSwap(&other->_internal_metadata_); + _impl_.options_.InternalSwap(&other->_impl_.options_); + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::InternalSwap( + &_impl_.name_, lhs_arena, + &other->_impl_.name_, rhs_arena + ); + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::InternalSwap( + &_impl_.type_url_, lhs_arena, + &other->_impl_.type_url_, rhs_arena + ); + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::InternalSwap( + &_impl_.json_name_, lhs_arena, + &other->_impl_.json_name_, rhs_arena + ); + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::InternalSwap( + &_impl_.default_value_, lhs_arena, + &other->_impl_.default_value_, rhs_arena + ); + ::PROTOBUF_NAMESPACE_ID::internal::memswap< + PROTOBUF_FIELD_OFFSET(Field, _impl_.packed_) + + sizeof(Field::_impl_.packed_) + - PROTOBUF_FIELD_OFFSET(Field, _impl_.kind_)>( + reinterpret_cast<char*>(&_impl_.kind_), + reinterpret_cast<char*>(&other->_impl_.kind_)); +} + +::PROTOBUF_NAMESPACE_ID::Metadata Field::GetMetadata() const { + return ::_pbi::AssignDescriptors( + &descriptor_table_google_2fprotobuf_2ftype_2eproto_getter, &descriptor_table_google_2fprotobuf_2ftype_2eproto_once, + file_level_metadata_google_2fprotobuf_2ftype_2eproto[1]); +} + +// =================================================================== + +class Enum::_Internal { + public: + static const ::PROTOBUF_NAMESPACE_ID::SourceContext& source_context(const Enum* msg); +}; + +const ::PROTOBUF_NAMESPACE_ID::SourceContext& +Enum::_Internal::source_context(const Enum* msg) { + return *msg->_impl_.source_context_; +} +void Enum::clear_source_context() { + if (GetArenaForAllocation() == nullptr && _impl_.source_context_ != nullptr) { + delete _impl_.source_context_; + } + _impl_.source_context_ = nullptr; +} +Enum::Enum(::PROTOBUF_NAMESPACE_ID::Arena* arena, + bool is_message_owned) + : ::PROTOBUF_NAMESPACE_ID::Message(arena, is_message_owned) { + SharedCtor(arena, is_message_owned); + // @@protoc_insertion_point(arena_constructor:google.protobuf.Enum) +} +Enum::Enum(const Enum& from) + : ::PROTOBUF_NAMESPACE_ID::Message() { + Enum* const _this = this; (void)_this; + new (&_impl_) Impl_{ + decltype(_impl_.enumvalue_){from._impl_.enumvalue_} + , decltype(_impl_.options_){from._impl_.options_} + , decltype(_impl_.name_){} + , decltype(_impl_.source_context_){nullptr} + , decltype(_impl_.syntax_){} + , /*decltype(_impl_._cached_size_)*/{}}; + + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); + _impl_.name_.InitDefault(); + #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + _impl_.name_.Set("", GetArenaForAllocation()); + #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (!from._internal_name().empty()) { + _this->_impl_.name_.Set(from._internal_name(), + _this->GetArenaForAllocation()); + } + if (from._internal_has_source_context()) { + _this->_impl_.source_context_ = new ::PROTOBUF_NAMESPACE_ID::SourceContext(*from._impl_.source_context_); + } + _this->_impl_.syntax_ = from._impl_.syntax_; + // @@protoc_insertion_point(copy_constructor:google.protobuf.Enum) +} + +inline void Enum::SharedCtor( + ::_pb::Arena* arena, bool is_message_owned) { + (void)arena; + (void)is_message_owned; + new (&_impl_) Impl_{ + decltype(_impl_.enumvalue_){arena} + , decltype(_impl_.options_){arena} + , decltype(_impl_.name_){} + , decltype(_impl_.source_context_){nullptr} + , decltype(_impl_.syntax_){0} + , /*decltype(_impl_._cached_size_)*/{} + }; + _impl_.name_.InitDefault(); + #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + _impl_.name_.Set("", GetArenaForAllocation()); + #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING +} + +Enum::~Enum() { + // @@protoc_insertion_point(destructor:google.protobuf.Enum) + if (auto *arena = _internal_metadata_.DeleteReturnArena<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>()) { + (void)arena; + return; + } + SharedDtor(); +} + +inline void Enum::SharedDtor() { + GOOGLE_DCHECK(GetArenaForAllocation() == nullptr); + _impl_.enumvalue_.~RepeatedPtrField(); + _impl_.options_.~RepeatedPtrField(); + _impl_.name_.Destroy(); + if (this != internal_default_instance()) delete _impl_.source_context_; +} + +void Enum::SetCachedSize(int size) const { + _impl_._cached_size_.Set(size); +} + +void Enum::Clear() { +// @@protoc_insertion_point(message_clear_start:google.protobuf.Enum) + uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + _impl_.enumvalue_.Clear(); + _impl_.options_.Clear(); + _impl_.name_.ClearToEmpty(); + if (GetArenaForAllocation() == nullptr && _impl_.source_context_ != nullptr) { + delete _impl_.source_context_; + } + _impl_.source_context_ = nullptr; + _impl_.syntax_ = 0; + _internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); +} + +const char* Enum::_InternalParse(const char* ptr, ::_pbi::ParseContext* ctx) { +#define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure + while (!ctx->Done(&ptr)) { + uint32_t tag; + ptr = ::_pbi::ReadTag(ptr, &tag); + switch (tag >> 3) { + // string name = 1; + case 1: + if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 10)) { + auto str = _internal_mutable_name(); + ptr = ::_pbi::InlineGreedyStringParser(str, ptr, ctx); + CHK_(ptr); + CHK_(::_pbi::VerifyUTF8(str, "google.protobuf.Enum.name")); + } else + goto handle_unusual; + continue; + // repeated .google.protobuf.EnumValue enumvalue = 2; + case 2: + if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 18)) { + ptr -= 1; + do { + ptr += 1; + ptr = ctx->ParseMessage(_internal_add_enumvalue(), ptr); + CHK_(ptr); + if (!ctx->DataAvailable(ptr)) break; + } while (::PROTOBUF_NAMESPACE_ID::internal::ExpectTag<18>(ptr)); + } else + goto handle_unusual; + continue; + // repeated .google.protobuf.Option options = 3; + case 3: + if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 26)) { + ptr -= 1; + do { + ptr += 1; + ptr = ctx->ParseMessage(_internal_add_options(), ptr); + CHK_(ptr); + if (!ctx->DataAvailable(ptr)) break; + } while (::PROTOBUF_NAMESPACE_ID::internal::ExpectTag<26>(ptr)); + } else + goto handle_unusual; + continue; + // .google.protobuf.SourceContext source_context = 4; + case 4: + if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 34)) { + ptr = ctx->ParseMessage(_internal_mutable_source_context(), ptr); + CHK_(ptr); + } else + goto handle_unusual; + continue; + // .google.protobuf.Syntax syntax = 5; + case 5: + if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 40)) { + uint64_t val = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr); + CHK_(ptr); + _internal_set_syntax(static_cast<::PROTOBUF_NAMESPACE_ID::Syntax>(val)); + } else + goto handle_unusual; + continue; + default: + goto handle_unusual; + } // switch + handle_unusual: + if ((tag == 0) || ((tag & 7) == 4)) { + CHK_(ptr); + ctx->SetLastTag(tag); + goto message_done; + } + ptr = UnknownFieldParse( + tag, + _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(), + ptr, ctx); + CHK_(ptr != nullptr); + } // while +message_done: + return ptr; +failure: + ptr = nullptr; + goto message_done; +#undef CHK_ +} + +uint8_t* Enum::_InternalSerialize( + uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const { + // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.Enum) + uint32_t cached_has_bits = 0; + (void) cached_has_bits; + + // string name = 1; + if (!this->_internal_name().empty()) { + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::VerifyUtf8String( + this->_internal_name().data(), static_cast<int>(this->_internal_name().length()), + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::SERIALIZE, + "google.protobuf.Enum.name"); + target = stream->WriteStringMaybeAliased( + 1, this->_internal_name(), target); + } + + // repeated .google.protobuf.EnumValue enumvalue = 2; + for (unsigned i = 0, + n = static_cast<unsigned>(this->_internal_enumvalue_size()); i < n; i++) { + const auto& repfield = this->_internal_enumvalue(i); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite:: + InternalWriteMessage(2, repfield, repfield.GetCachedSize(), target, stream); + } + + // repeated .google.protobuf.Option options = 3; + for (unsigned i = 0, + n = static_cast<unsigned>(this->_internal_options_size()); i < n; i++) { + const auto& repfield = this->_internal_options(i); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite:: + InternalWriteMessage(3, repfield, repfield.GetCachedSize(), target, stream); + } + + // .google.protobuf.SourceContext source_context = 4; + if (this->_internal_has_source_context()) { + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite:: + InternalWriteMessage(4, _Internal::source_context(this), + _Internal::source_context(this).GetCachedSize(), target, stream); + } + + // .google.protobuf.Syntax syntax = 5; + if (this->_internal_syntax() != 0) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteEnumToArray( + 5, this->_internal_syntax(), target); + } + + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + target = ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( + _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.Enum) + return target; +} + +size_t Enum::ByteSizeLong() const { +// @@protoc_insertion_point(message_byte_size_start:google.protobuf.Enum) + size_t total_size = 0; + + uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + // repeated .google.protobuf.EnumValue enumvalue = 2; + total_size += 1UL * this->_internal_enumvalue_size(); + for (const auto& msg : this->_impl_.enumvalue_) { + total_size += + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::MessageSize(msg); + } + + // repeated .google.protobuf.Option options = 3; + total_size += 1UL * this->_internal_options_size(); + for (const auto& msg : this->_impl_.options_) { + total_size += + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::MessageSize(msg); + } + + // string name = 1; + if (!this->_internal_name().empty()) { + total_size += 1 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize( + this->_internal_name()); + } + + // .google.protobuf.SourceContext source_context = 4; + if (this->_internal_has_source_context()) { + total_size += 1 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::MessageSize( + *_impl_.source_context_); + } + + // .google.protobuf.Syntax syntax = 5; + if (this->_internal_syntax() != 0) { + total_size += 1 + + ::_pbi::WireFormatLite::EnumSize(this->_internal_syntax()); + } + + return MaybeComputeUnknownFieldsSize(total_size, &_impl_._cached_size_); +} + +const ::PROTOBUF_NAMESPACE_ID::Message::ClassData Enum::_class_data_ = { + ::PROTOBUF_NAMESPACE_ID::Message::CopyWithSourceCheck, + Enum::MergeImpl +}; +const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*Enum::GetClassData() const { return &_class_data_; } + + +void Enum::MergeImpl(::PROTOBUF_NAMESPACE_ID::Message& to_msg, const ::PROTOBUF_NAMESPACE_ID::Message& from_msg) { + auto* const _this = static_cast<Enum*>(&to_msg); + auto& from = static_cast<const Enum&>(from_msg); + // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.Enum) + GOOGLE_DCHECK_NE(&from, _this); + uint32_t cached_has_bits = 0; + (void) cached_has_bits; + + _this->_impl_.enumvalue_.MergeFrom(from._impl_.enumvalue_); + _this->_impl_.options_.MergeFrom(from._impl_.options_); + if (!from._internal_name().empty()) { + _this->_internal_set_name(from._internal_name()); + } + if (from._internal_has_source_context()) { + _this->_internal_mutable_source_context()->::PROTOBUF_NAMESPACE_ID::SourceContext::MergeFrom( + from._internal_source_context()); + } + if (from._internal_syntax() != 0) { + _this->_internal_set_syntax(from._internal_syntax()); + } + _this->_internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); +} + +void Enum::CopyFrom(const Enum& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.Enum) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool Enum::IsInitialized() const { + return true; +} + +void Enum::InternalSwap(Enum* other) { + using std::swap; + auto* lhs_arena = GetArenaForAllocation(); + auto* rhs_arena = other->GetArenaForAllocation(); + _internal_metadata_.InternalSwap(&other->_internal_metadata_); + _impl_.enumvalue_.InternalSwap(&other->_impl_.enumvalue_); + _impl_.options_.InternalSwap(&other->_impl_.options_); + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::InternalSwap( + &_impl_.name_, lhs_arena, + &other->_impl_.name_, rhs_arena + ); + ::PROTOBUF_NAMESPACE_ID::internal::memswap< + PROTOBUF_FIELD_OFFSET(Enum, _impl_.syntax_) + + sizeof(Enum::_impl_.syntax_) + - PROTOBUF_FIELD_OFFSET(Enum, _impl_.source_context_)>( + reinterpret_cast<char*>(&_impl_.source_context_), + reinterpret_cast<char*>(&other->_impl_.source_context_)); +} + +::PROTOBUF_NAMESPACE_ID::Metadata Enum::GetMetadata() const { + return ::_pbi::AssignDescriptors( + &descriptor_table_google_2fprotobuf_2ftype_2eproto_getter, &descriptor_table_google_2fprotobuf_2ftype_2eproto_once, + file_level_metadata_google_2fprotobuf_2ftype_2eproto[2]); +} + +// =================================================================== + +class EnumValue::_Internal { + public: +}; + +EnumValue::EnumValue(::PROTOBUF_NAMESPACE_ID::Arena* arena, + bool is_message_owned) + : ::PROTOBUF_NAMESPACE_ID::Message(arena, is_message_owned) { + SharedCtor(arena, is_message_owned); + // @@protoc_insertion_point(arena_constructor:google.protobuf.EnumValue) +} +EnumValue::EnumValue(const EnumValue& from) + : ::PROTOBUF_NAMESPACE_ID::Message() { + EnumValue* const _this = this; (void)_this; + new (&_impl_) Impl_{ + decltype(_impl_.options_){from._impl_.options_} + , decltype(_impl_.name_){} + , decltype(_impl_.number_){} + , /*decltype(_impl_._cached_size_)*/{}}; + + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); + _impl_.name_.InitDefault(); + #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + _impl_.name_.Set("", GetArenaForAllocation()); + #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (!from._internal_name().empty()) { + _this->_impl_.name_.Set(from._internal_name(), + _this->GetArenaForAllocation()); + } + _this->_impl_.number_ = from._impl_.number_; + // @@protoc_insertion_point(copy_constructor:google.protobuf.EnumValue) +} + +inline void EnumValue::SharedCtor( + ::_pb::Arena* arena, bool is_message_owned) { + (void)arena; + (void)is_message_owned; + new (&_impl_) Impl_{ + decltype(_impl_.options_){arena} + , decltype(_impl_.name_){} + , decltype(_impl_.number_){0} + , /*decltype(_impl_._cached_size_)*/{} + }; + _impl_.name_.InitDefault(); + #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + _impl_.name_.Set("", GetArenaForAllocation()); + #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING +} + +EnumValue::~EnumValue() { + // @@protoc_insertion_point(destructor:google.protobuf.EnumValue) + if (auto *arena = _internal_metadata_.DeleteReturnArena<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>()) { + (void)arena; + return; + } + SharedDtor(); +} + +inline void EnumValue::SharedDtor() { + GOOGLE_DCHECK(GetArenaForAllocation() == nullptr); + _impl_.options_.~RepeatedPtrField(); + _impl_.name_.Destroy(); +} + +void EnumValue::SetCachedSize(int size) const { + _impl_._cached_size_.Set(size); +} + +void EnumValue::Clear() { +// @@protoc_insertion_point(message_clear_start:google.protobuf.EnumValue) + uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + _impl_.options_.Clear(); + _impl_.name_.ClearToEmpty(); + _impl_.number_ = 0; + _internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); +} + +const char* EnumValue::_InternalParse(const char* ptr, ::_pbi::ParseContext* ctx) { +#define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure + while (!ctx->Done(&ptr)) { + uint32_t tag; + ptr = ::_pbi::ReadTag(ptr, &tag); + switch (tag >> 3) { + // string name = 1; + case 1: + if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 10)) { + auto str = _internal_mutable_name(); + ptr = ::_pbi::InlineGreedyStringParser(str, ptr, ctx); + CHK_(ptr); + CHK_(::_pbi::VerifyUTF8(str, "google.protobuf.EnumValue.name")); + } else + goto handle_unusual; + continue; + // int32 number = 2; + case 2: + if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 16)) { + _impl_.number_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint32(&ptr); + CHK_(ptr); + } else + goto handle_unusual; + continue; + // repeated .google.protobuf.Option options = 3; + case 3: + if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 26)) { + ptr -= 1; + do { + ptr += 1; + ptr = ctx->ParseMessage(_internal_add_options(), ptr); + CHK_(ptr); + if (!ctx->DataAvailable(ptr)) break; + } while (::PROTOBUF_NAMESPACE_ID::internal::ExpectTag<26>(ptr)); + } else + goto handle_unusual; + continue; + default: + goto handle_unusual; + } // switch + handle_unusual: + if ((tag == 0) || ((tag & 7) == 4)) { + CHK_(ptr); + ctx->SetLastTag(tag); + goto message_done; + } + ptr = UnknownFieldParse( + tag, + _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(), + ptr, ctx); + CHK_(ptr != nullptr); + } // while +message_done: + return ptr; +failure: + ptr = nullptr; + goto message_done; +#undef CHK_ +} + +uint8_t* EnumValue::_InternalSerialize( + uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const { + // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.EnumValue) + uint32_t cached_has_bits = 0; + (void) cached_has_bits; + + // string name = 1; + if (!this->_internal_name().empty()) { + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::VerifyUtf8String( + this->_internal_name().data(), static_cast<int>(this->_internal_name().length()), + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::SERIALIZE, + "google.protobuf.EnumValue.name"); + target = stream->WriteStringMaybeAliased( + 1, this->_internal_name(), target); + } + + // int32 number = 2; + if (this->_internal_number() != 0) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteInt32ToArray(2, this->_internal_number(), target); + } + + // repeated .google.protobuf.Option options = 3; + for (unsigned i = 0, + n = static_cast<unsigned>(this->_internal_options_size()); i < n; i++) { + const auto& repfield = this->_internal_options(i); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite:: + InternalWriteMessage(3, repfield, repfield.GetCachedSize(), target, stream); + } + + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + target = ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( + _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.EnumValue) + return target; +} + +size_t EnumValue::ByteSizeLong() const { +// @@protoc_insertion_point(message_byte_size_start:google.protobuf.EnumValue) + size_t total_size = 0; + + uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + // repeated .google.protobuf.Option options = 3; + total_size += 1UL * this->_internal_options_size(); + for (const auto& msg : this->_impl_.options_) { + total_size += + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::MessageSize(msg); + } + + // string name = 1; + if (!this->_internal_name().empty()) { + total_size += 1 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize( + this->_internal_name()); + } + + // int32 number = 2; + if (this->_internal_number() != 0) { + total_size += ::_pbi::WireFormatLite::Int32SizePlusOne(this->_internal_number()); + } + + return MaybeComputeUnknownFieldsSize(total_size, &_impl_._cached_size_); +} + +const ::PROTOBUF_NAMESPACE_ID::Message::ClassData EnumValue::_class_data_ = { + ::PROTOBUF_NAMESPACE_ID::Message::CopyWithSourceCheck, + EnumValue::MergeImpl +}; +const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*EnumValue::GetClassData() const { return &_class_data_; } + + +void EnumValue::MergeImpl(::PROTOBUF_NAMESPACE_ID::Message& to_msg, const ::PROTOBUF_NAMESPACE_ID::Message& from_msg) { + auto* const _this = static_cast<EnumValue*>(&to_msg); + auto& from = static_cast<const EnumValue&>(from_msg); + // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.EnumValue) + GOOGLE_DCHECK_NE(&from, _this); + uint32_t cached_has_bits = 0; + (void) cached_has_bits; + + _this->_impl_.options_.MergeFrom(from._impl_.options_); + if (!from._internal_name().empty()) { + _this->_internal_set_name(from._internal_name()); + } + if (from._internal_number() != 0) { + _this->_internal_set_number(from._internal_number()); + } + _this->_internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); +} + +void EnumValue::CopyFrom(const EnumValue& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.EnumValue) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool EnumValue::IsInitialized() const { + return true; +} + +void EnumValue::InternalSwap(EnumValue* other) { + using std::swap; + auto* lhs_arena = GetArenaForAllocation(); + auto* rhs_arena = other->GetArenaForAllocation(); + _internal_metadata_.InternalSwap(&other->_internal_metadata_); + _impl_.options_.InternalSwap(&other->_impl_.options_); + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::InternalSwap( + &_impl_.name_, lhs_arena, + &other->_impl_.name_, rhs_arena + ); + swap(_impl_.number_, other->_impl_.number_); +} + +::PROTOBUF_NAMESPACE_ID::Metadata EnumValue::GetMetadata() const { + return ::_pbi::AssignDescriptors( + &descriptor_table_google_2fprotobuf_2ftype_2eproto_getter, &descriptor_table_google_2fprotobuf_2ftype_2eproto_once, + file_level_metadata_google_2fprotobuf_2ftype_2eproto[3]); +} + +// =================================================================== + +class Option::_Internal { + public: + static const ::PROTOBUF_NAMESPACE_ID::Any& value(const Option* msg); +}; + +const ::PROTOBUF_NAMESPACE_ID::Any& +Option::_Internal::value(const Option* msg) { + return *msg->_impl_.value_; +} +void Option::clear_value() { + if (GetArenaForAllocation() == nullptr && _impl_.value_ != nullptr) { + delete _impl_.value_; + } + _impl_.value_ = nullptr; +} +Option::Option(::PROTOBUF_NAMESPACE_ID::Arena* arena, + bool is_message_owned) + : ::PROTOBUF_NAMESPACE_ID::Message(arena, is_message_owned) { + SharedCtor(arena, is_message_owned); + // @@protoc_insertion_point(arena_constructor:google.protobuf.Option) +} +Option::Option(const Option& from) + : ::PROTOBUF_NAMESPACE_ID::Message() { + Option* const _this = this; (void)_this; + new (&_impl_) Impl_{ + decltype(_impl_.name_){} + , decltype(_impl_.value_){nullptr} + , /*decltype(_impl_._cached_size_)*/{}}; + + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); + _impl_.name_.InitDefault(); + #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + _impl_.name_.Set("", GetArenaForAllocation()); + #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (!from._internal_name().empty()) { + _this->_impl_.name_.Set(from._internal_name(), + _this->GetArenaForAllocation()); + } + if (from._internal_has_value()) { + _this->_impl_.value_ = new ::PROTOBUF_NAMESPACE_ID::Any(*from._impl_.value_); + } + // @@protoc_insertion_point(copy_constructor:google.protobuf.Option) +} + +inline void Option::SharedCtor( + ::_pb::Arena* arena, bool is_message_owned) { + (void)arena; + (void)is_message_owned; + new (&_impl_) Impl_{ + decltype(_impl_.name_){} + , decltype(_impl_.value_){nullptr} + , /*decltype(_impl_._cached_size_)*/{} + }; + _impl_.name_.InitDefault(); + #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + _impl_.name_.Set("", GetArenaForAllocation()); + #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING +} + +Option::~Option() { + // @@protoc_insertion_point(destructor:google.protobuf.Option) + if (auto *arena = _internal_metadata_.DeleteReturnArena<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>()) { + (void)arena; + return; + } + SharedDtor(); +} + +inline void Option::SharedDtor() { + GOOGLE_DCHECK(GetArenaForAllocation() == nullptr); + _impl_.name_.Destroy(); + if (this != internal_default_instance()) delete _impl_.value_; +} + +void Option::SetCachedSize(int size) const { + _impl_._cached_size_.Set(size); +} + +void Option::Clear() { +// @@protoc_insertion_point(message_clear_start:google.protobuf.Option) + uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + _impl_.name_.ClearToEmpty(); + if (GetArenaForAllocation() == nullptr && _impl_.value_ != nullptr) { + delete _impl_.value_; + } + _impl_.value_ = nullptr; + _internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); +} + +const char* Option::_InternalParse(const char* ptr, ::_pbi::ParseContext* ctx) { +#define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure + while (!ctx->Done(&ptr)) { + uint32_t tag; + ptr = ::_pbi::ReadTag(ptr, &tag); + switch (tag >> 3) { + // string name = 1; + case 1: + if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 10)) { + auto str = _internal_mutable_name(); + ptr = ::_pbi::InlineGreedyStringParser(str, ptr, ctx); + CHK_(ptr); + CHK_(::_pbi::VerifyUTF8(str, "google.protobuf.Option.name")); + } else + goto handle_unusual; + continue; + // .google.protobuf.Any value = 2; + case 2: + if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 18)) { + ptr = ctx->ParseMessage(_internal_mutable_value(), ptr); + CHK_(ptr); + } else + goto handle_unusual; + continue; + default: + goto handle_unusual; + } // switch + handle_unusual: + if ((tag == 0) || ((tag & 7) == 4)) { + CHK_(ptr); + ctx->SetLastTag(tag); + goto message_done; + } + ptr = UnknownFieldParse( + tag, + _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(), + ptr, ctx); + CHK_(ptr != nullptr); + } // while +message_done: + return ptr; +failure: + ptr = nullptr; + goto message_done; +#undef CHK_ +} + +uint8_t* Option::_InternalSerialize( + uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const { + // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.Option) + uint32_t cached_has_bits = 0; + (void) cached_has_bits; + + // string name = 1; + if (!this->_internal_name().empty()) { + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::VerifyUtf8String( + this->_internal_name().data(), static_cast<int>(this->_internal_name().length()), + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::SERIALIZE, + "google.protobuf.Option.name"); + target = stream->WriteStringMaybeAliased( + 1, this->_internal_name(), target); + } + + // .google.protobuf.Any value = 2; + if (this->_internal_has_value()) { + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite:: + InternalWriteMessage(2, _Internal::value(this), + _Internal::value(this).GetCachedSize(), target, stream); + } + + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + target = ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( + _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.Option) + return target; +} + +size_t Option::ByteSizeLong() const { +// @@protoc_insertion_point(message_byte_size_start:google.protobuf.Option) + size_t total_size = 0; + + uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + // string name = 1; + if (!this->_internal_name().empty()) { + total_size += 1 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize( + this->_internal_name()); + } + + // .google.protobuf.Any value = 2; + if (this->_internal_has_value()) { + total_size += 1 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::MessageSize( + *_impl_.value_); + } + + return MaybeComputeUnknownFieldsSize(total_size, &_impl_._cached_size_); +} + +const ::PROTOBUF_NAMESPACE_ID::Message::ClassData Option::_class_data_ = { + ::PROTOBUF_NAMESPACE_ID::Message::CopyWithSourceCheck, + Option::MergeImpl +}; +const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*Option::GetClassData() const { return &_class_data_; } + + +void Option::MergeImpl(::PROTOBUF_NAMESPACE_ID::Message& to_msg, const ::PROTOBUF_NAMESPACE_ID::Message& from_msg) { + auto* const _this = static_cast<Option*>(&to_msg); + auto& from = static_cast<const Option&>(from_msg); + // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.Option) + GOOGLE_DCHECK_NE(&from, _this); + uint32_t cached_has_bits = 0; + (void) cached_has_bits; + + if (!from._internal_name().empty()) { + _this->_internal_set_name(from._internal_name()); + } + if (from._internal_has_value()) { + _this->_internal_mutable_value()->::PROTOBUF_NAMESPACE_ID::Any::MergeFrom( + from._internal_value()); + } + _this->_internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); +} + +void Option::CopyFrom(const Option& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.Option) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool Option::IsInitialized() const { + return true; +} + +void Option::InternalSwap(Option* other) { + using std::swap; + auto* lhs_arena = GetArenaForAllocation(); + auto* rhs_arena = other->GetArenaForAllocation(); + _internal_metadata_.InternalSwap(&other->_internal_metadata_); + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::InternalSwap( + &_impl_.name_, lhs_arena, + &other->_impl_.name_, rhs_arena + ); + swap(_impl_.value_, other->_impl_.value_); +} + +::PROTOBUF_NAMESPACE_ID::Metadata Option::GetMetadata() const { + return ::_pbi::AssignDescriptors( + &descriptor_table_google_2fprotobuf_2ftype_2eproto_getter, &descriptor_table_google_2fprotobuf_2ftype_2eproto_once, + file_level_metadata_google_2fprotobuf_2ftype_2eproto[4]); +} + +// @@protoc_insertion_point(namespace_scope) +PROTOBUF_NAMESPACE_CLOSE +PROTOBUF_NAMESPACE_OPEN +template<> PROTOBUF_NOINLINE ::PROTOBUF_NAMESPACE_ID::Type* +Arena::CreateMaybeMessage< ::PROTOBUF_NAMESPACE_ID::Type >(Arena* arena) { + return Arena::CreateMessageInternal< ::PROTOBUF_NAMESPACE_ID::Type >(arena); +} +template<> PROTOBUF_NOINLINE ::PROTOBUF_NAMESPACE_ID::Field* +Arena::CreateMaybeMessage< ::PROTOBUF_NAMESPACE_ID::Field >(Arena* arena) { + return Arena::CreateMessageInternal< ::PROTOBUF_NAMESPACE_ID::Field >(arena); +} +template<> PROTOBUF_NOINLINE ::PROTOBUF_NAMESPACE_ID::Enum* +Arena::CreateMaybeMessage< ::PROTOBUF_NAMESPACE_ID::Enum >(Arena* arena) { + return Arena::CreateMessageInternal< ::PROTOBUF_NAMESPACE_ID::Enum >(arena); +} +template<> PROTOBUF_NOINLINE ::PROTOBUF_NAMESPACE_ID::EnumValue* +Arena::CreateMaybeMessage< ::PROTOBUF_NAMESPACE_ID::EnumValue >(Arena* arena) { + return Arena::CreateMessageInternal< ::PROTOBUF_NAMESPACE_ID::EnumValue >(arena); +} +template<> PROTOBUF_NOINLINE ::PROTOBUF_NAMESPACE_ID::Option* +Arena::CreateMaybeMessage< ::PROTOBUF_NAMESPACE_ID::Option >(Arena* arena) { + return Arena::CreateMessageInternal< ::PROTOBUF_NAMESPACE_ID::Option >(arena); +} +PROTOBUF_NAMESPACE_CLOSE + +// @@protoc_insertion_point(global_scope) +#include <google/protobuf/port_undef.inc> diff --git a/toolkit/components/protobuf/src/google/protobuf/type.pb.h b/toolkit/components/protobuf/src/google/protobuf/type.pb.h new file mode 100644 index 0000000000..0f11e6cd1b --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/type.pb.h @@ -0,0 +1,2571 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: google/protobuf/type.proto + +#ifndef GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2ftype_2eproto +#define GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2ftype_2eproto + +#include <limits> +#include <string> + +#include <google/protobuf/port_def.inc> +#if PROTOBUF_VERSION < 3021000 +#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 3021006 < 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. +#endif + +#include <google/protobuf/port_undef.inc> +#include <google/protobuf/io/coded_stream.h> +#include <google/protobuf/arena.h> +#include <google/protobuf/arenastring.h> +#include <google/protobuf/generated_message_util.h> +#include <google/protobuf/metadata_lite.h> +#include <google/protobuf/generated_message_reflection.h> +#include <google/protobuf/message.h> +#include <google/protobuf/repeated_field.h> // IWYU pragma: export +#include <google/protobuf/extension_set.h> // IWYU pragma: export +#include <google/protobuf/generated_enum_reflection.h> +#include <google/protobuf/unknown_field_set.h> +#include <google/protobuf/any.pb.h> +#include <google/protobuf/source_context.pb.h> +// @@protoc_insertion_point(includes) +#include <google/protobuf/port_def.inc> +#define PROTOBUF_INTERNAL_EXPORT_google_2fprotobuf_2ftype_2eproto PROTOBUF_EXPORT +PROTOBUF_NAMESPACE_OPEN +namespace internal { +class AnyMetadata; +} // namespace internal +PROTOBUF_NAMESPACE_CLOSE + +// Internal implementation detail -- do not use these members. +struct PROTOBUF_EXPORT TableStruct_google_2fprotobuf_2ftype_2eproto { + static const uint32_t offsets[]; +}; +PROTOBUF_EXPORT extern const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable descriptor_table_google_2fprotobuf_2ftype_2eproto; +PROTOBUF_NAMESPACE_OPEN +class Enum; +struct EnumDefaultTypeInternal; +PROTOBUF_EXPORT extern EnumDefaultTypeInternal _Enum_default_instance_; +class EnumValue; +struct EnumValueDefaultTypeInternal; +PROTOBUF_EXPORT extern EnumValueDefaultTypeInternal _EnumValue_default_instance_; +class Field; +struct FieldDefaultTypeInternal; +PROTOBUF_EXPORT extern FieldDefaultTypeInternal _Field_default_instance_; +class Option; +struct OptionDefaultTypeInternal; +PROTOBUF_EXPORT extern OptionDefaultTypeInternal _Option_default_instance_; +class Type; +struct TypeDefaultTypeInternal; +PROTOBUF_EXPORT extern TypeDefaultTypeInternal _Type_default_instance_; +PROTOBUF_NAMESPACE_CLOSE +PROTOBUF_NAMESPACE_OPEN +template<> PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::Enum* Arena::CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::Enum>(Arena*); +template<> PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::EnumValue* Arena::CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::EnumValue>(Arena*); +template<> PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::Field* Arena::CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::Field>(Arena*); +template<> PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::Option* Arena::CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::Option>(Arena*); +template<> PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::Type* Arena::CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::Type>(Arena*); +PROTOBUF_NAMESPACE_CLOSE +PROTOBUF_NAMESPACE_OPEN + +enum Field_Kind : int { + Field_Kind_TYPE_UNKNOWN = 0, + Field_Kind_TYPE_DOUBLE = 1, + Field_Kind_TYPE_FLOAT = 2, + Field_Kind_TYPE_INT64 = 3, + Field_Kind_TYPE_UINT64 = 4, + Field_Kind_TYPE_INT32 = 5, + Field_Kind_TYPE_FIXED64 = 6, + Field_Kind_TYPE_FIXED32 = 7, + Field_Kind_TYPE_BOOL = 8, + Field_Kind_TYPE_STRING = 9, + Field_Kind_TYPE_GROUP = 10, + Field_Kind_TYPE_MESSAGE = 11, + Field_Kind_TYPE_BYTES = 12, + Field_Kind_TYPE_UINT32 = 13, + Field_Kind_TYPE_ENUM = 14, + Field_Kind_TYPE_SFIXED32 = 15, + Field_Kind_TYPE_SFIXED64 = 16, + Field_Kind_TYPE_SINT32 = 17, + Field_Kind_TYPE_SINT64 = 18, + Field_Kind_Field_Kind_INT_MIN_SENTINEL_DO_NOT_USE_ = std::numeric_limits<int32_t>::min(), + Field_Kind_Field_Kind_INT_MAX_SENTINEL_DO_NOT_USE_ = std::numeric_limits<int32_t>::max() +}; +PROTOBUF_EXPORT bool Field_Kind_IsValid(int value); +constexpr Field_Kind Field_Kind_Kind_MIN = Field_Kind_TYPE_UNKNOWN; +constexpr Field_Kind Field_Kind_Kind_MAX = Field_Kind_TYPE_SINT64; +constexpr int Field_Kind_Kind_ARRAYSIZE = Field_Kind_Kind_MAX + 1; + +PROTOBUF_EXPORT const ::PROTOBUF_NAMESPACE_ID::EnumDescriptor* Field_Kind_descriptor(); +template<typename T> +inline const std::string& Field_Kind_Name(T enum_t_value) { + static_assert(::std::is_same<T, Field_Kind>::value || + ::std::is_integral<T>::value, + "Incorrect type passed to function Field_Kind_Name."); + return ::PROTOBUF_NAMESPACE_ID::internal::NameOfEnum( + Field_Kind_descriptor(), enum_t_value); +} +inline bool Field_Kind_Parse( + ::PROTOBUF_NAMESPACE_ID::ConstStringParam name, Field_Kind* value) { + return ::PROTOBUF_NAMESPACE_ID::internal::ParseNamedEnum<Field_Kind>( + Field_Kind_descriptor(), name, value); +} +enum Field_Cardinality : int { + Field_Cardinality_CARDINALITY_UNKNOWN = 0, + Field_Cardinality_CARDINALITY_OPTIONAL = 1, + Field_Cardinality_CARDINALITY_REQUIRED = 2, + Field_Cardinality_CARDINALITY_REPEATED = 3, + Field_Cardinality_Field_Cardinality_INT_MIN_SENTINEL_DO_NOT_USE_ = std::numeric_limits<int32_t>::min(), + Field_Cardinality_Field_Cardinality_INT_MAX_SENTINEL_DO_NOT_USE_ = std::numeric_limits<int32_t>::max() +}; +PROTOBUF_EXPORT bool Field_Cardinality_IsValid(int value); +constexpr Field_Cardinality Field_Cardinality_Cardinality_MIN = Field_Cardinality_CARDINALITY_UNKNOWN; +constexpr Field_Cardinality Field_Cardinality_Cardinality_MAX = Field_Cardinality_CARDINALITY_REPEATED; +constexpr int Field_Cardinality_Cardinality_ARRAYSIZE = Field_Cardinality_Cardinality_MAX + 1; + +PROTOBUF_EXPORT const ::PROTOBUF_NAMESPACE_ID::EnumDescriptor* Field_Cardinality_descriptor(); +template<typename T> +inline const std::string& Field_Cardinality_Name(T enum_t_value) { + static_assert(::std::is_same<T, Field_Cardinality>::value || + ::std::is_integral<T>::value, + "Incorrect type passed to function Field_Cardinality_Name."); + return ::PROTOBUF_NAMESPACE_ID::internal::NameOfEnum( + Field_Cardinality_descriptor(), enum_t_value); +} +inline bool Field_Cardinality_Parse( + ::PROTOBUF_NAMESPACE_ID::ConstStringParam name, Field_Cardinality* value) { + return ::PROTOBUF_NAMESPACE_ID::internal::ParseNamedEnum<Field_Cardinality>( + Field_Cardinality_descriptor(), name, value); +} +enum Syntax : int { + SYNTAX_PROTO2 = 0, + SYNTAX_PROTO3 = 1, + Syntax_INT_MIN_SENTINEL_DO_NOT_USE_ = std::numeric_limits<int32_t>::min(), + Syntax_INT_MAX_SENTINEL_DO_NOT_USE_ = std::numeric_limits<int32_t>::max() +}; +PROTOBUF_EXPORT bool Syntax_IsValid(int value); +constexpr Syntax Syntax_MIN = SYNTAX_PROTO2; +constexpr Syntax Syntax_MAX = SYNTAX_PROTO3; +constexpr int Syntax_ARRAYSIZE = Syntax_MAX + 1; + +PROTOBUF_EXPORT const ::PROTOBUF_NAMESPACE_ID::EnumDescriptor* Syntax_descriptor(); +template<typename T> +inline const std::string& Syntax_Name(T enum_t_value) { + static_assert(::std::is_same<T, Syntax>::value || + ::std::is_integral<T>::value, + "Incorrect type passed to function Syntax_Name."); + return ::PROTOBUF_NAMESPACE_ID::internal::NameOfEnum( + Syntax_descriptor(), enum_t_value); +} +inline bool Syntax_Parse( + ::PROTOBUF_NAMESPACE_ID::ConstStringParam name, Syntax* value) { + return ::PROTOBUF_NAMESPACE_ID::internal::ParseNamedEnum<Syntax>( + Syntax_descriptor(), name, value); +} +// =================================================================== + +class PROTOBUF_EXPORT Type final : + public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.Type) */ { + public: + inline Type() : Type(nullptr) {} + ~Type() override; + explicit PROTOBUF_CONSTEXPR Type(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized); + + Type(const Type& from); + Type(Type&& from) noexcept + : Type() { + *this = ::std::move(from); + } + + inline Type& operator=(const Type& from) { + CopyFrom(from); + return *this; + } + inline Type& operator=(Type&& from) noexcept { + if (this == &from) return *this; + if (GetOwningArena() == from.GetOwningArena() + #ifdef PROTOBUF_FORCE_COPY_IN_MOVE + && GetOwningArena() != nullptr + #endif // !PROTOBUF_FORCE_COPY_IN_MOVE + ) { + InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* descriptor() { + return GetDescriptor(); + } + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() { + return default_instance().GetMetadata().descriptor; + } + static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() { + return default_instance().GetMetadata().reflection; + } + static const Type& default_instance() { + return *internal_default_instance(); + } + static inline const Type* internal_default_instance() { + return reinterpret_cast<const Type*>( + &_Type_default_instance_); + } + static constexpr int kIndexInFileMessages = + 0; + + friend void swap(Type& a, Type& b) { + a.Swap(&b); + } + inline void Swap(Type* other) { + if (other == this) return; + #ifdef PROTOBUF_FORCE_COPY_IN_SWAP + if (GetOwningArena() != nullptr && + GetOwningArena() == other->GetOwningArena()) { + #else // PROTOBUF_FORCE_COPY_IN_SWAP + if (GetOwningArena() == other->GetOwningArena()) { + #endif // !PROTOBUF_FORCE_COPY_IN_SWAP + InternalSwap(other); + } else { + ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(Type* other) { + if (other == this) return; + GOOGLE_DCHECK(GetOwningArena() == other->GetOwningArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + Type* New(::PROTOBUF_NAMESPACE_ID::Arena* arena = nullptr) const final { + return CreateMaybeMessage<Type>(arena); + } + using ::PROTOBUF_NAMESPACE_ID::Message::CopyFrom; + void CopyFrom(const Type& from); + using ::PROTOBUF_NAMESPACE_ID::Message::MergeFrom; + void MergeFrom( const Type& from) { + Type::MergeImpl(*this, from); + } + private: + static void MergeImpl(::PROTOBUF_NAMESPACE_ID::Message& to_msg, const ::PROTOBUF_NAMESPACE_ID::Message& from_msg); + public: + PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + bool IsInitialized() const final; + + size_t ByteSizeLong() const final; + const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final; + uint8_t* _InternalSerialize( + uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final; + int GetCachedSize() const final { return _impl_._cached_size_.Get(); } + + private: + void SharedCtor(::PROTOBUF_NAMESPACE_ID::Arena* arena, bool is_message_owned); + void SharedDtor(); + void SetCachedSize(int size) const final; + void InternalSwap(Type* other); + + private: + friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata; + static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() { + return "google.protobuf.Type"; + } + protected: + explicit Type(::PROTOBUF_NAMESPACE_ID::Arena* arena, + bool is_message_owned = false); + public: + + static const ClassData _class_data_; + const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*GetClassData() const final; + + ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final; + + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + + enum : int { + kFieldsFieldNumber = 2, + kOneofsFieldNumber = 3, + kOptionsFieldNumber = 4, + kNameFieldNumber = 1, + kSourceContextFieldNumber = 5, + kSyntaxFieldNumber = 6, + }; + // repeated .google.protobuf.Field fields = 2; + int fields_size() const; + private: + int _internal_fields_size() const; + public: + void clear_fields(); + ::PROTOBUF_NAMESPACE_ID::Field* mutable_fields(int index); + ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::Field >* + mutable_fields(); + private: + const ::PROTOBUF_NAMESPACE_ID::Field& _internal_fields(int index) const; + ::PROTOBUF_NAMESPACE_ID::Field* _internal_add_fields(); + public: + const ::PROTOBUF_NAMESPACE_ID::Field& fields(int index) const; + ::PROTOBUF_NAMESPACE_ID::Field* add_fields(); + const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::Field >& + fields() const; + + // repeated string oneofs = 3; + int oneofs_size() const; + private: + int _internal_oneofs_size() const; + public: + void clear_oneofs(); + const std::string& oneofs(int index) const; + std::string* mutable_oneofs(int index); + void set_oneofs(int index, const std::string& value); + void set_oneofs(int index, std::string&& value); + void set_oneofs(int index, const char* value); + void set_oneofs(int index, const char* value, size_t size); + std::string* add_oneofs(); + void add_oneofs(const std::string& value); + void add_oneofs(std::string&& value); + void add_oneofs(const char* value); + void add_oneofs(const char* value, size_t size); + const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField<std::string>& oneofs() const; + ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField<std::string>* mutable_oneofs(); + private: + const std::string& _internal_oneofs(int index) const; + std::string* _internal_add_oneofs(); + public: + + // repeated .google.protobuf.Option options = 4; + int options_size() const; + private: + int _internal_options_size() const; + public: + void clear_options(); + ::PROTOBUF_NAMESPACE_ID::Option* mutable_options(int index); + ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::Option >* + mutable_options(); + private: + const ::PROTOBUF_NAMESPACE_ID::Option& _internal_options(int index) const; + ::PROTOBUF_NAMESPACE_ID::Option* _internal_add_options(); + public: + const ::PROTOBUF_NAMESPACE_ID::Option& options(int index) const; + ::PROTOBUF_NAMESPACE_ID::Option* add_options(); + const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::Option >& + options() const; + + // string name = 1; + void clear_name(); + const std::string& name() const; + template <typename ArgT0 = const std::string&, typename... ArgT> + void set_name(ArgT0&& arg0, ArgT... args); + std::string* mutable_name(); + PROTOBUF_NODISCARD std::string* release_name(); + void set_allocated_name(std::string* name); + private: + const std::string& _internal_name() const; + inline PROTOBUF_ALWAYS_INLINE void _internal_set_name(const std::string& value); + std::string* _internal_mutable_name(); + public: + + // .google.protobuf.SourceContext source_context = 5; + bool has_source_context() const; + private: + bool _internal_has_source_context() const; + public: + void clear_source_context(); + const ::PROTOBUF_NAMESPACE_ID::SourceContext& source_context() const; + PROTOBUF_NODISCARD ::PROTOBUF_NAMESPACE_ID::SourceContext* release_source_context(); + ::PROTOBUF_NAMESPACE_ID::SourceContext* mutable_source_context(); + void set_allocated_source_context(::PROTOBUF_NAMESPACE_ID::SourceContext* source_context); + private: + const ::PROTOBUF_NAMESPACE_ID::SourceContext& _internal_source_context() const; + ::PROTOBUF_NAMESPACE_ID::SourceContext* _internal_mutable_source_context(); + public: + void unsafe_arena_set_allocated_source_context( + ::PROTOBUF_NAMESPACE_ID::SourceContext* source_context); + ::PROTOBUF_NAMESPACE_ID::SourceContext* unsafe_arena_release_source_context(); + + // .google.protobuf.Syntax syntax = 6; + void clear_syntax(); + ::PROTOBUF_NAMESPACE_ID::Syntax syntax() const; + void set_syntax(::PROTOBUF_NAMESPACE_ID::Syntax value); + private: + ::PROTOBUF_NAMESPACE_ID::Syntax _internal_syntax() const; + void _internal_set_syntax(::PROTOBUF_NAMESPACE_ID::Syntax value); + public: + + // @@protoc_insertion_point(class_scope:google.protobuf.Type) + private: + class _Internal; + + template <typename T> friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper; + typedef void InternalArenaConstructable_; + typedef void DestructorSkippable_; + struct Impl_ { + ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::Field > fields_; + ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField<std::string> oneofs_; + ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::Option > options_; + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr name_; + ::PROTOBUF_NAMESPACE_ID::SourceContext* source_context_; + int syntax_; + mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_; + }; + union { Impl_ _impl_; }; + friend struct ::TableStruct_google_2fprotobuf_2ftype_2eproto; +}; +// ------------------------------------------------------------------- + +class PROTOBUF_EXPORT Field final : + public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.Field) */ { + public: + inline Field() : Field(nullptr) {} + ~Field() override; + explicit PROTOBUF_CONSTEXPR Field(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized); + + Field(const Field& from); + Field(Field&& from) noexcept + : Field() { + *this = ::std::move(from); + } + + inline Field& operator=(const Field& from) { + CopyFrom(from); + return *this; + } + inline Field& operator=(Field&& from) noexcept { + if (this == &from) return *this; + if (GetOwningArena() == from.GetOwningArena() + #ifdef PROTOBUF_FORCE_COPY_IN_MOVE + && GetOwningArena() != nullptr + #endif // !PROTOBUF_FORCE_COPY_IN_MOVE + ) { + InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* descriptor() { + return GetDescriptor(); + } + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() { + return default_instance().GetMetadata().descriptor; + } + static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() { + return default_instance().GetMetadata().reflection; + } + static const Field& default_instance() { + return *internal_default_instance(); + } + static inline const Field* internal_default_instance() { + return reinterpret_cast<const Field*>( + &_Field_default_instance_); + } + static constexpr int kIndexInFileMessages = + 1; + + friend void swap(Field& a, Field& b) { + a.Swap(&b); + } + inline void Swap(Field* other) { + if (other == this) return; + #ifdef PROTOBUF_FORCE_COPY_IN_SWAP + if (GetOwningArena() != nullptr && + GetOwningArena() == other->GetOwningArena()) { + #else // PROTOBUF_FORCE_COPY_IN_SWAP + if (GetOwningArena() == other->GetOwningArena()) { + #endif // !PROTOBUF_FORCE_COPY_IN_SWAP + InternalSwap(other); + } else { + ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(Field* other) { + if (other == this) return; + GOOGLE_DCHECK(GetOwningArena() == other->GetOwningArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + Field* New(::PROTOBUF_NAMESPACE_ID::Arena* arena = nullptr) const final { + return CreateMaybeMessage<Field>(arena); + } + using ::PROTOBUF_NAMESPACE_ID::Message::CopyFrom; + void CopyFrom(const Field& from); + using ::PROTOBUF_NAMESPACE_ID::Message::MergeFrom; + void MergeFrom( const Field& from) { + Field::MergeImpl(*this, from); + } + private: + static void MergeImpl(::PROTOBUF_NAMESPACE_ID::Message& to_msg, const ::PROTOBUF_NAMESPACE_ID::Message& from_msg); + public: + PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + bool IsInitialized() const final; + + size_t ByteSizeLong() const final; + const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final; + uint8_t* _InternalSerialize( + uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final; + int GetCachedSize() const final { return _impl_._cached_size_.Get(); } + + private: + void SharedCtor(::PROTOBUF_NAMESPACE_ID::Arena* arena, bool is_message_owned); + void SharedDtor(); + void SetCachedSize(int size) const final; + void InternalSwap(Field* other); + + private: + friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata; + static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() { + return "google.protobuf.Field"; + } + protected: + explicit Field(::PROTOBUF_NAMESPACE_ID::Arena* arena, + bool is_message_owned = false); + public: + + static const ClassData _class_data_; + const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*GetClassData() const final; + + ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final; + + // nested types ---------------------------------------------------- + + typedef Field_Kind Kind; + static constexpr Kind TYPE_UNKNOWN = + Field_Kind_TYPE_UNKNOWN; + static constexpr Kind TYPE_DOUBLE = + Field_Kind_TYPE_DOUBLE; + static constexpr Kind TYPE_FLOAT = + Field_Kind_TYPE_FLOAT; + static constexpr Kind TYPE_INT64 = + Field_Kind_TYPE_INT64; + static constexpr Kind TYPE_UINT64 = + Field_Kind_TYPE_UINT64; + static constexpr Kind TYPE_INT32 = + Field_Kind_TYPE_INT32; + static constexpr Kind TYPE_FIXED64 = + Field_Kind_TYPE_FIXED64; + static constexpr Kind TYPE_FIXED32 = + Field_Kind_TYPE_FIXED32; + static constexpr Kind TYPE_BOOL = + Field_Kind_TYPE_BOOL; + static constexpr Kind TYPE_STRING = + Field_Kind_TYPE_STRING; + static constexpr Kind TYPE_GROUP = + Field_Kind_TYPE_GROUP; + static constexpr Kind TYPE_MESSAGE = + Field_Kind_TYPE_MESSAGE; + static constexpr Kind TYPE_BYTES = + Field_Kind_TYPE_BYTES; + static constexpr Kind TYPE_UINT32 = + Field_Kind_TYPE_UINT32; + static constexpr Kind TYPE_ENUM = + Field_Kind_TYPE_ENUM; + static constexpr Kind TYPE_SFIXED32 = + Field_Kind_TYPE_SFIXED32; + static constexpr Kind TYPE_SFIXED64 = + Field_Kind_TYPE_SFIXED64; + static constexpr Kind TYPE_SINT32 = + Field_Kind_TYPE_SINT32; + static constexpr Kind TYPE_SINT64 = + Field_Kind_TYPE_SINT64; + static inline bool Kind_IsValid(int value) { + return Field_Kind_IsValid(value); + } + static constexpr Kind Kind_MIN = + Field_Kind_Kind_MIN; + static constexpr Kind Kind_MAX = + Field_Kind_Kind_MAX; + static constexpr int Kind_ARRAYSIZE = + Field_Kind_Kind_ARRAYSIZE; + static inline const ::PROTOBUF_NAMESPACE_ID::EnumDescriptor* + Kind_descriptor() { + return Field_Kind_descriptor(); + } + template<typename T> + static inline const std::string& Kind_Name(T enum_t_value) { + static_assert(::std::is_same<T, Kind>::value || + ::std::is_integral<T>::value, + "Incorrect type passed to function Kind_Name."); + return Field_Kind_Name(enum_t_value); + } + static inline bool Kind_Parse(::PROTOBUF_NAMESPACE_ID::ConstStringParam name, + Kind* value) { + return Field_Kind_Parse(name, value); + } + + typedef Field_Cardinality Cardinality; + static constexpr Cardinality CARDINALITY_UNKNOWN = + Field_Cardinality_CARDINALITY_UNKNOWN; + static constexpr Cardinality CARDINALITY_OPTIONAL = + Field_Cardinality_CARDINALITY_OPTIONAL; + static constexpr Cardinality CARDINALITY_REQUIRED = + Field_Cardinality_CARDINALITY_REQUIRED; + static constexpr Cardinality CARDINALITY_REPEATED = + Field_Cardinality_CARDINALITY_REPEATED; + static inline bool Cardinality_IsValid(int value) { + return Field_Cardinality_IsValid(value); + } + static constexpr Cardinality Cardinality_MIN = + Field_Cardinality_Cardinality_MIN; + static constexpr Cardinality Cardinality_MAX = + Field_Cardinality_Cardinality_MAX; + static constexpr int Cardinality_ARRAYSIZE = + Field_Cardinality_Cardinality_ARRAYSIZE; + static inline const ::PROTOBUF_NAMESPACE_ID::EnumDescriptor* + Cardinality_descriptor() { + return Field_Cardinality_descriptor(); + } + template<typename T> + static inline const std::string& Cardinality_Name(T enum_t_value) { + static_assert(::std::is_same<T, Cardinality>::value || + ::std::is_integral<T>::value, + "Incorrect type passed to function Cardinality_Name."); + return Field_Cardinality_Name(enum_t_value); + } + static inline bool Cardinality_Parse(::PROTOBUF_NAMESPACE_ID::ConstStringParam name, + Cardinality* value) { + return Field_Cardinality_Parse(name, value); + } + + // accessors ------------------------------------------------------- + + enum : int { + kOptionsFieldNumber = 9, + kNameFieldNumber = 4, + kTypeUrlFieldNumber = 6, + kJsonNameFieldNumber = 10, + kDefaultValueFieldNumber = 11, + kKindFieldNumber = 1, + kCardinalityFieldNumber = 2, + kNumberFieldNumber = 3, + kOneofIndexFieldNumber = 7, + kPackedFieldNumber = 8, + }; + // repeated .google.protobuf.Option options = 9; + int options_size() const; + private: + int _internal_options_size() const; + public: + void clear_options(); + ::PROTOBUF_NAMESPACE_ID::Option* mutable_options(int index); + ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::Option >* + mutable_options(); + private: + const ::PROTOBUF_NAMESPACE_ID::Option& _internal_options(int index) const; + ::PROTOBUF_NAMESPACE_ID::Option* _internal_add_options(); + public: + const ::PROTOBUF_NAMESPACE_ID::Option& options(int index) const; + ::PROTOBUF_NAMESPACE_ID::Option* add_options(); + const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::Option >& + options() const; + + // string name = 4; + void clear_name(); + const std::string& name() const; + template <typename ArgT0 = const std::string&, typename... ArgT> + void set_name(ArgT0&& arg0, ArgT... args); + std::string* mutable_name(); + PROTOBUF_NODISCARD std::string* release_name(); + void set_allocated_name(std::string* name); + private: + const std::string& _internal_name() const; + inline PROTOBUF_ALWAYS_INLINE void _internal_set_name(const std::string& value); + std::string* _internal_mutable_name(); + public: + + // string type_url = 6; + void clear_type_url(); + const std::string& type_url() const; + template <typename ArgT0 = const std::string&, typename... ArgT> + void set_type_url(ArgT0&& arg0, ArgT... args); + std::string* mutable_type_url(); + PROTOBUF_NODISCARD std::string* release_type_url(); + void set_allocated_type_url(std::string* type_url); + private: + const std::string& _internal_type_url() const; + inline PROTOBUF_ALWAYS_INLINE void _internal_set_type_url(const std::string& value); + std::string* _internal_mutable_type_url(); + public: + + // string json_name = 10; + void clear_json_name(); + const std::string& json_name() const; + template <typename ArgT0 = const std::string&, typename... ArgT> + void set_json_name(ArgT0&& arg0, ArgT... args); + std::string* mutable_json_name(); + PROTOBUF_NODISCARD std::string* release_json_name(); + void set_allocated_json_name(std::string* json_name); + private: + const std::string& _internal_json_name() const; + inline PROTOBUF_ALWAYS_INLINE void _internal_set_json_name(const std::string& value); + std::string* _internal_mutable_json_name(); + public: + + // string default_value = 11; + void clear_default_value(); + const std::string& default_value() const; + template <typename ArgT0 = const std::string&, typename... ArgT> + void set_default_value(ArgT0&& arg0, ArgT... args); + std::string* mutable_default_value(); + PROTOBUF_NODISCARD std::string* release_default_value(); + void set_allocated_default_value(std::string* default_value); + private: + const std::string& _internal_default_value() const; + inline PROTOBUF_ALWAYS_INLINE void _internal_set_default_value(const std::string& value); + std::string* _internal_mutable_default_value(); + public: + + // .google.protobuf.Field.Kind kind = 1; + void clear_kind(); + ::PROTOBUF_NAMESPACE_ID::Field_Kind kind() const; + void set_kind(::PROTOBUF_NAMESPACE_ID::Field_Kind value); + private: + ::PROTOBUF_NAMESPACE_ID::Field_Kind _internal_kind() const; + void _internal_set_kind(::PROTOBUF_NAMESPACE_ID::Field_Kind value); + public: + + // .google.protobuf.Field.Cardinality cardinality = 2; + void clear_cardinality(); + ::PROTOBUF_NAMESPACE_ID::Field_Cardinality cardinality() const; + void set_cardinality(::PROTOBUF_NAMESPACE_ID::Field_Cardinality value); + private: + ::PROTOBUF_NAMESPACE_ID::Field_Cardinality _internal_cardinality() const; + void _internal_set_cardinality(::PROTOBUF_NAMESPACE_ID::Field_Cardinality value); + public: + + // int32 number = 3; + void clear_number(); + int32_t number() const; + void set_number(int32_t value); + private: + int32_t _internal_number() const; + void _internal_set_number(int32_t value); + public: + + // int32 oneof_index = 7; + void clear_oneof_index(); + int32_t oneof_index() const; + void set_oneof_index(int32_t value); + private: + int32_t _internal_oneof_index() const; + void _internal_set_oneof_index(int32_t value); + public: + + // bool packed = 8; + void clear_packed(); + bool packed() const; + void set_packed(bool value); + private: + bool _internal_packed() const; + void _internal_set_packed(bool value); + public: + + // @@protoc_insertion_point(class_scope:google.protobuf.Field) + private: + class _Internal; + + template <typename T> friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper; + typedef void InternalArenaConstructable_; + typedef void DestructorSkippable_; + struct Impl_ { + ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::Option > options_; + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr name_; + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr type_url_; + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr json_name_; + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr default_value_; + int kind_; + int cardinality_; + int32_t number_; + int32_t oneof_index_; + bool packed_; + mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_; + }; + union { Impl_ _impl_; }; + friend struct ::TableStruct_google_2fprotobuf_2ftype_2eproto; +}; +// ------------------------------------------------------------------- + +class PROTOBUF_EXPORT Enum final : + public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.Enum) */ { + public: + inline Enum() : Enum(nullptr) {} + ~Enum() override; + explicit PROTOBUF_CONSTEXPR Enum(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized); + + Enum(const Enum& from); + Enum(Enum&& from) noexcept + : Enum() { + *this = ::std::move(from); + } + + inline Enum& operator=(const Enum& from) { + CopyFrom(from); + return *this; + } + inline Enum& operator=(Enum&& from) noexcept { + if (this == &from) return *this; + if (GetOwningArena() == from.GetOwningArena() + #ifdef PROTOBUF_FORCE_COPY_IN_MOVE + && GetOwningArena() != nullptr + #endif // !PROTOBUF_FORCE_COPY_IN_MOVE + ) { + InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* descriptor() { + return GetDescriptor(); + } + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() { + return default_instance().GetMetadata().descriptor; + } + static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() { + return default_instance().GetMetadata().reflection; + } + static const Enum& default_instance() { + return *internal_default_instance(); + } + static inline const Enum* internal_default_instance() { + return reinterpret_cast<const Enum*>( + &_Enum_default_instance_); + } + static constexpr int kIndexInFileMessages = + 2; + + friend void swap(Enum& a, Enum& b) { + a.Swap(&b); + } + inline void Swap(Enum* other) { + if (other == this) return; + #ifdef PROTOBUF_FORCE_COPY_IN_SWAP + if (GetOwningArena() != nullptr && + GetOwningArena() == other->GetOwningArena()) { + #else // PROTOBUF_FORCE_COPY_IN_SWAP + if (GetOwningArena() == other->GetOwningArena()) { + #endif // !PROTOBUF_FORCE_COPY_IN_SWAP + InternalSwap(other); + } else { + ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(Enum* other) { + if (other == this) return; + GOOGLE_DCHECK(GetOwningArena() == other->GetOwningArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + Enum* New(::PROTOBUF_NAMESPACE_ID::Arena* arena = nullptr) const final { + return CreateMaybeMessage<Enum>(arena); + } + using ::PROTOBUF_NAMESPACE_ID::Message::CopyFrom; + void CopyFrom(const Enum& from); + using ::PROTOBUF_NAMESPACE_ID::Message::MergeFrom; + void MergeFrom( const Enum& from) { + Enum::MergeImpl(*this, from); + } + private: + static void MergeImpl(::PROTOBUF_NAMESPACE_ID::Message& to_msg, const ::PROTOBUF_NAMESPACE_ID::Message& from_msg); + public: + PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + bool IsInitialized() const final; + + size_t ByteSizeLong() const final; + const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final; + uint8_t* _InternalSerialize( + uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final; + int GetCachedSize() const final { return _impl_._cached_size_.Get(); } + + private: + void SharedCtor(::PROTOBUF_NAMESPACE_ID::Arena* arena, bool is_message_owned); + void SharedDtor(); + void SetCachedSize(int size) const final; + void InternalSwap(Enum* other); + + private: + friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata; + static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() { + return "google.protobuf.Enum"; + } + protected: + explicit Enum(::PROTOBUF_NAMESPACE_ID::Arena* arena, + bool is_message_owned = false); + public: + + static const ClassData _class_data_; + const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*GetClassData() const final; + + ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final; + + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + + enum : int { + kEnumvalueFieldNumber = 2, + kOptionsFieldNumber = 3, + kNameFieldNumber = 1, + kSourceContextFieldNumber = 4, + kSyntaxFieldNumber = 5, + }; + // repeated .google.protobuf.EnumValue enumvalue = 2; + int enumvalue_size() const; + private: + int _internal_enumvalue_size() const; + public: + void clear_enumvalue(); + ::PROTOBUF_NAMESPACE_ID::EnumValue* mutable_enumvalue(int index); + ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::EnumValue >* + mutable_enumvalue(); + private: + const ::PROTOBUF_NAMESPACE_ID::EnumValue& _internal_enumvalue(int index) const; + ::PROTOBUF_NAMESPACE_ID::EnumValue* _internal_add_enumvalue(); + public: + const ::PROTOBUF_NAMESPACE_ID::EnumValue& enumvalue(int index) const; + ::PROTOBUF_NAMESPACE_ID::EnumValue* add_enumvalue(); + const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::EnumValue >& + enumvalue() const; + + // repeated .google.protobuf.Option options = 3; + int options_size() const; + private: + int _internal_options_size() const; + public: + void clear_options(); + ::PROTOBUF_NAMESPACE_ID::Option* mutable_options(int index); + ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::Option >* + mutable_options(); + private: + const ::PROTOBUF_NAMESPACE_ID::Option& _internal_options(int index) const; + ::PROTOBUF_NAMESPACE_ID::Option* _internal_add_options(); + public: + const ::PROTOBUF_NAMESPACE_ID::Option& options(int index) const; + ::PROTOBUF_NAMESPACE_ID::Option* add_options(); + const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::Option >& + options() const; + + // string name = 1; + void clear_name(); + const std::string& name() const; + template <typename ArgT0 = const std::string&, typename... ArgT> + void set_name(ArgT0&& arg0, ArgT... args); + std::string* mutable_name(); + PROTOBUF_NODISCARD std::string* release_name(); + void set_allocated_name(std::string* name); + private: + const std::string& _internal_name() const; + inline PROTOBUF_ALWAYS_INLINE void _internal_set_name(const std::string& value); + std::string* _internal_mutable_name(); + public: + + // .google.protobuf.SourceContext source_context = 4; + bool has_source_context() const; + private: + bool _internal_has_source_context() const; + public: + void clear_source_context(); + const ::PROTOBUF_NAMESPACE_ID::SourceContext& source_context() const; + PROTOBUF_NODISCARD ::PROTOBUF_NAMESPACE_ID::SourceContext* release_source_context(); + ::PROTOBUF_NAMESPACE_ID::SourceContext* mutable_source_context(); + void set_allocated_source_context(::PROTOBUF_NAMESPACE_ID::SourceContext* source_context); + private: + const ::PROTOBUF_NAMESPACE_ID::SourceContext& _internal_source_context() const; + ::PROTOBUF_NAMESPACE_ID::SourceContext* _internal_mutable_source_context(); + public: + void unsafe_arena_set_allocated_source_context( + ::PROTOBUF_NAMESPACE_ID::SourceContext* source_context); + ::PROTOBUF_NAMESPACE_ID::SourceContext* unsafe_arena_release_source_context(); + + // .google.protobuf.Syntax syntax = 5; + void clear_syntax(); + ::PROTOBUF_NAMESPACE_ID::Syntax syntax() const; + void set_syntax(::PROTOBUF_NAMESPACE_ID::Syntax value); + private: + ::PROTOBUF_NAMESPACE_ID::Syntax _internal_syntax() const; + void _internal_set_syntax(::PROTOBUF_NAMESPACE_ID::Syntax value); + public: + + // @@protoc_insertion_point(class_scope:google.protobuf.Enum) + private: + class _Internal; + + template <typename T> friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper; + typedef void InternalArenaConstructable_; + typedef void DestructorSkippable_; + struct Impl_ { + ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::EnumValue > enumvalue_; + ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::Option > options_; + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr name_; + ::PROTOBUF_NAMESPACE_ID::SourceContext* source_context_; + int syntax_; + mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_; + }; + union { Impl_ _impl_; }; + friend struct ::TableStruct_google_2fprotobuf_2ftype_2eproto; +}; +// ------------------------------------------------------------------- + +class PROTOBUF_EXPORT EnumValue final : + public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.EnumValue) */ { + public: + inline EnumValue() : EnumValue(nullptr) {} + ~EnumValue() override; + explicit PROTOBUF_CONSTEXPR EnumValue(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized); + + EnumValue(const EnumValue& from); + EnumValue(EnumValue&& from) noexcept + : EnumValue() { + *this = ::std::move(from); + } + + inline EnumValue& operator=(const EnumValue& from) { + CopyFrom(from); + return *this; + } + inline EnumValue& operator=(EnumValue&& from) noexcept { + if (this == &from) return *this; + if (GetOwningArena() == from.GetOwningArena() + #ifdef PROTOBUF_FORCE_COPY_IN_MOVE + && GetOwningArena() != nullptr + #endif // !PROTOBUF_FORCE_COPY_IN_MOVE + ) { + InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* descriptor() { + return GetDescriptor(); + } + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() { + return default_instance().GetMetadata().descriptor; + } + static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() { + return default_instance().GetMetadata().reflection; + } + static const EnumValue& default_instance() { + return *internal_default_instance(); + } + static inline const EnumValue* internal_default_instance() { + return reinterpret_cast<const EnumValue*>( + &_EnumValue_default_instance_); + } + static constexpr int kIndexInFileMessages = + 3; + + friend void swap(EnumValue& a, EnumValue& b) { + a.Swap(&b); + } + inline void Swap(EnumValue* other) { + if (other == this) return; + #ifdef PROTOBUF_FORCE_COPY_IN_SWAP + if (GetOwningArena() != nullptr && + GetOwningArena() == other->GetOwningArena()) { + #else // PROTOBUF_FORCE_COPY_IN_SWAP + if (GetOwningArena() == other->GetOwningArena()) { + #endif // !PROTOBUF_FORCE_COPY_IN_SWAP + InternalSwap(other); + } else { + ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(EnumValue* other) { + if (other == this) return; + GOOGLE_DCHECK(GetOwningArena() == other->GetOwningArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + EnumValue* New(::PROTOBUF_NAMESPACE_ID::Arena* arena = nullptr) const final { + return CreateMaybeMessage<EnumValue>(arena); + } + using ::PROTOBUF_NAMESPACE_ID::Message::CopyFrom; + void CopyFrom(const EnumValue& from); + using ::PROTOBUF_NAMESPACE_ID::Message::MergeFrom; + void MergeFrom( const EnumValue& from) { + EnumValue::MergeImpl(*this, from); + } + private: + static void MergeImpl(::PROTOBUF_NAMESPACE_ID::Message& to_msg, const ::PROTOBUF_NAMESPACE_ID::Message& from_msg); + public: + PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + bool IsInitialized() const final; + + size_t ByteSizeLong() const final; + const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final; + uint8_t* _InternalSerialize( + uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final; + int GetCachedSize() const final { return _impl_._cached_size_.Get(); } + + private: + void SharedCtor(::PROTOBUF_NAMESPACE_ID::Arena* arena, bool is_message_owned); + void SharedDtor(); + void SetCachedSize(int size) const final; + void InternalSwap(EnumValue* other); + + private: + friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata; + static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() { + return "google.protobuf.EnumValue"; + } + protected: + explicit EnumValue(::PROTOBUF_NAMESPACE_ID::Arena* arena, + bool is_message_owned = false); + public: + + static const ClassData _class_data_; + const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*GetClassData() const final; + + ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final; + + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + + enum : int { + kOptionsFieldNumber = 3, + kNameFieldNumber = 1, + kNumberFieldNumber = 2, + }; + // repeated .google.protobuf.Option options = 3; + int options_size() const; + private: + int _internal_options_size() const; + public: + void clear_options(); + ::PROTOBUF_NAMESPACE_ID::Option* mutable_options(int index); + ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::Option >* + mutable_options(); + private: + const ::PROTOBUF_NAMESPACE_ID::Option& _internal_options(int index) const; + ::PROTOBUF_NAMESPACE_ID::Option* _internal_add_options(); + public: + const ::PROTOBUF_NAMESPACE_ID::Option& options(int index) const; + ::PROTOBUF_NAMESPACE_ID::Option* add_options(); + const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::Option >& + options() const; + + // string name = 1; + void clear_name(); + const std::string& name() const; + template <typename ArgT0 = const std::string&, typename... ArgT> + void set_name(ArgT0&& arg0, ArgT... args); + std::string* mutable_name(); + PROTOBUF_NODISCARD std::string* release_name(); + void set_allocated_name(std::string* name); + private: + const std::string& _internal_name() const; + inline PROTOBUF_ALWAYS_INLINE void _internal_set_name(const std::string& value); + std::string* _internal_mutable_name(); + public: + + // int32 number = 2; + void clear_number(); + int32_t number() const; + void set_number(int32_t value); + private: + int32_t _internal_number() const; + void _internal_set_number(int32_t value); + public: + + // @@protoc_insertion_point(class_scope:google.protobuf.EnumValue) + private: + class _Internal; + + template <typename T> friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper; + typedef void InternalArenaConstructable_; + typedef void DestructorSkippable_; + struct Impl_ { + ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::Option > options_; + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr name_; + int32_t number_; + mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_; + }; + union { Impl_ _impl_; }; + friend struct ::TableStruct_google_2fprotobuf_2ftype_2eproto; +}; +// ------------------------------------------------------------------- + +class PROTOBUF_EXPORT Option final : + public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.Option) */ { + public: + inline Option() : Option(nullptr) {} + ~Option() override; + explicit PROTOBUF_CONSTEXPR Option(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized); + + Option(const Option& from); + Option(Option&& from) noexcept + : Option() { + *this = ::std::move(from); + } + + inline Option& operator=(const Option& from) { + CopyFrom(from); + return *this; + } + inline Option& operator=(Option&& from) noexcept { + if (this == &from) return *this; + if (GetOwningArena() == from.GetOwningArena() + #ifdef PROTOBUF_FORCE_COPY_IN_MOVE + && GetOwningArena() != nullptr + #endif // !PROTOBUF_FORCE_COPY_IN_MOVE + ) { + InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* descriptor() { + return GetDescriptor(); + } + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() { + return default_instance().GetMetadata().descriptor; + } + static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() { + return default_instance().GetMetadata().reflection; + } + static const Option& default_instance() { + return *internal_default_instance(); + } + static inline const Option* internal_default_instance() { + return reinterpret_cast<const Option*>( + &_Option_default_instance_); + } + static constexpr int kIndexInFileMessages = + 4; + + friend void swap(Option& a, Option& b) { + a.Swap(&b); + } + inline void Swap(Option* other) { + if (other == this) return; + #ifdef PROTOBUF_FORCE_COPY_IN_SWAP + if (GetOwningArena() != nullptr && + GetOwningArena() == other->GetOwningArena()) { + #else // PROTOBUF_FORCE_COPY_IN_SWAP + if (GetOwningArena() == other->GetOwningArena()) { + #endif // !PROTOBUF_FORCE_COPY_IN_SWAP + InternalSwap(other); + } else { + ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(Option* other) { + if (other == this) return; + GOOGLE_DCHECK(GetOwningArena() == other->GetOwningArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + Option* New(::PROTOBUF_NAMESPACE_ID::Arena* arena = nullptr) const final { + return CreateMaybeMessage<Option>(arena); + } + using ::PROTOBUF_NAMESPACE_ID::Message::CopyFrom; + void CopyFrom(const Option& from); + using ::PROTOBUF_NAMESPACE_ID::Message::MergeFrom; + void MergeFrom( const Option& from) { + Option::MergeImpl(*this, from); + } + private: + static void MergeImpl(::PROTOBUF_NAMESPACE_ID::Message& to_msg, const ::PROTOBUF_NAMESPACE_ID::Message& from_msg); + public: + PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + bool IsInitialized() const final; + + size_t ByteSizeLong() const final; + const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final; + uint8_t* _InternalSerialize( + uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final; + int GetCachedSize() const final { return _impl_._cached_size_.Get(); } + + private: + void SharedCtor(::PROTOBUF_NAMESPACE_ID::Arena* arena, bool is_message_owned); + void SharedDtor(); + void SetCachedSize(int size) const final; + void InternalSwap(Option* other); + + private: + friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata; + static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() { + return "google.protobuf.Option"; + } + protected: + explicit Option(::PROTOBUF_NAMESPACE_ID::Arena* arena, + bool is_message_owned = false); + public: + + static const ClassData _class_data_; + const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*GetClassData() const final; + + ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final; + + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + + enum : int { + kNameFieldNumber = 1, + kValueFieldNumber = 2, + }; + // string name = 1; + void clear_name(); + const std::string& name() const; + template <typename ArgT0 = const std::string&, typename... ArgT> + void set_name(ArgT0&& arg0, ArgT... args); + std::string* mutable_name(); + PROTOBUF_NODISCARD std::string* release_name(); + void set_allocated_name(std::string* name); + private: + const std::string& _internal_name() const; + inline PROTOBUF_ALWAYS_INLINE void _internal_set_name(const std::string& value); + std::string* _internal_mutable_name(); + public: + + // .google.protobuf.Any value = 2; + bool has_value() const; + private: + bool _internal_has_value() const; + public: + void clear_value(); + const ::PROTOBUF_NAMESPACE_ID::Any& value() const; + PROTOBUF_NODISCARD ::PROTOBUF_NAMESPACE_ID::Any* release_value(); + ::PROTOBUF_NAMESPACE_ID::Any* mutable_value(); + void set_allocated_value(::PROTOBUF_NAMESPACE_ID::Any* value); + private: + const ::PROTOBUF_NAMESPACE_ID::Any& _internal_value() const; + ::PROTOBUF_NAMESPACE_ID::Any* _internal_mutable_value(); + public: + void unsafe_arena_set_allocated_value( + ::PROTOBUF_NAMESPACE_ID::Any* value); + ::PROTOBUF_NAMESPACE_ID::Any* unsafe_arena_release_value(); + + // @@protoc_insertion_point(class_scope:google.protobuf.Option) + private: + class _Internal; + + template <typename T> friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper; + typedef void InternalArenaConstructable_; + typedef void DestructorSkippable_; + struct Impl_ { + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr name_; + ::PROTOBUF_NAMESPACE_ID::Any* value_; + mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_; + }; + union { Impl_ _impl_; }; + friend struct ::TableStruct_google_2fprotobuf_2ftype_2eproto; +}; +// =================================================================== + + +// =================================================================== + +#ifdef __GNUC__ + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wstrict-aliasing" +#endif // __GNUC__ +// Type + +// string name = 1; +inline void Type::clear_name() { + _impl_.name_.ClearToEmpty(); +} +inline const std::string& Type::name() const { + // @@protoc_insertion_point(field_get:google.protobuf.Type.name) + return _internal_name(); +} +template <typename ArgT0, typename... ArgT> +inline PROTOBUF_ALWAYS_INLINE +void Type::set_name(ArgT0&& arg0, ArgT... args) { + + _impl_.name_.Set(static_cast<ArgT0 &&>(arg0), args..., GetArenaForAllocation()); + // @@protoc_insertion_point(field_set:google.protobuf.Type.name) +} +inline std::string* Type::mutable_name() { + std::string* _s = _internal_mutable_name(); + // @@protoc_insertion_point(field_mutable:google.protobuf.Type.name) + return _s; +} +inline const std::string& Type::_internal_name() const { + return _impl_.name_.Get(); +} +inline void Type::_internal_set_name(const std::string& value) { + + _impl_.name_.Set(value, GetArenaForAllocation()); +} +inline std::string* Type::_internal_mutable_name() { + + return _impl_.name_.Mutable(GetArenaForAllocation()); +} +inline std::string* Type::release_name() { + // @@protoc_insertion_point(field_release:google.protobuf.Type.name) + return _impl_.name_.Release(); +} +inline void Type::set_allocated_name(std::string* name) { + if (name != nullptr) { + + } else { + + } + _impl_.name_.SetAllocated(name, GetArenaForAllocation()); +#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (_impl_.name_.IsDefault()) { + _impl_.name_.Set("", GetArenaForAllocation()); + } +#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + // @@protoc_insertion_point(field_set_allocated:google.protobuf.Type.name) +} + +// repeated .google.protobuf.Field fields = 2; +inline int Type::_internal_fields_size() const { + return _impl_.fields_.size(); +} +inline int Type::fields_size() const { + return _internal_fields_size(); +} +inline void Type::clear_fields() { + _impl_.fields_.Clear(); +} +inline ::PROTOBUF_NAMESPACE_ID::Field* Type::mutable_fields(int index) { + // @@protoc_insertion_point(field_mutable:google.protobuf.Type.fields) + return _impl_.fields_.Mutable(index); +} +inline ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::Field >* +Type::mutable_fields() { + // @@protoc_insertion_point(field_mutable_list:google.protobuf.Type.fields) + return &_impl_.fields_; +} +inline const ::PROTOBUF_NAMESPACE_ID::Field& Type::_internal_fields(int index) const { + return _impl_.fields_.Get(index); +} +inline const ::PROTOBUF_NAMESPACE_ID::Field& Type::fields(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.Type.fields) + return _internal_fields(index); +} +inline ::PROTOBUF_NAMESPACE_ID::Field* Type::_internal_add_fields() { + return _impl_.fields_.Add(); +} +inline ::PROTOBUF_NAMESPACE_ID::Field* Type::add_fields() { + ::PROTOBUF_NAMESPACE_ID::Field* _add = _internal_add_fields(); + // @@protoc_insertion_point(field_add:google.protobuf.Type.fields) + return _add; +} +inline const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::Field >& +Type::fields() const { + // @@protoc_insertion_point(field_list:google.protobuf.Type.fields) + return _impl_.fields_; +} + +// repeated string oneofs = 3; +inline int Type::_internal_oneofs_size() const { + return _impl_.oneofs_.size(); +} +inline int Type::oneofs_size() const { + return _internal_oneofs_size(); +} +inline void Type::clear_oneofs() { + _impl_.oneofs_.Clear(); +} +inline std::string* Type::add_oneofs() { + std::string* _s = _internal_add_oneofs(); + // @@protoc_insertion_point(field_add_mutable:google.protobuf.Type.oneofs) + return _s; +} +inline const std::string& Type::_internal_oneofs(int index) const { + return _impl_.oneofs_.Get(index); +} +inline const std::string& Type::oneofs(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.Type.oneofs) + return _internal_oneofs(index); +} +inline std::string* Type::mutable_oneofs(int index) { + // @@protoc_insertion_point(field_mutable:google.protobuf.Type.oneofs) + return _impl_.oneofs_.Mutable(index); +} +inline void Type::set_oneofs(int index, const std::string& value) { + _impl_.oneofs_.Mutable(index)->assign(value); + // @@protoc_insertion_point(field_set:google.protobuf.Type.oneofs) +} +inline void Type::set_oneofs(int index, std::string&& value) { + _impl_.oneofs_.Mutable(index)->assign(std::move(value)); + // @@protoc_insertion_point(field_set:google.protobuf.Type.oneofs) +} +inline void Type::set_oneofs(int index, const char* value) { + GOOGLE_DCHECK(value != nullptr); + _impl_.oneofs_.Mutable(index)->assign(value); + // @@protoc_insertion_point(field_set_char:google.protobuf.Type.oneofs) +} +inline void Type::set_oneofs(int index, const char* value, size_t size) { + _impl_.oneofs_.Mutable(index)->assign( + reinterpret_cast<const char*>(value), size); + // @@protoc_insertion_point(field_set_pointer:google.protobuf.Type.oneofs) +} +inline std::string* Type::_internal_add_oneofs() { + return _impl_.oneofs_.Add(); +} +inline void Type::add_oneofs(const std::string& value) { + _impl_.oneofs_.Add()->assign(value); + // @@protoc_insertion_point(field_add:google.protobuf.Type.oneofs) +} +inline void Type::add_oneofs(std::string&& value) { + _impl_.oneofs_.Add(std::move(value)); + // @@protoc_insertion_point(field_add:google.protobuf.Type.oneofs) +} +inline void Type::add_oneofs(const char* value) { + GOOGLE_DCHECK(value != nullptr); + _impl_.oneofs_.Add()->assign(value); + // @@protoc_insertion_point(field_add_char:google.protobuf.Type.oneofs) +} +inline void Type::add_oneofs(const char* value, size_t size) { + _impl_.oneofs_.Add()->assign(reinterpret_cast<const char*>(value), size); + // @@protoc_insertion_point(field_add_pointer:google.protobuf.Type.oneofs) +} +inline const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField<std::string>& +Type::oneofs() const { + // @@protoc_insertion_point(field_list:google.protobuf.Type.oneofs) + return _impl_.oneofs_; +} +inline ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField<std::string>* +Type::mutable_oneofs() { + // @@protoc_insertion_point(field_mutable_list:google.protobuf.Type.oneofs) + return &_impl_.oneofs_; +} + +// repeated .google.protobuf.Option options = 4; +inline int Type::_internal_options_size() const { + return _impl_.options_.size(); +} +inline int Type::options_size() const { + return _internal_options_size(); +} +inline void Type::clear_options() { + _impl_.options_.Clear(); +} +inline ::PROTOBUF_NAMESPACE_ID::Option* Type::mutable_options(int index) { + // @@protoc_insertion_point(field_mutable:google.protobuf.Type.options) + return _impl_.options_.Mutable(index); +} +inline ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::Option >* +Type::mutable_options() { + // @@protoc_insertion_point(field_mutable_list:google.protobuf.Type.options) + return &_impl_.options_; +} +inline const ::PROTOBUF_NAMESPACE_ID::Option& Type::_internal_options(int index) const { + return _impl_.options_.Get(index); +} +inline const ::PROTOBUF_NAMESPACE_ID::Option& Type::options(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.Type.options) + return _internal_options(index); +} +inline ::PROTOBUF_NAMESPACE_ID::Option* Type::_internal_add_options() { + return _impl_.options_.Add(); +} +inline ::PROTOBUF_NAMESPACE_ID::Option* Type::add_options() { + ::PROTOBUF_NAMESPACE_ID::Option* _add = _internal_add_options(); + // @@protoc_insertion_point(field_add:google.protobuf.Type.options) + return _add; +} +inline const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::Option >& +Type::options() const { + // @@protoc_insertion_point(field_list:google.protobuf.Type.options) + return _impl_.options_; +} + +// .google.protobuf.SourceContext source_context = 5; +inline bool Type::_internal_has_source_context() const { + return this != internal_default_instance() && _impl_.source_context_ != nullptr; +} +inline bool Type::has_source_context() const { + return _internal_has_source_context(); +} +inline const ::PROTOBUF_NAMESPACE_ID::SourceContext& Type::_internal_source_context() const { + const ::PROTOBUF_NAMESPACE_ID::SourceContext* p = _impl_.source_context_; + return p != nullptr ? *p : reinterpret_cast<const ::PROTOBUF_NAMESPACE_ID::SourceContext&>( + ::PROTOBUF_NAMESPACE_ID::_SourceContext_default_instance_); +} +inline const ::PROTOBUF_NAMESPACE_ID::SourceContext& Type::source_context() const { + // @@protoc_insertion_point(field_get:google.protobuf.Type.source_context) + return _internal_source_context(); +} +inline void Type::unsafe_arena_set_allocated_source_context( + ::PROTOBUF_NAMESPACE_ID::SourceContext* source_context) { + if (GetArenaForAllocation() == nullptr) { + delete reinterpret_cast<::PROTOBUF_NAMESPACE_ID::MessageLite*>(_impl_.source_context_); + } + _impl_.source_context_ = source_context; + if (source_context) { + + } else { + + } + // @@protoc_insertion_point(field_unsafe_arena_set_allocated:google.protobuf.Type.source_context) +} +inline ::PROTOBUF_NAMESPACE_ID::SourceContext* Type::release_source_context() { + + ::PROTOBUF_NAMESPACE_ID::SourceContext* temp = _impl_.source_context_; + _impl_.source_context_ = nullptr; +#ifdef PROTOBUF_FORCE_COPY_IN_RELEASE + auto* old = reinterpret_cast<::PROTOBUF_NAMESPACE_ID::MessageLite*>(temp); + temp = ::PROTOBUF_NAMESPACE_ID::internal::DuplicateIfNonNull(temp); + if (GetArenaForAllocation() == nullptr) { delete old; } +#else // PROTOBUF_FORCE_COPY_IN_RELEASE + if (GetArenaForAllocation() != nullptr) { + temp = ::PROTOBUF_NAMESPACE_ID::internal::DuplicateIfNonNull(temp); + } +#endif // !PROTOBUF_FORCE_COPY_IN_RELEASE + return temp; +} +inline ::PROTOBUF_NAMESPACE_ID::SourceContext* Type::unsafe_arena_release_source_context() { + // @@protoc_insertion_point(field_release:google.protobuf.Type.source_context) + + ::PROTOBUF_NAMESPACE_ID::SourceContext* temp = _impl_.source_context_; + _impl_.source_context_ = nullptr; + return temp; +} +inline ::PROTOBUF_NAMESPACE_ID::SourceContext* Type::_internal_mutable_source_context() { + + if (_impl_.source_context_ == nullptr) { + auto* p = CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::SourceContext>(GetArenaForAllocation()); + _impl_.source_context_ = p; + } + return _impl_.source_context_; +} +inline ::PROTOBUF_NAMESPACE_ID::SourceContext* Type::mutable_source_context() { + ::PROTOBUF_NAMESPACE_ID::SourceContext* _msg = _internal_mutable_source_context(); + // @@protoc_insertion_point(field_mutable:google.protobuf.Type.source_context) + return _msg; +} +inline void Type::set_allocated_source_context(::PROTOBUF_NAMESPACE_ID::SourceContext* source_context) { + ::PROTOBUF_NAMESPACE_ID::Arena* message_arena = GetArenaForAllocation(); + if (message_arena == nullptr) { + delete reinterpret_cast< ::PROTOBUF_NAMESPACE_ID::MessageLite*>(_impl_.source_context_); + } + if (source_context) { + ::PROTOBUF_NAMESPACE_ID::Arena* submessage_arena = + ::PROTOBUF_NAMESPACE_ID::Arena::InternalGetOwningArena( + reinterpret_cast<::PROTOBUF_NAMESPACE_ID::MessageLite*>(source_context)); + if (message_arena != submessage_arena) { + source_context = ::PROTOBUF_NAMESPACE_ID::internal::GetOwnedMessage( + message_arena, source_context, submessage_arena); + } + + } else { + + } + _impl_.source_context_ = source_context; + // @@protoc_insertion_point(field_set_allocated:google.protobuf.Type.source_context) +} + +// .google.protobuf.Syntax syntax = 6; +inline void Type::clear_syntax() { + _impl_.syntax_ = 0; +} +inline ::PROTOBUF_NAMESPACE_ID::Syntax Type::_internal_syntax() const { + return static_cast< ::PROTOBUF_NAMESPACE_ID::Syntax >(_impl_.syntax_); +} +inline ::PROTOBUF_NAMESPACE_ID::Syntax Type::syntax() const { + // @@protoc_insertion_point(field_get:google.protobuf.Type.syntax) + return _internal_syntax(); +} +inline void Type::_internal_set_syntax(::PROTOBUF_NAMESPACE_ID::Syntax value) { + + _impl_.syntax_ = value; +} +inline void Type::set_syntax(::PROTOBUF_NAMESPACE_ID::Syntax value) { + _internal_set_syntax(value); + // @@protoc_insertion_point(field_set:google.protobuf.Type.syntax) +} + +// ------------------------------------------------------------------- + +// Field + +// .google.protobuf.Field.Kind kind = 1; +inline void Field::clear_kind() { + _impl_.kind_ = 0; +} +inline ::PROTOBUF_NAMESPACE_ID::Field_Kind Field::_internal_kind() const { + return static_cast< ::PROTOBUF_NAMESPACE_ID::Field_Kind >(_impl_.kind_); +} +inline ::PROTOBUF_NAMESPACE_ID::Field_Kind Field::kind() const { + // @@protoc_insertion_point(field_get:google.protobuf.Field.kind) + return _internal_kind(); +} +inline void Field::_internal_set_kind(::PROTOBUF_NAMESPACE_ID::Field_Kind value) { + + _impl_.kind_ = value; +} +inline void Field::set_kind(::PROTOBUF_NAMESPACE_ID::Field_Kind value) { + _internal_set_kind(value); + // @@protoc_insertion_point(field_set:google.protobuf.Field.kind) +} + +// .google.protobuf.Field.Cardinality cardinality = 2; +inline void Field::clear_cardinality() { + _impl_.cardinality_ = 0; +} +inline ::PROTOBUF_NAMESPACE_ID::Field_Cardinality Field::_internal_cardinality() const { + return static_cast< ::PROTOBUF_NAMESPACE_ID::Field_Cardinality >(_impl_.cardinality_); +} +inline ::PROTOBUF_NAMESPACE_ID::Field_Cardinality Field::cardinality() const { + // @@protoc_insertion_point(field_get:google.protobuf.Field.cardinality) + return _internal_cardinality(); +} +inline void Field::_internal_set_cardinality(::PROTOBUF_NAMESPACE_ID::Field_Cardinality value) { + + _impl_.cardinality_ = value; +} +inline void Field::set_cardinality(::PROTOBUF_NAMESPACE_ID::Field_Cardinality value) { + _internal_set_cardinality(value); + // @@protoc_insertion_point(field_set:google.protobuf.Field.cardinality) +} + +// int32 number = 3; +inline void Field::clear_number() { + _impl_.number_ = 0; +} +inline int32_t Field::_internal_number() const { + return _impl_.number_; +} +inline int32_t Field::number() const { + // @@protoc_insertion_point(field_get:google.protobuf.Field.number) + return _internal_number(); +} +inline void Field::_internal_set_number(int32_t value) { + + _impl_.number_ = value; +} +inline void Field::set_number(int32_t value) { + _internal_set_number(value); + // @@protoc_insertion_point(field_set:google.protobuf.Field.number) +} + +// string name = 4; +inline void Field::clear_name() { + _impl_.name_.ClearToEmpty(); +} +inline const std::string& Field::name() const { + // @@protoc_insertion_point(field_get:google.protobuf.Field.name) + return _internal_name(); +} +template <typename ArgT0, typename... ArgT> +inline PROTOBUF_ALWAYS_INLINE +void Field::set_name(ArgT0&& arg0, ArgT... args) { + + _impl_.name_.Set(static_cast<ArgT0 &&>(arg0), args..., GetArenaForAllocation()); + // @@protoc_insertion_point(field_set:google.protobuf.Field.name) +} +inline std::string* Field::mutable_name() { + std::string* _s = _internal_mutable_name(); + // @@protoc_insertion_point(field_mutable:google.protobuf.Field.name) + return _s; +} +inline const std::string& Field::_internal_name() const { + return _impl_.name_.Get(); +} +inline void Field::_internal_set_name(const std::string& value) { + + _impl_.name_.Set(value, GetArenaForAllocation()); +} +inline std::string* Field::_internal_mutable_name() { + + return _impl_.name_.Mutable(GetArenaForAllocation()); +} +inline std::string* Field::release_name() { + // @@protoc_insertion_point(field_release:google.protobuf.Field.name) + return _impl_.name_.Release(); +} +inline void Field::set_allocated_name(std::string* name) { + if (name != nullptr) { + + } else { + + } + _impl_.name_.SetAllocated(name, GetArenaForAllocation()); +#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (_impl_.name_.IsDefault()) { + _impl_.name_.Set("", GetArenaForAllocation()); + } +#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + // @@protoc_insertion_point(field_set_allocated:google.protobuf.Field.name) +} + +// string type_url = 6; +inline void Field::clear_type_url() { + _impl_.type_url_.ClearToEmpty(); +} +inline const std::string& Field::type_url() const { + // @@protoc_insertion_point(field_get:google.protobuf.Field.type_url) + return _internal_type_url(); +} +template <typename ArgT0, typename... ArgT> +inline PROTOBUF_ALWAYS_INLINE +void Field::set_type_url(ArgT0&& arg0, ArgT... args) { + + _impl_.type_url_.Set(static_cast<ArgT0 &&>(arg0), args..., GetArenaForAllocation()); + // @@protoc_insertion_point(field_set:google.protobuf.Field.type_url) +} +inline std::string* Field::mutable_type_url() { + std::string* _s = _internal_mutable_type_url(); + // @@protoc_insertion_point(field_mutable:google.protobuf.Field.type_url) + return _s; +} +inline const std::string& Field::_internal_type_url() const { + return _impl_.type_url_.Get(); +} +inline void Field::_internal_set_type_url(const std::string& value) { + + _impl_.type_url_.Set(value, GetArenaForAllocation()); +} +inline std::string* Field::_internal_mutable_type_url() { + + return _impl_.type_url_.Mutable(GetArenaForAllocation()); +} +inline std::string* Field::release_type_url() { + // @@protoc_insertion_point(field_release:google.protobuf.Field.type_url) + return _impl_.type_url_.Release(); +} +inline void Field::set_allocated_type_url(std::string* type_url) { + if (type_url != nullptr) { + + } else { + + } + _impl_.type_url_.SetAllocated(type_url, GetArenaForAllocation()); +#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (_impl_.type_url_.IsDefault()) { + _impl_.type_url_.Set("", GetArenaForAllocation()); + } +#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + // @@protoc_insertion_point(field_set_allocated:google.protobuf.Field.type_url) +} + +// int32 oneof_index = 7; +inline void Field::clear_oneof_index() { + _impl_.oneof_index_ = 0; +} +inline int32_t Field::_internal_oneof_index() const { + return _impl_.oneof_index_; +} +inline int32_t Field::oneof_index() const { + // @@protoc_insertion_point(field_get:google.protobuf.Field.oneof_index) + return _internal_oneof_index(); +} +inline void Field::_internal_set_oneof_index(int32_t value) { + + _impl_.oneof_index_ = value; +} +inline void Field::set_oneof_index(int32_t value) { + _internal_set_oneof_index(value); + // @@protoc_insertion_point(field_set:google.protobuf.Field.oneof_index) +} + +// bool packed = 8; +inline void Field::clear_packed() { + _impl_.packed_ = false; +} +inline bool Field::_internal_packed() const { + return _impl_.packed_; +} +inline bool Field::packed() const { + // @@protoc_insertion_point(field_get:google.protobuf.Field.packed) + return _internal_packed(); +} +inline void Field::_internal_set_packed(bool value) { + + _impl_.packed_ = value; +} +inline void Field::set_packed(bool value) { + _internal_set_packed(value); + // @@protoc_insertion_point(field_set:google.protobuf.Field.packed) +} + +// repeated .google.protobuf.Option options = 9; +inline int Field::_internal_options_size() const { + return _impl_.options_.size(); +} +inline int Field::options_size() const { + return _internal_options_size(); +} +inline void Field::clear_options() { + _impl_.options_.Clear(); +} +inline ::PROTOBUF_NAMESPACE_ID::Option* Field::mutable_options(int index) { + // @@protoc_insertion_point(field_mutable:google.protobuf.Field.options) + return _impl_.options_.Mutable(index); +} +inline ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::Option >* +Field::mutable_options() { + // @@protoc_insertion_point(field_mutable_list:google.protobuf.Field.options) + return &_impl_.options_; +} +inline const ::PROTOBUF_NAMESPACE_ID::Option& Field::_internal_options(int index) const { + return _impl_.options_.Get(index); +} +inline const ::PROTOBUF_NAMESPACE_ID::Option& Field::options(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.Field.options) + return _internal_options(index); +} +inline ::PROTOBUF_NAMESPACE_ID::Option* Field::_internal_add_options() { + return _impl_.options_.Add(); +} +inline ::PROTOBUF_NAMESPACE_ID::Option* Field::add_options() { + ::PROTOBUF_NAMESPACE_ID::Option* _add = _internal_add_options(); + // @@protoc_insertion_point(field_add:google.protobuf.Field.options) + return _add; +} +inline const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::Option >& +Field::options() const { + // @@protoc_insertion_point(field_list:google.protobuf.Field.options) + return _impl_.options_; +} + +// string json_name = 10; +inline void Field::clear_json_name() { + _impl_.json_name_.ClearToEmpty(); +} +inline const std::string& Field::json_name() const { + // @@protoc_insertion_point(field_get:google.protobuf.Field.json_name) + return _internal_json_name(); +} +template <typename ArgT0, typename... ArgT> +inline PROTOBUF_ALWAYS_INLINE +void Field::set_json_name(ArgT0&& arg0, ArgT... args) { + + _impl_.json_name_.Set(static_cast<ArgT0 &&>(arg0), args..., GetArenaForAllocation()); + // @@protoc_insertion_point(field_set:google.protobuf.Field.json_name) +} +inline std::string* Field::mutable_json_name() { + std::string* _s = _internal_mutable_json_name(); + // @@protoc_insertion_point(field_mutable:google.protobuf.Field.json_name) + return _s; +} +inline const std::string& Field::_internal_json_name() const { + return _impl_.json_name_.Get(); +} +inline void Field::_internal_set_json_name(const std::string& value) { + + _impl_.json_name_.Set(value, GetArenaForAllocation()); +} +inline std::string* Field::_internal_mutable_json_name() { + + return _impl_.json_name_.Mutable(GetArenaForAllocation()); +} +inline std::string* Field::release_json_name() { + // @@protoc_insertion_point(field_release:google.protobuf.Field.json_name) + return _impl_.json_name_.Release(); +} +inline void Field::set_allocated_json_name(std::string* json_name) { + if (json_name != nullptr) { + + } else { + + } + _impl_.json_name_.SetAllocated(json_name, GetArenaForAllocation()); +#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (_impl_.json_name_.IsDefault()) { + _impl_.json_name_.Set("", GetArenaForAllocation()); + } +#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + // @@protoc_insertion_point(field_set_allocated:google.protobuf.Field.json_name) +} + +// string default_value = 11; +inline void Field::clear_default_value() { + _impl_.default_value_.ClearToEmpty(); +} +inline const std::string& Field::default_value() const { + // @@protoc_insertion_point(field_get:google.protobuf.Field.default_value) + return _internal_default_value(); +} +template <typename ArgT0, typename... ArgT> +inline PROTOBUF_ALWAYS_INLINE +void Field::set_default_value(ArgT0&& arg0, ArgT... args) { + + _impl_.default_value_.Set(static_cast<ArgT0 &&>(arg0), args..., GetArenaForAllocation()); + // @@protoc_insertion_point(field_set:google.protobuf.Field.default_value) +} +inline std::string* Field::mutable_default_value() { + std::string* _s = _internal_mutable_default_value(); + // @@protoc_insertion_point(field_mutable:google.protobuf.Field.default_value) + return _s; +} +inline const std::string& Field::_internal_default_value() const { + return _impl_.default_value_.Get(); +} +inline void Field::_internal_set_default_value(const std::string& value) { + + _impl_.default_value_.Set(value, GetArenaForAllocation()); +} +inline std::string* Field::_internal_mutable_default_value() { + + return _impl_.default_value_.Mutable(GetArenaForAllocation()); +} +inline std::string* Field::release_default_value() { + // @@protoc_insertion_point(field_release:google.protobuf.Field.default_value) + return _impl_.default_value_.Release(); +} +inline void Field::set_allocated_default_value(std::string* default_value) { + if (default_value != nullptr) { + + } else { + + } + _impl_.default_value_.SetAllocated(default_value, GetArenaForAllocation()); +#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (_impl_.default_value_.IsDefault()) { + _impl_.default_value_.Set("", GetArenaForAllocation()); + } +#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + // @@protoc_insertion_point(field_set_allocated:google.protobuf.Field.default_value) +} + +// ------------------------------------------------------------------- + +// Enum + +// string name = 1; +inline void Enum::clear_name() { + _impl_.name_.ClearToEmpty(); +} +inline const std::string& Enum::name() const { + // @@protoc_insertion_point(field_get:google.protobuf.Enum.name) + return _internal_name(); +} +template <typename ArgT0, typename... ArgT> +inline PROTOBUF_ALWAYS_INLINE +void Enum::set_name(ArgT0&& arg0, ArgT... args) { + + _impl_.name_.Set(static_cast<ArgT0 &&>(arg0), args..., GetArenaForAllocation()); + // @@protoc_insertion_point(field_set:google.protobuf.Enum.name) +} +inline std::string* Enum::mutable_name() { + std::string* _s = _internal_mutable_name(); + // @@protoc_insertion_point(field_mutable:google.protobuf.Enum.name) + return _s; +} +inline const std::string& Enum::_internal_name() const { + return _impl_.name_.Get(); +} +inline void Enum::_internal_set_name(const std::string& value) { + + _impl_.name_.Set(value, GetArenaForAllocation()); +} +inline std::string* Enum::_internal_mutable_name() { + + return _impl_.name_.Mutable(GetArenaForAllocation()); +} +inline std::string* Enum::release_name() { + // @@protoc_insertion_point(field_release:google.protobuf.Enum.name) + return _impl_.name_.Release(); +} +inline void Enum::set_allocated_name(std::string* name) { + if (name != nullptr) { + + } else { + + } + _impl_.name_.SetAllocated(name, GetArenaForAllocation()); +#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (_impl_.name_.IsDefault()) { + _impl_.name_.Set("", GetArenaForAllocation()); + } +#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + // @@protoc_insertion_point(field_set_allocated:google.protobuf.Enum.name) +} + +// repeated .google.protobuf.EnumValue enumvalue = 2; +inline int Enum::_internal_enumvalue_size() const { + return _impl_.enumvalue_.size(); +} +inline int Enum::enumvalue_size() const { + return _internal_enumvalue_size(); +} +inline void Enum::clear_enumvalue() { + _impl_.enumvalue_.Clear(); +} +inline ::PROTOBUF_NAMESPACE_ID::EnumValue* Enum::mutable_enumvalue(int index) { + // @@protoc_insertion_point(field_mutable:google.protobuf.Enum.enumvalue) + return _impl_.enumvalue_.Mutable(index); +} +inline ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::EnumValue >* +Enum::mutable_enumvalue() { + // @@protoc_insertion_point(field_mutable_list:google.protobuf.Enum.enumvalue) + return &_impl_.enumvalue_; +} +inline const ::PROTOBUF_NAMESPACE_ID::EnumValue& Enum::_internal_enumvalue(int index) const { + return _impl_.enumvalue_.Get(index); +} +inline const ::PROTOBUF_NAMESPACE_ID::EnumValue& Enum::enumvalue(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.Enum.enumvalue) + return _internal_enumvalue(index); +} +inline ::PROTOBUF_NAMESPACE_ID::EnumValue* Enum::_internal_add_enumvalue() { + return _impl_.enumvalue_.Add(); +} +inline ::PROTOBUF_NAMESPACE_ID::EnumValue* Enum::add_enumvalue() { + ::PROTOBUF_NAMESPACE_ID::EnumValue* _add = _internal_add_enumvalue(); + // @@protoc_insertion_point(field_add:google.protobuf.Enum.enumvalue) + return _add; +} +inline const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::EnumValue >& +Enum::enumvalue() const { + // @@protoc_insertion_point(field_list:google.protobuf.Enum.enumvalue) + return _impl_.enumvalue_; +} + +// repeated .google.protobuf.Option options = 3; +inline int Enum::_internal_options_size() const { + return _impl_.options_.size(); +} +inline int Enum::options_size() const { + return _internal_options_size(); +} +inline void Enum::clear_options() { + _impl_.options_.Clear(); +} +inline ::PROTOBUF_NAMESPACE_ID::Option* Enum::mutable_options(int index) { + // @@protoc_insertion_point(field_mutable:google.protobuf.Enum.options) + return _impl_.options_.Mutable(index); +} +inline ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::Option >* +Enum::mutable_options() { + // @@protoc_insertion_point(field_mutable_list:google.protobuf.Enum.options) + return &_impl_.options_; +} +inline const ::PROTOBUF_NAMESPACE_ID::Option& Enum::_internal_options(int index) const { + return _impl_.options_.Get(index); +} +inline const ::PROTOBUF_NAMESPACE_ID::Option& Enum::options(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.Enum.options) + return _internal_options(index); +} +inline ::PROTOBUF_NAMESPACE_ID::Option* Enum::_internal_add_options() { + return _impl_.options_.Add(); +} +inline ::PROTOBUF_NAMESPACE_ID::Option* Enum::add_options() { + ::PROTOBUF_NAMESPACE_ID::Option* _add = _internal_add_options(); + // @@protoc_insertion_point(field_add:google.protobuf.Enum.options) + return _add; +} +inline const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::Option >& +Enum::options() const { + // @@protoc_insertion_point(field_list:google.protobuf.Enum.options) + return _impl_.options_; +} + +// .google.protobuf.SourceContext source_context = 4; +inline bool Enum::_internal_has_source_context() const { + return this != internal_default_instance() && _impl_.source_context_ != nullptr; +} +inline bool Enum::has_source_context() const { + return _internal_has_source_context(); +} +inline const ::PROTOBUF_NAMESPACE_ID::SourceContext& Enum::_internal_source_context() const { + const ::PROTOBUF_NAMESPACE_ID::SourceContext* p = _impl_.source_context_; + return p != nullptr ? *p : reinterpret_cast<const ::PROTOBUF_NAMESPACE_ID::SourceContext&>( + ::PROTOBUF_NAMESPACE_ID::_SourceContext_default_instance_); +} +inline const ::PROTOBUF_NAMESPACE_ID::SourceContext& Enum::source_context() const { + // @@protoc_insertion_point(field_get:google.protobuf.Enum.source_context) + return _internal_source_context(); +} +inline void Enum::unsafe_arena_set_allocated_source_context( + ::PROTOBUF_NAMESPACE_ID::SourceContext* source_context) { + if (GetArenaForAllocation() == nullptr) { + delete reinterpret_cast<::PROTOBUF_NAMESPACE_ID::MessageLite*>(_impl_.source_context_); + } + _impl_.source_context_ = source_context; + if (source_context) { + + } else { + + } + // @@protoc_insertion_point(field_unsafe_arena_set_allocated:google.protobuf.Enum.source_context) +} +inline ::PROTOBUF_NAMESPACE_ID::SourceContext* Enum::release_source_context() { + + ::PROTOBUF_NAMESPACE_ID::SourceContext* temp = _impl_.source_context_; + _impl_.source_context_ = nullptr; +#ifdef PROTOBUF_FORCE_COPY_IN_RELEASE + auto* old = reinterpret_cast<::PROTOBUF_NAMESPACE_ID::MessageLite*>(temp); + temp = ::PROTOBUF_NAMESPACE_ID::internal::DuplicateIfNonNull(temp); + if (GetArenaForAllocation() == nullptr) { delete old; } +#else // PROTOBUF_FORCE_COPY_IN_RELEASE + if (GetArenaForAllocation() != nullptr) { + temp = ::PROTOBUF_NAMESPACE_ID::internal::DuplicateIfNonNull(temp); + } +#endif // !PROTOBUF_FORCE_COPY_IN_RELEASE + return temp; +} +inline ::PROTOBUF_NAMESPACE_ID::SourceContext* Enum::unsafe_arena_release_source_context() { + // @@protoc_insertion_point(field_release:google.protobuf.Enum.source_context) + + ::PROTOBUF_NAMESPACE_ID::SourceContext* temp = _impl_.source_context_; + _impl_.source_context_ = nullptr; + return temp; +} +inline ::PROTOBUF_NAMESPACE_ID::SourceContext* Enum::_internal_mutable_source_context() { + + if (_impl_.source_context_ == nullptr) { + auto* p = CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::SourceContext>(GetArenaForAllocation()); + _impl_.source_context_ = p; + } + return _impl_.source_context_; +} +inline ::PROTOBUF_NAMESPACE_ID::SourceContext* Enum::mutable_source_context() { + ::PROTOBUF_NAMESPACE_ID::SourceContext* _msg = _internal_mutable_source_context(); + // @@protoc_insertion_point(field_mutable:google.protobuf.Enum.source_context) + return _msg; +} +inline void Enum::set_allocated_source_context(::PROTOBUF_NAMESPACE_ID::SourceContext* source_context) { + ::PROTOBUF_NAMESPACE_ID::Arena* message_arena = GetArenaForAllocation(); + if (message_arena == nullptr) { + delete reinterpret_cast< ::PROTOBUF_NAMESPACE_ID::MessageLite*>(_impl_.source_context_); + } + if (source_context) { + ::PROTOBUF_NAMESPACE_ID::Arena* submessage_arena = + ::PROTOBUF_NAMESPACE_ID::Arena::InternalGetOwningArena( + reinterpret_cast<::PROTOBUF_NAMESPACE_ID::MessageLite*>(source_context)); + if (message_arena != submessage_arena) { + source_context = ::PROTOBUF_NAMESPACE_ID::internal::GetOwnedMessage( + message_arena, source_context, submessage_arena); + } + + } else { + + } + _impl_.source_context_ = source_context; + // @@protoc_insertion_point(field_set_allocated:google.protobuf.Enum.source_context) +} + +// .google.protobuf.Syntax syntax = 5; +inline void Enum::clear_syntax() { + _impl_.syntax_ = 0; +} +inline ::PROTOBUF_NAMESPACE_ID::Syntax Enum::_internal_syntax() const { + return static_cast< ::PROTOBUF_NAMESPACE_ID::Syntax >(_impl_.syntax_); +} +inline ::PROTOBUF_NAMESPACE_ID::Syntax Enum::syntax() const { + // @@protoc_insertion_point(field_get:google.protobuf.Enum.syntax) + return _internal_syntax(); +} +inline void Enum::_internal_set_syntax(::PROTOBUF_NAMESPACE_ID::Syntax value) { + + _impl_.syntax_ = value; +} +inline void Enum::set_syntax(::PROTOBUF_NAMESPACE_ID::Syntax value) { + _internal_set_syntax(value); + // @@protoc_insertion_point(field_set:google.protobuf.Enum.syntax) +} + +// ------------------------------------------------------------------- + +// EnumValue + +// string name = 1; +inline void EnumValue::clear_name() { + _impl_.name_.ClearToEmpty(); +} +inline const std::string& EnumValue::name() const { + // @@protoc_insertion_point(field_get:google.protobuf.EnumValue.name) + return _internal_name(); +} +template <typename ArgT0, typename... ArgT> +inline PROTOBUF_ALWAYS_INLINE +void EnumValue::set_name(ArgT0&& arg0, ArgT... args) { + + _impl_.name_.Set(static_cast<ArgT0 &&>(arg0), args..., GetArenaForAllocation()); + // @@protoc_insertion_point(field_set:google.protobuf.EnumValue.name) +} +inline std::string* EnumValue::mutable_name() { + std::string* _s = _internal_mutable_name(); + // @@protoc_insertion_point(field_mutable:google.protobuf.EnumValue.name) + return _s; +} +inline const std::string& EnumValue::_internal_name() const { + return _impl_.name_.Get(); +} +inline void EnumValue::_internal_set_name(const std::string& value) { + + _impl_.name_.Set(value, GetArenaForAllocation()); +} +inline std::string* EnumValue::_internal_mutable_name() { + + return _impl_.name_.Mutable(GetArenaForAllocation()); +} +inline std::string* EnumValue::release_name() { + // @@protoc_insertion_point(field_release:google.protobuf.EnumValue.name) + return _impl_.name_.Release(); +} +inline void EnumValue::set_allocated_name(std::string* name) { + if (name != nullptr) { + + } else { + + } + _impl_.name_.SetAllocated(name, GetArenaForAllocation()); +#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (_impl_.name_.IsDefault()) { + _impl_.name_.Set("", GetArenaForAllocation()); + } +#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + // @@protoc_insertion_point(field_set_allocated:google.protobuf.EnumValue.name) +} + +// int32 number = 2; +inline void EnumValue::clear_number() { + _impl_.number_ = 0; +} +inline int32_t EnumValue::_internal_number() const { + return _impl_.number_; +} +inline int32_t EnumValue::number() const { + // @@protoc_insertion_point(field_get:google.protobuf.EnumValue.number) + return _internal_number(); +} +inline void EnumValue::_internal_set_number(int32_t value) { + + _impl_.number_ = value; +} +inline void EnumValue::set_number(int32_t value) { + _internal_set_number(value); + // @@protoc_insertion_point(field_set:google.protobuf.EnumValue.number) +} + +// repeated .google.protobuf.Option options = 3; +inline int EnumValue::_internal_options_size() const { + return _impl_.options_.size(); +} +inline int EnumValue::options_size() const { + return _internal_options_size(); +} +inline void EnumValue::clear_options() { + _impl_.options_.Clear(); +} +inline ::PROTOBUF_NAMESPACE_ID::Option* EnumValue::mutable_options(int index) { + // @@protoc_insertion_point(field_mutable:google.protobuf.EnumValue.options) + return _impl_.options_.Mutable(index); +} +inline ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::Option >* +EnumValue::mutable_options() { + // @@protoc_insertion_point(field_mutable_list:google.protobuf.EnumValue.options) + return &_impl_.options_; +} +inline const ::PROTOBUF_NAMESPACE_ID::Option& EnumValue::_internal_options(int index) const { + return _impl_.options_.Get(index); +} +inline const ::PROTOBUF_NAMESPACE_ID::Option& EnumValue::options(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.EnumValue.options) + return _internal_options(index); +} +inline ::PROTOBUF_NAMESPACE_ID::Option* EnumValue::_internal_add_options() { + return _impl_.options_.Add(); +} +inline ::PROTOBUF_NAMESPACE_ID::Option* EnumValue::add_options() { + ::PROTOBUF_NAMESPACE_ID::Option* _add = _internal_add_options(); + // @@protoc_insertion_point(field_add:google.protobuf.EnumValue.options) + return _add; +} +inline const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::Option >& +EnumValue::options() const { + // @@protoc_insertion_point(field_list:google.protobuf.EnumValue.options) + return _impl_.options_; +} + +// ------------------------------------------------------------------- + +// Option + +// string name = 1; +inline void Option::clear_name() { + _impl_.name_.ClearToEmpty(); +} +inline const std::string& Option::name() const { + // @@protoc_insertion_point(field_get:google.protobuf.Option.name) + return _internal_name(); +} +template <typename ArgT0, typename... ArgT> +inline PROTOBUF_ALWAYS_INLINE +void Option::set_name(ArgT0&& arg0, ArgT... args) { + + _impl_.name_.Set(static_cast<ArgT0 &&>(arg0), args..., GetArenaForAllocation()); + // @@protoc_insertion_point(field_set:google.protobuf.Option.name) +} +inline std::string* Option::mutable_name() { + std::string* _s = _internal_mutable_name(); + // @@protoc_insertion_point(field_mutable:google.protobuf.Option.name) + return _s; +} +inline const std::string& Option::_internal_name() const { + return _impl_.name_.Get(); +} +inline void Option::_internal_set_name(const std::string& value) { + + _impl_.name_.Set(value, GetArenaForAllocation()); +} +inline std::string* Option::_internal_mutable_name() { + + return _impl_.name_.Mutable(GetArenaForAllocation()); +} +inline std::string* Option::release_name() { + // @@protoc_insertion_point(field_release:google.protobuf.Option.name) + return _impl_.name_.Release(); +} +inline void Option::set_allocated_name(std::string* name) { + if (name != nullptr) { + + } else { + + } + _impl_.name_.SetAllocated(name, GetArenaForAllocation()); +#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (_impl_.name_.IsDefault()) { + _impl_.name_.Set("", GetArenaForAllocation()); + } +#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + // @@protoc_insertion_point(field_set_allocated:google.protobuf.Option.name) +} + +// .google.protobuf.Any value = 2; +inline bool Option::_internal_has_value() const { + return this != internal_default_instance() && _impl_.value_ != nullptr; +} +inline bool Option::has_value() const { + return _internal_has_value(); +} +inline const ::PROTOBUF_NAMESPACE_ID::Any& Option::_internal_value() const { + const ::PROTOBUF_NAMESPACE_ID::Any* p = _impl_.value_; + return p != nullptr ? *p : reinterpret_cast<const ::PROTOBUF_NAMESPACE_ID::Any&>( + ::PROTOBUF_NAMESPACE_ID::_Any_default_instance_); +} +inline const ::PROTOBUF_NAMESPACE_ID::Any& Option::value() const { + // @@protoc_insertion_point(field_get:google.protobuf.Option.value) + return _internal_value(); +} +inline void Option::unsafe_arena_set_allocated_value( + ::PROTOBUF_NAMESPACE_ID::Any* value) { + if (GetArenaForAllocation() == nullptr) { + delete reinterpret_cast<::PROTOBUF_NAMESPACE_ID::MessageLite*>(_impl_.value_); + } + _impl_.value_ = value; + if (value) { + + } else { + + } + // @@protoc_insertion_point(field_unsafe_arena_set_allocated:google.protobuf.Option.value) +} +inline ::PROTOBUF_NAMESPACE_ID::Any* Option::release_value() { + + ::PROTOBUF_NAMESPACE_ID::Any* temp = _impl_.value_; + _impl_.value_ = nullptr; +#ifdef PROTOBUF_FORCE_COPY_IN_RELEASE + auto* old = reinterpret_cast<::PROTOBUF_NAMESPACE_ID::MessageLite*>(temp); + temp = ::PROTOBUF_NAMESPACE_ID::internal::DuplicateIfNonNull(temp); + if (GetArenaForAllocation() == nullptr) { delete old; } +#else // PROTOBUF_FORCE_COPY_IN_RELEASE + if (GetArenaForAllocation() != nullptr) { + temp = ::PROTOBUF_NAMESPACE_ID::internal::DuplicateIfNonNull(temp); + } +#endif // !PROTOBUF_FORCE_COPY_IN_RELEASE + return temp; +} +inline ::PROTOBUF_NAMESPACE_ID::Any* Option::unsafe_arena_release_value() { + // @@protoc_insertion_point(field_release:google.protobuf.Option.value) + + ::PROTOBUF_NAMESPACE_ID::Any* temp = _impl_.value_; + _impl_.value_ = nullptr; + return temp; +} +inline ::PROTOBUF_NAMESPACE_ID::Any* Option::_internal_mutable_value() { + + if (_impl_.value_ == nullptr) { + auto* p = CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::Any>(GetArenaForAllocation()); + _impl_.value_ = p; + } + return _impl_.value_; +} +inline ::PROTOBUF_NAMESPACE_ID::Any* Option::mutable_value() { + ::PROTOBUF_NAMESPACE_ID::Any* _msg = _internal_mutable_value(); + // @@protoc_insertion_point(field_mutable:google.protobuf.Option.value) + return _msg; +} +inline void Option::set_allocated_value(::PROTOBUF_NAMESPACE_ID::Any* value) { + ::PROTOBUF_NAMESPACE_ID::Arena* message_arena = GetArenaForAllocation(); + if (message_arena == nullptr) { + delete reinterpret_cast< ::PROTOBUF_NAMESPACE_ID::MessageLite*>(_impl_.value_); + } + if (value) { + ::PROTOBUF_NAMESPACE_ID::Arena* submessage_arena = + ::PROTOBUF_NAMESPACE_ID::Arena::InternalGetOwningArena( + reinterpret_cast<::PROTOBUF_NAMESPACE_ID::MessageLite*>(value)); + if (message_arena != submessage_arena) { + value = ::PROTOBUF_NAMESPACE_ID::internal::GetOwnedMessage( + message_arena, value, submessage_arena); + } + + } else { + + } + _impl_.value_ = value; + // @@protoc_insertion_point(field_set_allocated:google.protobuf.Option.value) +} + +#ifdef __GNUC__ + #pragma GCC diagnostic pop +#endif // __GNUC__ +// ------------------------------------------------------------------- + +// ------------------------------------------------------------------- + +// ------------------------------------------------------------------- + +// ------------------------------------------------------------------- + + +// @@protoc_insertion_point(namespace_scope) + +PROTOBUF_NAMESPACE_CLOSE + +PROTOBUF_NAMESPACE_OPEN + +template <> struct is_proto_enum< ::PROTOBUF_NAMESPACE_ID::Field_Kind> : ::std::true_type {}; +template <> +inline const EnumDescriptor* GetEnumDescriptor< ::PROTOBUF_NAMESPACE_ID::Field_Kind>() { + return ::PROTOBUF_NAMESPACE_ID::Field_Kind_descriptor(); +} +template <> struct is_proto_enum< ::PROTOBUF_NAMESPACE_ID::Field_Cardinality> : ::std::true_type {}; +template <> +inline const EnumDescriptor* GetEnumDescriptor< ::PROTOBUF_NAMESPACE_ID::Field_Cardinality>() { + return ::PROTOBUF_NAMESPACE_ID::Field_Cardinality_descriptor(); +} +template <> struct is_proto_enum< ::PROTOBUF_NAMESPACE_ID::Syntax> : ::std::true_type {}; +template <> +inline const EnumDescriptor* GetEnumDescriptor< ::PROTOBUF_NAMESPACE_ID::Syntax>() { + return ::PROTOBUF_NAMESPACE_ID::Syntax_descriptor(); +} + +PROTOBUF_NAMESPACE_CLOSE + +// @@protoc_insertion_point(global_scope) + +#include <google/protobuf/port_undef.inc> +#endif // GOOGLE_PROTOBUF_INCLUDED_GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2ftype_2eproto diff --git a/toolkit/components/protobuf/src/google/protobuf/type.proto b/toolkit/components/protobuf/src/google/protobuf/type.proto new file mode 100644 index 0000000000..d3f6a68b83 --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/type.proto @@ -0,0 +1,187 @@ +// 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. + +syntax = "proto3"; + +package google.protobuf; + +import "google/protobuf/any.proto"; +import "google/protobuf/source_context.proto"; + +option csharp_namespace = "Google.Protobuf.WellKnownTypes"; +option cc_enable_arenas = true; +option java_package = "com.google.protobuf"; +option java_outer_classname = "TypeProto"; +option java_multiple_files = true; +option objc_class_prefix = "GPB"; +option go_package = "google.golang.org/protobuf/types/known/typepb"; + +// A protocol buffer message type. +message Type { + // The fully qualified message name. + string name = 1; + // The list of fields. + repeated Field fields = 2; + // The list of types appearing in `oneof` definitions in this type. + repeated string oneofs = 3; + // The protocol buffer options. + repeated Option options = 4; + // The source context. + SourceContext source_context = 5; + // The source syntax. + Syntax syntax = 6; +} + +// A single field of a message type. +message Field { + // Basic field types. + enum Kind { + // Field type unknown. + TYPE_UNKNOWN = 0; + // Field type double. + TYPE_DOUBLE = 1; + // Field type float. + TYPE_FLOAT = 2; + // Field type int64. + TYPE_INT64 = 3; + // Field type uint64. + TYPE_UINT64 = 4; + // Field type int32. + TYPE_INT32 = 5; + // Field type fixed64. + TYPE_FIXED64 = 6; + // Field type fixed32. + TYPE_FIXED32 = 7; + // Field type bool. + TYPE_BOOL = 8; + // Field type string. + TYPE_STRING = 9; + // Field type group. Proto2 syntax only, and deprecated. + TYPE_GROUP = 10; + // Field type message. + TYPE_MESSAGE = 11; + // Field type bytes. + TYPE_BYTES = 12; + // Field type uint32. + TYPE_UINT32 = 13; + // Field type enum. + TYPE_ENUM = 14; + // Field type sfixed32. + TYPE_SFIXED32 = 15; + // Field type sfixed64. + TYPE_SFIXED64 = 16; + // Field type sint32. + TYPE_SINT32 = 17; + // Field type sint64. + TYPE_SINT64 = 18; + } + + // Whether a field is optional, required, or repeated. + enum Cardinality { + // For fields with unknown cardinality. + CARDINALITY_UNKNOWN = 0; + // For optional fields. + CARDINALITY_OPTIONAL = 1; + // For required fields. Proto2 syntax only. + CARDINALITY_REQUIRED = 2; + // For repeated fields. + CARDINALITY_REPEATED = 3; + } + + // The field type. + Kind kind = 1; + // The field cardinality. + Cardinality cardinality = 2; + // The field number. + int32 number = 3; + // The field name. + string name = 4; + // The field type URL, without the scheme, for message or enumeration + // types. Example: `"type.googleapis.com/google.protobuf.Timestamp"`. + string type_url = 6; + // The index of the field type in `Type.oneofs`, for message or enumeration + // types. The first type has index 1; zero means the type is not in the list. + int32 oneof_index = 7; + // Whether to use alternative packed wire representation. + bool packed = 8; + // The protocol buffer options. + repeated Option options = 9; + // The field JSON name. + string json_name = 10; + // The string value of the default value of this field. Proto2 syntax only. + string default_value = 11; +} + +// Enum type definition. +message Enum { + // Enum type name. + string name = 1; + // Enum value definitions. + repeated EnumValue enumvalue = 2; + // Protocol buffer options. + repeated Option options = 3; + // The source context. + SourceContext source_context = 4; + // The source syntax. + Syntax syntax = 5; +} + +// Enum value definition. +message EnumValue { + // Enum value name. + string name = 1; + // Enum value number. + int32 number = 2; + // Protocol buffer options. + repeated Option options = 3; +} + +// A protocol buffer option, which can be attached to a message, field, +// enumeration, etc. +message Option { + // The option's name. For protobuf built-in options (options defined in + // descriptor.proto), this is the short name. For example, `"map_entry"`. + // For custom options, it should be the fully-qualified name. For example, + // `"google.api.http"`. + string name = 1; + // The option's value packed in an Any message. If the value is a primitive, + // the corresponding wrapper type defined in google/protobuf/wrappers.proto + // should be used. If the value is an enum, it should be stored as an int32 + // value using the google.protobuf.Int32Value type. + Any value = 2; +} + +// The syntax in which a protocol buffer element is defined. +enum Syntax { + // Syntax `proto2`. + SYNTAX_PROTO2 = 0; + // Syntax `proto3`. + SYNTAX_PROTO3 = 1; +} diff --git a/toolkit/components/protobuf/src/google/protobuf/unknown_field_set.cc b/toolkit/components/protobuf/src/google/protobuf/unknown_field_set.cc new file mode 100644 index 0000000000..74c358e9a2 --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/unknown_field_set.cc @@ -0,0 +1,350 @@ +// 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. + +// Author: kenton@google.com (Kenton Varda) +// Based on original Protocol Buffers design by +// Sanjay Ghemawat, Jeff Dean, and others. + +#include <google/protobuf/unknown_field_set.h> + +#include <google/protobuf/stubs/logging.h> +#include <google/protobuf/stubs/common.h> +#include <google/protobuf/io/coded_stream.h> +#include <google/protobuf/io/zero_copy_stream.h> +#include <google/protobuf/io/zero_copy_stream_impl.h> +#include <google/protobuf/io/zero_copy_stream_impl_lite.h> +#include <google/protobuf/extension_set.h> +#include <google/protobuf/generated_message_tctable_decl.h> +#include <google/protobuf/generated_message_tctable_impl.h> +#include <google/protobuf/parse_context.h> +#include <google/protobuf/wire_format.h> +#include <google/protobuf/wire_format_lite.h> +#include <google/protobuf/stubs/stl_util.h> + +// Must be included last. +#include <google/protobuf/port_def.inc> + +namespace google { +namespace protobuf { + +const UnknownFieldSet& UnknownFieldSet::default_instance() { + static auto instance = internal::OnShutdownDelete(new UnknownFieldSet()); + return *instance; +} + +void UnknownFieldSet::ClearFallback() { + GOOGLE_DCHECK(!fields_.empty()); + int n = fields_.size(); + do { + (fields_)[--n].Delete(); + } while (n > 0); + fields_.clear(); +} + +void UnknownFieldSet::InternalMergeFrom(const UnknownFieldSet& other) { + int other_field_count = other.field_count(); + if (other_field_count > 0) { + fields_.reserve(fields_.size() + other_field_count); + for (int i = 0; i < other_field_count; i++) { + fields_.push_back((other.fields_)[i]); + fields_.back().DeepCopy((other.fields_)[i]); + } + } +} + +void UnknownFieldSet::MergeFrom(const UnknownFieldSet& other) { + int other_field_count = other.field_count(); + if (other_field_count > 0) { + fields_.reserve(fields_.size() + other_field_count); + for (int i = 0; i < other_field_count; i++) { + fields_.push_back((other.fields_)[i]); + fields_.back().DeepCopy((other.fields_)[i]); + } + } +} + +// A specialized MergeFrom for performance when we are merging from an UFS that +// is temporary and can be destroyed in the process. +void UnknownFieldSet::MergeFromAndDestroy(UnknownFieldSet* other) { + if (fields_.empty()) { + fields_ = std::move(other->fields_); + } else { + fields_.insert(fields_.end(), + std::make_move_iterator(other->fields_.begin()), + std::make_move_iterator(other->fields_.end())); + } + other->fields_.clear(); +} + +void UnknownFieldSet::MergeToInternalMetadata( + const UnknownFieldSet& other, internal::InternalMetadata* metadata) { + metadata->mutable_unknown_fields<UnknownFieldSet>()->MergeFrom(other); +} + +size_t UnknownFieldSet::SpaceUsedExcludingSelfLong() const { + if (fields_.empty()) return 0; + + size_t total_size = sizeof(UnknownField) * fields_.capacity(); + + for (const UnknownField& field : fields_) { + switch (field.type()) { + case UnknownField::TYPE_LENGTH_DELIMITED: + total_size += sizeof(*field.data_.length_delimited_.string_value) + + internal::StringSpaceUsedExcludingSelfLong( + *field.data_.length_delimited_.string_value); + break; + case UnknownField::TYPE_GROUP: + total_size += field.data_.group_->SpaceUsedLong(); + break; + default: + break; + } + } + return total_size; +} + +size_t UnknownFieldSet::SpaceUsedLong() const { + return sizeof(*this) + SpaceUsedExcludingSelf(); +} + +void UnknownFieldSet::AddVarint(int number, uint64_t value) { + UnknownField field; + field.number_ = number; + field.SetType(UnknownField::TYPE_VARINT); + field.data_.varint_ = value; + fields_.push_back(field); +} + +void UnknownFieldSet::AddFixed32(int number, uint32_t value) { + UnknownField field; + field.number_ = number; + field.SetType(UnknownField::TYPE_FIXED32); + field.data_.fixed32_ = value; + fields_.push_back(field); +} + +void UnknownFieldSet::AddFixed64(int number, uint64_t value) { + UnknownField field; + field.number_ = number; + field.SetType(UnknownField::TYPE_FIXED64); + field.data_.fixed64_ = value; + fields_.push_back(field); +} + +std::string* UnknownFieldSet::AddLengthDelimited(int number) { + UnknownField field; + field.number_ = number; + field.SetType(UnknownField::TYPE_LENGTH_DELIMITED); + field.data_.length_delimited_.string_value = new std::string; + fields_.push_back(field); + return field.data_.length_delimited_.string_value; +} + + +UnknownFieldSet* UnknownFieldSet::AddGroup(int number) { + UnknownField field; + field.number_ = number; + field.SetType(UnknownField::TYPE_GROUP); + field.data_.group_ = new UnknownFieldSet; + fields_.push_back(field); + return field.data_.group_; +} + +void UnknownFieldSet::AddField(const UnknownField& field) { + fields_.push_back(field); + fields_.back().DeepCopy(field); +} + +void UnknownFieldSet::DeleteSubrange(int start, int num) { + // Delete the specified fields. + for (int i = 0; i < num; ++i) { + (fields_)[i + start].Delete(); + } + // Slide down the remaining fields. + for (size_t i = start + num; i < fields_.size(); ++i) { + (fields_)[i - num] = (fields_)[i]; + } + // Pop off the # of deleted fields. + for (int i = 0; i < num; ++i) { + fields_.pop_back(); + } +} + +void UnknownFieldSet::DeleteByNumber(int number) { + size_t left = 0; // The number of fields left after deletion. + for (size_t i = 0; i < fields_.size(); ++i) { + UnknownField* field = &(fields_)[i]; + if (field->number() == number) { + field->Delete(); + } else { + if (i != left) { + (fields_)[left] = (fields_)[i]; + } + ++left; + } + } + fields_.resize(left); +} + +bool UnknownFieldSet::MergeFromCodedStream(io::CodedInputStream* input) { + UnknownFieldSet other; + if (internal::WireFormat::SkipMessage(input, &other) && + input->ConsumedEntireMessage()) { + MergeFromAndDestroy(&other); + return true; + } else { + return false; + } +} + +bool UnknownFieldSet::ParseFromCodedStream(io::CodedInputStream* input) { + Clear(); + return MergeFromCodedStream(input); +} + +bool UnknownFieldSet::ParseFromZeroCopyStream(io::ZeroCopyInputStream* input) { + io::CodedInputStream coded_input(input); + return (ParseFromCodedStream(&coded_input) && + coded_input.ConsumedEntireMessage()); +} + +bool UnknownFieldSet::ParseFromArray(const void* data, int size) { + io::ArrayInputStream input(data, size); + return ParseFromZeroCopyStream(&input); +} + +bool UnknownFieldSet::SerializeToString(std::string* output) const { + const size_t size = + google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(*this); + STLStringResizeUninitializedAmortized(output, size); + google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( + *this, reinterpret_cast<uint8_t*>(const_cast<char*>(output->data()))); + return true; +} + +bool UnknownFieldSet::SerializeToCodedStream( + io::CodedOutputStream* output) const { + google::protobuf::internal::WireFormat::SerializeUnknownFields(*this, output); + return !output->HadError(); +} +void UnknownField::Delete() { + switch (type()) { + case UnknownField::TYPE_LENGTH_DELIMITED: + delete data_.length_delimited_.string_value; + break; + case UnknownField::TYPE_GROUP: + delete data_.group_; + break; + default: + break; + } +} + +void UnknownField::DeepCopy(const UnknownField& other) { + (void)other; // Parameter is used by Google-internal code. + switch (type()) { + case UnknownField::TYPE_LENGTH_DELIMITED: + data_.length_delimited_.string_value = + new std::string(*data_.length_delimited_.string_value); + break; + case UnknownField::TYPE_GROUP: { + UnknownFieldSet* group = new UnknownFieldSet(); + group->InternalMergeFrom(*data_.group_); + data_.group_ = group; + break; + } + default: + break; + } +} + + +uint8_t* UnknownField::InternalSerializeLengthDelimitedNoTag( + uint8_t* target, io::EpsCopyOutputStream* stream) const { + GOOGLE_DCHECK_EQ(TYPE_LENGTH_DELIMITED, type()); + const std::string& data = *data_.length_delimited_.string_value; + target = io::CodedOutputStream::WriteVarint32ToArray(data.size(), target); + target = stream->WriteRaw(data.data(), data.size(), target); + return target; +} + +namespace internal { + +class UnknownFieldParserHelper { + public: + explicit UnknownFieldParserHelper(UnknownFieldSet* unknown) + : unknown_(unknown) {} + + void AddVarint(uint32_t num, uint64_t value) { + unknown_->AddVarint(num, value); + } + void AddFixed64(uint32_t num, uint64_t value) { + unknown_->AddFixed64(num, value); + } + const char* ParseLengthDelimited(uint32_t num, const char* ptr, + ParseContext* ctx) { + std::string* s = unknown_->AddLengthDelimited(num); + int size = ReadSize(&ptr); + GOOGLE_PROTOBUF_PARSER_ASSERT(ptr); + return ctx->ReadString(ptr, size, s); + } + const char* ParseGroup(uint32_t num, const char* ptr, ParseContext* ctx) { + UnknownFieldParserHelper child(unknown_->AddGroup(num)); + return ctx->ParseGroup(&child, ptr, num * 8 + 3); + } + void AddFixed32(uint32_t num, uint32_t value) { + unknown_->AddFixed32(num, value); + } + + const char* _InternalParse(const char* ptr, ParseContext* ctx) { + return WireFormatParser(*this, ptr, ctx); + } + + private: + UnknownFieldSet* unknown_; +}; + +const char* UnknownGroupParse(UnknownFieldSet* unknown, const char* ptr, + ParseContext* ctx) { + UnknownFieldParserHelper field_parser(unknown); + return WireFormatParser(field_parser, ptr, ctx); +} + +const char* UnknownFieldParse(uint64_t tag, UnknownFieldSet* unknown, + const char* ptr, ParseContext* ctx) { + UnknownFieldParserHelper field_parser(unknown); + return FieldParser(tag, field_parser, ptr, ctx); +} + +} // namespace internal +} // namespace protobuf +} // namespace google + +#include <google/protobuf/port_undef.inc> diff --git a/toolkit/components/protobuf/src/google/protobuf/unknown_field_set.h b/toolkit/components/protobuf/src/google/protobuf/unknown_field_set.h new file mode 100644 index 0000000000..9aa2cbbe47 --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/unknown_field_set.h @@ -0,0 +1,407 @@ +// 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. + +// Author: kenton@google.com (Kenton Varda) +// Based on original Protocol Buffers design by +// Sanjay Ghemawat, Jeff Dean, and others. +// +// Contains classes used to keep track of unrecognized fields seen while +// parsing a protocol message. + +#ifndef GOOGLE_PROTOBUF_UNKNOWN_FIELD_SET_H__ +#define GOOGLE_PROTOBUF_UNKNOWN_FIELD_SET_H__ + + +#include <assert.h> + +#include <string> +#include <vector> + +#include <google/protobuf/stubs/common.h> +#include <google/protobuf/stubs/logging.h> +#include <google/protobuf/io/coded_stream.h> +#include <google/protobuf/io/zero_copy_stream_impl_lite.h> +#include <google/protobuf/port.h> +#include <google/protobuf/message_lite.h> +#include <google/protobuf/parse_context.h> + +// Must be included last. +#include <google/protobuf/port_def.inc> + +#ifdef SWIG +#error "You cannot SWIG proto headers" +#endif + +namespace google { +namespace protobuf { +namespace internal { +class InternalMetadata; // metadata_lite.h +class WireFormat; // wire_format.h +class MessageSetFieldSkipperUsingCord; +// extension_set_heavy.cc +} // namespace internal + +class Message; // message.h +class UnknownField; // below + +// An UnknownFieldSet contains fields that were encountered while parsing a +// message but were not defined by its type. Keeping track of these can be +// useful, especially in that they may be written if the message is serialized +// again without being cleared in between. This means that software which +// simply receives messages and forwards them to other servers does not need +// to be updated every time a new field is added to the message definition. +// +// To get the UnknownFieldSet attached to any message, call +// Reflection::GetUnknownFields(). +// +// This class is necessarily tied to the protocol buffer wire format, unlike +// the Reflection interface which is independent of any serialization scheme. +class PROTOBUF_EXPORT UnknownFieldSet { + public: + UnknownFieldSet(); + ~UnknownFieldSet(); + + // Remove all fields. + inline void Clear(); + + // Remove all fields and deallocate internal data objects + void ClearAndFreeMemory(); + + // Is this set empty? + inline bool empty() const; + + // Merge the contents of some other UnknownFieldSet with this one. + void MergeFrom(const UnknownFieldSet& other); + + // Similar to above, but this function will destroy the contents of other. + void MergeFromAndDestroy(UnknownFieldSet* other); + + // Merge the contents an UnknownFieldSet with the UnknownFieldSet in + // *metadata, if there is one. If *metadata doesn't have an UnknownFieldSet + // then add one to it and make it be a copy of the first arg. + static void MergeToInternalMetadata(const UnknownFieldSet& other, + internal::InternalMetadata* metadata); + + // Swaps the contents of some other UnknownFieldSet with this one. + inline void Swap(UnknownFieldSet* x); + + // Computes (an estimate of) the total number of bytes currently used for + // storing the unknown fields in memory. Does NOT include + // sizeof(*this) in the calculation. + size_t SpaceUsedExcludingSelfLong() const; + + int SpaceUsedExcludingSelf() const { + return internal::ToIntSize(SpaceUsedExcludingSelfLong()); + } + + // Version of SpaceUsed() including sizeof(*this). + size_t SpaceUsedLong() const; + + int SpaceUsed() const { return internal::ToIntSize(SpaceUsedLong()); } + + // Returns the number of fields present in the UnknownFieldSet. + inline int field_count() const; + // Get a field in the set, where 0 <= index < field_count(). The fields + // appear in the order in which they were added. + inline const UnknownField& field(int index) const; + // Get a mutable pointer to a field in the set, where + // 0 <= index < field_count(). The fields appear in the order in which + // they were added. + inline UnknownField* mutable_field(int index); + + // Adding fields --------------------------------------------------- + + void AddVarint(int number, uint64_t value); + void AddFixed32(int number, uint32_t value); + void AddFixed64(int number, uint64_t value); + void AddLengthDelimited(int number, const std::string& value); + std::string* AddLengthDelimited(int number); + UnknownFieldSet* AddGroup(int number); + + // Adds an unknown field from another set. + void AddField(const UnknownField& field); + + // Delete fields with indices in the range [start .. start+num-1]. + // Caution: implementation moves all fields with indices [start+num .. ]. + void DeleteSubrange(int start, int num); + + // Delete all fields with a specific field number. The order of left fields + // is preserved. + // Caution: implementation moves all fields after the first deleted field. + void DeleteByNumber(int number); + + // Parsing helpers ------------------------------------------------- + // These work exactly like the similarly-named methods of Message. + + bool MergeFromCodedStream(io::CodedInputStream* input); + bool ParseFromCodedStream(io::CodedInputStream* input); + bool ParseFromZeroCopyStream(io::ZeroCopyInputStream* input); + bool ParseFromArray(const void* data, int size); + inline bool ParseFromString(const std::string& data) { + return ParseFromArray(data.data(), static_cast<int>(data.size())); + } + + // Merges this message's unknown field data (if any). This works whether + // the message is a lite or full proto (for legacy reasons, lite and full + // return different types for MessageType::unknown_fields()). + template <typename MessageType> + bool MergeFromMessage(const MessageType& message); + + // Serialization. + bool SerializeToString(std::string* output) const; + bool SerializeToCodedStream(io::CodedOutputStream* output) const; + static const UnknownFieldSet& default_instance(); + + private: + // For InternalMergeFrom + friend class UnknownField; + // Merges from other UnknownFieldSet. This method assumes, that this object + // is newly created and has no fields. + void InternalMergeFrom(const UnknownFieldSet& other); + void ClearFallback(); + + template <typename MessageType, + typename std::enable_if< + std::is_base_of<Message, MessageType>::value, int>::type = 0> + bool InternalMergeFromMessage(const MessageType& message) { + MergeFrom(message.GetReflection()->GetUnknownFields(message)); + return true; + } + + template <typename MessageType, + typename std::enable_if< + std::is_base_of<MessageLite, MessageType>::value && + !std::is_base_of<Message, MessageType>::value, + int>::type = 0> + bool InternalMergeFromMessage(const MessageType& message) { + const auto& unknown_fields = message.unknown_fields(); + io::ArrayInputStream array_stream(unknown_fields.data(), + unknown_fields.size()); + io::CodedInputStream coded_stream(&array_stream); + return MergeFromCodedStream(&coded_stream); + } + + std::vector<UnknownField> fields_; + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(UnknownFieldSet); +}; + +namespace internal { + +inline void WriteVarint(uint32_t num, uint64_t val, UnknownFieldSet* unknown) { + unknown->AddVarint(num, val); +} +inline void WriteLengthDelimited(uint32_t num, StringPiece val, + UnknownFieldSet* unknown) { + unknown->AddLengthDelimited(num)->assign(val.data(), val.size()); +} + +PROTOBUF_EXPORT +const char* UnknownGroupParse(UnknownFieldSet* unknown, const char* ptr, + ParseContext* ctx); +PROTOBUF_EXPORT +const char* UnknownFieldParse(uint64_t tag, UnknownFieldSet* unknown, + const char* ptr, ParseContext* ctx); + +} // namespace internal + +// Represents one field in an UnknownFieldSet. +class PROTOBUF_EXPORT UnknownField { + public: + enum Type { + TYPE_VARINT, + TYPE_FIXED32, + TYPE_FIXED64, + TYPE_LENGTH_DELIMITED, + TYPE_GROUP + }; + + // The field's field number, as seen on the wire. + inline int number() const; + + // The field type. + inline Type type() const; + + // Accessors ------------------------------------------------------- + // Each method works only for UnknownFields of the corresponding type. + + inline uint64_t varint() const; + inline uint32_t fixed32() const; + inline uint64_t fixed64() const; + inline const std::string& length_delimited() const; + inline const UnknownFieldSet& group() const; + + inline void set_varint(uint64_t value); + inline void set_fixed32(uint32_t value); + inline void set_fixed64(uint64_t value); + inline void set_length_delimited(const std::string& value); + inline std::string* mutable_length_delimited(); + inline UnknownFieldSet* mutable_group(); + + inline size_t GetLengthDelimitedSize() const; + uint8_t* InternalSerializeLengthDelimitedNoTag( + uint8_t* target, io::EpsCopyOutputStream* stream) const; + + + // If this UnknownField contains a pointer, delete it. + void Delete(); + + // Make a deep copy of any pointers in this UnknownField. + void DeepCopy(const UnknownField& other); + + // Set the wire type of this UnknownField. Should only be used when this + // UnknownField is being created. + inline void SetType(Type type); + + union LengthDelimited { + std::string* string_value; + }; + + uint32_t number_; + uint32_t type_; + union { + uint64_t varint_; + uint32_t fixed32_; + uint64_t fixed64_; + mutable union LengthDelimited length_delimited_; + UnknownFieldSet* group_; + } data_; +}; + +// =================================================================== +// inline implementations + +inline UnknownFieldSet::UnknownFieldSet() {} + +inline UnknownFieldSet::~UnknownFieldSet() { Clear(); } + +inline void UnknownFieldSet::ClearAndFreeMemory() { Clear(); } + +inline void UnknownFieldSet::Clear() { + if (!fields_.empty()) { + ClearFallback(); + } +} + +inline bool UnknownFieldSet::empty() const { return fields_.empty(); } + +inline void UnknownFieldSet::Swap(UnknownFieldSet* x) { + fields_.swap(x->fields_); +} + +inline int UnknownFieldSet::field_count() const { + return static_cast<int>(fields_.size()); +} +inline const UnknownField& UnknownFieldSet::field(int index) const { + return (fields_)[static_cast<size_t>(index)]; +} +inline UnknownField* UnknownFieldSet::mutable_field(int index) { + return &(fields_)[static_cast<size_t>(index)]; +} + +inline void UnknownFieldSet::AddLengthDelimited(int number, + const std::string& value) { + AddLengthDelimited(number)->assign(value); +} + + + + +inline int UnknownField::number() const { return static_cast<int>(number_); } +inline UnknownField::Type UnknownField::type() const { + return static_cast<Type>(type_); +} + +inline uint64_t UnknownField::varint() const { + assert(type() == TYPE_VARINT); + return data_.varint_; +} +inline uint32_t UnknownField::fixed32() const { + assert(type() == TYPE_FIXED32); + return data_.fixed32_; +} +inline uint64_t UnknownField::fixed64() const { + assert(type() == TYPE_FIXED64); + return data_.fixed64_; +} +inline const std::string& UnknownField::length_delimited() const { + assert(type() == TYPE_LENGTH_DELIMITED); + return *data_.length_delimited_.string_value; +} +inline const UnknownFieldSet& UnknownField::group() const { + assert(type() == TYPE_GROUP); + return *data_.group_; +} + +inline void UnknownField::set_varint(uint64_t value) { + assert(type() == TYPE_VARINT); + data_.varint_ = value; +} +inline void UnknownField::set_fixed32(uint32_t value) { + assert(type() == TYPE_FIXED32); + data_.fixed32_ = value; +} +inline void UnknownField::set_fixed64(uint64_t value) { + assert(type() == TYPE_FIXED64); + data_.fixed64_ = value; +} +inline void UnknownField::set_length_delimited(const std::string& value) { + assert(type() == TYPE_LENGTH_DELIMITED); + data_.length_delimited_.string_value->assign(value); +} +inline std::string* UnknownField::mutable_length_delimited() { + assert(type() == TYPE_LENGTH_DELIMITED); + return data_.length_delimited_.string_value; +} +inline UnknownFieldSet* UnknownField::mutable_group() { + assert(type() == TYPE_GROUP); + return data_.group_; +} +template <typename MessageType> +bool UnknownFieldSet::MergeFromMessage(const MessageType& message) { + // SFINAE will route to the right version. + return InternalMergeFromMessage(message); +} + + +inline size_t UnknownField::GetLengthDelimitedSize() const { + GOOGLE_DCHECK_EQ(TYPE_LENGTH_DELIMITED, type()); + return data_.length_delimited_.string_value->size(); +} + +inline void UnknownField::SetType(Type type) { + type_ = type; +} + + +} // namespace protobuf +} // namespace google + +#include <google/protobuf/port_undef.inc> +#endif // GOOGLE_PROTOBUF_UNKNOWN_FIELD_SET_H__ diff --git a/toolkit/components/protobuf/src/google/protobuf/util/delimited_message_util.cc b/toolkit/components/protobuf/src/google/protobuf/util/delimited_message_util.cc new file mode 100644 index 0000000000..fdc633f49a --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/util/delimited_message_util.cc @@ -0,0 +1,128 @@ +// 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. + +// Adapted from the patch of kenton@google.com (Kenton Varda) +// See https://github.com/protocolbuffers/protobuf/pull/710 for details. + +#include <google/protobuf/util/delimited_message_util.h> +#include <google/protobuf/io/coded_stream.h> + +namespace google { +namespace protobuf { +namespace util { + +bool SerializeDelimitedToFileDescriptor(const MessageLite& message, + int file_descriptor) { + io::FileOutputStream output(file_descriptor); + return SerializeDelimitedToZeroCopyStream(message, &output); +} + +bool SerializeDelimitedToOstream(const MessageLite& message, + std::ostream* output) { + { + io::OstreamOutputStream zero_copy_output(output); + if (!SerializeDelimitedToZeroCopyStream(message, &zero_copy_output)) + return false; + } + return output->good(); +} + +bool ParseDelimitedFromZeroCopyStream(MessageLite* message, + io::ZeroCopyInputStream* input, + bool* clean_eof) { + io::CodedInputStream coded_input(input); + return ParseDelimitedFromCodedStream(message, &coded_input, clean_eof); +} + +bool ParseDelimitedFromCodedStream(MessageLite* message, + io::CodedInputStream* input, + bool* clean_eof) { + if (clean_eof != nullptr) *clean_eof = false; + int start = input->CurrentPosition(); + + // Read the size. + uint32_t size; + if (!input->ReadVarint32(&size)) { + if (clean_eof != nullptr) *clean_eof = input->CurrentPosition() == start; + return false; + } + + // Get the position after any size bytes have been read (and only the message + // itself remains). + int position_after_size = input->CurrentPosition(); + + // Tell the stream not to read beyond that size. + io::CodedInputStream::Limit limit = input->PushLimit(static_cast<int>(size)); + + // Parse the message. + if (!message->MergeFromCodedStream(input)) return false; + if (!input->ConsumedEntireMessage()) return false; + if (input->CurrentPosition() - position_after_size != static_cast<int>(size)) + return false; + + // Release the limit. + input->PopLimit(limit); + + return true; +} + +bool SerializeDelimitedToZeroCopyStream(const MessageLite& message, + io::ZeroCopyOutputStream* output) { + io::CodedOutputStream coded_output(output); + return SerializeDelimitedToCodedStream(message, &coded_output); +} + +bool SerializeDelimitedToCodedStream(const MessageLite& message, + io::CodedOutputStream* output) { + // Write the size. + size_t size = message.ByteSizeLong(); + if (size > INT_MAX) return false; + + output->WriteVarint32(static_cast<uint32_t>(size)); + + // Write the content. + uint8_t* buffer = + output->GetDirectBufferForNBytesAndAdvance(static_cast<int>(size)); + if (buffer != nullptr) { + // Optimization: The message fits in one buffer, so use the faster + // direct-to-array serialization path. + message.SerializeWithCachedSizesToArray(buffer); + } else { + // Slightly-slower path when the message is multiple buffers. + message.SerializeWithCachedSizes(output); + if (output->HadError()) return false; + } + + return true; +} + +} // namespace util +} // namespace protobuf +} // namespace google diff --git a/toolkit/components/protobuf/src/google/protobuf/util/delimited_message_util.h b/toolkit/components/protobuf/src/google/protobuf/util/delimited_message_util.h new file mode 100644 index 0000000000..78625cf2f1 --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/util/delimited_message_util.h @@ -0,0 +1,109 @@ +// 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. + +// Adapted from the patch of kenton@google.com (Kenton Varda) +// See https://github.com/protocolbuffers/protobuf/pull/710 for details. + +#ifndef GOOGLE_PROTOBUF_UTIL_DELIMITED_MESSAGE_UTIL_H__ +#define GOOGLE_PROTOBUF_UTIL_DELIMITED_MESSAGE_UTIL_H__ + + +#include <ostream> + +#include <google/protobuf/message_lite.h> +#include <google/protobuf/io/coded_stream.h> +#include <google/protobuf/io/zero_copy_stream_impl.h> + +// Must be included last. +#include <google/protobuf/port_def.inc> + +namespace google { +namespace protobuf { +namespace util { + +// Write a single size-delimited message from the given stream. Delimited +// format allows a single file or stream to contain multiple messages, +// whereas normally writing multiple non-delimited messages to the same +// stream would cause them to be merged. A delimited message is a varint +// encoding the message size followed by a message of exactly that size. +// +// Note that if you want to *read* a delimited message from a file descriptor +// or istream, you will need to construct an io::FileInputStream or +// io::OstreamInputStream (implementations of io::ZeroCopyStream) and use the +// utility function ParseDelimitedFromZeroCopyStream(). You must then +// continue to use the same ZeroCopyInputStream to read all further data from +// the stream until EOF. This is because these ZeroCopyInputStream +// implementations are buffered: they read a big chunk of data at a time, +// then parse it. As a result, they may read past the end of the delimited +// message. There is no way for them to push the extra data back into the +// underlying source, so instead you must keep using the same stream object. +bool PROTOBUF_EXPORT SerializeDelimitedToFileDescriptor( + const MessageLite& message, int file_descriptor); + +bool PROTOBUF_EXPORT SerializeDelimitedToOstream(const MessageLite& message, + std::ostream* output); + +// Read a single size-delimited message from the given stream. Delimited +// format allows a single file or stream to contain multiple messages, +// whereas normally parsing consumes the entire input. A delimited message +// is a varint encoding the message size followed by a message of exactly +// that size. +// +// If |clean_eof| is not NULL, then it will be set to indicate whether the +// stream ended cleanly. That is, if the stream ends without this method +// having read any data at all from it, then *clean_eof will be set true, +// otherwise it will be set false. Note that these methods return false +// on EOF, but they also return false on other errors, so |clean_eof| is +// needed to distinguish a clean end from errors. +bool PROTOBUF_EXPORT ParseDelimitedFromZeroCopyStream( + MessageLite* message, io::ZeroCopyInputStream* input, bool* clean_eof); + +bool PROTOBUF_EXPORT ParseDelimitedFromCodedStream(MessageLite* message, + io::CodedInputStream* input, + bool* clean_eof); + +// Write a single size-delimited message from the given stream. Delimited +// format allows a single file or stream to contain multiple messages, +// whereas normally writing multiple non-delimited messages to the same +// stream would cause them to be merged. A delimited message is a varint +// encoding the message size followed by a message of exactly that size. +bool PROTOBUF_EXPORT SerializeDelimitedToZeroCopyStream( + const MessageLite& message, io::ZeroCopyOutputStream* output); + +bool PROTOBUF_EXPORT SerializeDelimitedToCodedStream( + const MessageLite& message, io::CodedOutputStream* output); + +} // namespace util +} // namespace protobuf +} // namespace google + +#include <google/protobuf/port_undef.inc> + +#endif // GOOGLE_PROTOBUF_UTIL_DELIMITED_MESSAGE_UTIL_H__ diff --git a/toolkit/components/protobuf/src/google/protobuf/util/field_comparator.cc b/toolkit/components/protobuf/src/google/protobuf/util/field_comparator.cc new file mode 100644 index 0000000000..5d8e865ad8 --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/util/field_comparator.cc @@ -0,0 +1,210 @@ +// 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. + +// Author: ksroka@google.com (Krzysztof Sroka) + +#include <google/protobuf/util/field_comparator.h> + +#include <limits> +#include <string> + +#include <google/protobuf/descriptor.h> +#include <google/protobuf/message.h> +#include <google/protobuf/util/message_differencer.h> +#include <google/protobuf/stubs/map_util.h> +#include <google/protobuf/stubs/mathutil.h> + +namespace google { +namespace protobuf { +namespace util { + +FieldComparator::FieldComparator() {} +FieldComparator::~FieldComparator() {} + +SimpleFieldComparator::SimpleFieldComparator() + : float_comparison_(EXACT), + treat_nan_as_equal_(false), + has_default_tolerance_(false) {} + +SimpleFieldComparator::~SimpleFieldComparator() {} + +FieldComparator::ComparisonResult SimpleFieldComparator::SimpleCompare( + const Message& message_1, const Message& message_2, + const FieldDescriptor* field, int index_1, int index_2, + const util::FieldContext* /*field_context*/) { + const Reflection* reflection_1 = message_1.GetReflection(); + const Reflection* reflection_2 = message_2.GetReflection(); + + switch (field->cpp_type()) { +#define COMPARE_FIELD(METHOD) \ + if (field->is_repeated()) { \ + return ResultFromBoolean(Compare##METHOD( \ + *field, reflection_1->GetRepeated##METHOD(message_1, field, index_1), \ + reflection_2->GetRepeated##METHOD(message_2, field, index_2))); \ + } else { \ + return ResultFromBoolean( \ + Compare##METHOD(*field, reflection_1->Get##METHOD(message_1, field), \ + reflection_2->Get##METHOD(message_2, field))); \ + } \ + break; // Make sure no fall-through is introduced. + + case FieldDescriptor::CPPTYPE_BOOL: + COMPARE_FIELD(Bool); + case FieldDescriptor::CPPTYPE_DOUBLE: + COMPARE_FIELD(Double); + case FieldDescriptor::CPPTYPE_ENUM: + COMPARE_FIELD(Enum); + case FieldDescriptor::CPPTYPE_FLOAT: + COMPARE_FIELD(Float); + case FieldDescriptor::CPPTYPE_INT32: + COMPARE_FIELD(Int32); + case FieldDescriptor::CPPTYPE_INT64: + COMPARE_FIELD(Int64); + case FieldDescriptor::CPPTYPE_STRING: + if (field->is_repeated()) { + // Allocate scratch strings to store the result if a conversion is + // needed. + std::string scratch1; + std::string scratch2; + return ResultFromBoolean( + CompareString(*field, + reflection_1->GetRepeatedStringReference( + message_1, field, index_1, &scratch1), + reflection_2->GetRepeatedStringReference( + message_2, field, index_2, &scratch2))); + } else { + // Allocate scratch strings to store the result if a conversion is + // needed. + std::string scratch1; + std::string scratch2; + return ResultFromBoolean(CompareString( + *field, + reflection_1->GetStringReference(message_1, field, &scratch1), + reflection_2->GetStringReference(message_2, field, &scratch2))); + } + break; + case FieldDescriptor::CPPTYPE_UINT32: + COMPARE_FIELD(UInt32); + case FieldDescriptor::CPPTYPE_UINT64: + COMPARE_FIELD(UInt64); + +#undef COMPARE_FIELD + + case FieldDescriptor::CPPTYPE_MESSAGE: + return RECURSE; + + default: + GOOGLE_LOG(FATAL) << "No comparison code for field " << field->full_name() + << " of CppType = " << field->cpp_type(); + return DIFFERENT; + } +} + +bool SimpleFieldComparator::CompareWithDifferencer( + MessageDifferencer* differencer, const Message& message1, + const Message& message2, const util::FieldContext* field_context) { + return differencer->Compare(message1, message2, + field_context->parent_fields()); +} + +void SimpleFieldComparator::SetDefaultFractionAndMargin(double fraction, + double margin) { + default_tolerance_ = Tolerance(fraction, margin); + has_default_tolerance_ = true; +} + +void SimpleFieldComparator::SetFractionAndMargin(const FieldDescriptor* field, + double fraction, + double margin) { + GOOGLE_CHECK(FieldDescriptor::CPPTYPE_FLOAT == field->cpp_type() || + FieldDescriptor::CPPTYPE_DOUBLE == field->cpp_type()) + << "Field has to be float or double type. Field name is: " + << field->full_name(); + map_tolerance_[field] = Tolerance(fraction, margin); +} + +bool SimpleFieldComparator::CompareDouble(const FieldDescriptor& field, + double value_1, double value_2) { + return CompareDoubleOrFloat(field, value_1, value_2); +} + +bool SimpleFieldComparator::CompareEnum(const FieldDescriptor& /*field*/, + const EnumValueDescriptor* value_1, + const EnumValueDescriptor* value_2) { + return value_1->number() == value_2->number(); +} + +bool SimpleFieldComparator::CompareFloat(const FieldDescriptor& field, + float value_1, float value_2) { + return CompareDoubleOrFloat(field, value_1, value_2); +} + +template <typename T> +bool SimpleFieldComparator::CompareDoubleOrFloat(const FieldDescriptor& field, + T value_1, T value_2) { + if (value_1 == value_2) { + // Covers +inf and -inf (which are not within margin or fraction of + // themselves), and is a shortcut for finite values. + return true; + } else if (float_comparison_ == EXACT) { + if (treat_nan_as_equal_ && std::isnan(value_1) && std::isnan(value_2)) { + return true; + } + return false; + } else { + if (treat_nan_as_equal_ && std::isnan(value_1) && std::isnan(value_2)) { + return true; + } + // float_comparison_ == APPROXIMATE covers two use cases. + Tolerance* tolerance = FindOrNull(map_tolerance_, &field); + if (tolerance == NULL && has_default_tolerance_) { + tolerance = &default_tolerance_; + } + if (tolerance == NULL) { + return MathUtil::AlmostEquals(value_1, value_2); + } else { + // Use user-provided fraction and margin. Since they are stored as + // doubles, we explicitly cast them to types of values provided. This + // is very likely to fail if provided values are not numeric. + return MathUtil::WithinFractionOrMargin( + value_1, value_2, static_cast<T>(tolerance->fraction), + static_cast<T>(tolerance->margin)); + } + } +} + +FieldComparator::ComparisonResult SimpleFieldComparator::ResultFromBoolean( + bool boolean_result) const { + return boolean_result ? FieldComparator::SAME : FieldComparator::DIFFERENT; +} + +} // namespace util +} // namespace protobuf +} // namespace google diff --git a/toolkit/components/protobuf/src/google/protobuf/util/field_comparator.h b/toolkit/components/protobuf/src/google/protobuf/util/field_comparator.h new file mode 100644 index 0000000000..5706da357a --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/util/field_comparator.h @@ -0,0 +1,288 @@ +// 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. + +// Defines classes for field comparison. + +#ifndef GOOGLE_PROTOBUF_UTIL_FIELD_COMPARATOR_H__ +#define GOOGLE_PROTOBUF_UTIL_FIELD_COMPARATOR_H__ + + +#include <cstdint> +#include <map> +#include <string> +#include <vector> + +#include <google/protobuf/stubs/common.h> + +// Must be included last. +#include <google/protobuf/port_def.inc> + +namespace google { +namespace protobuf { + +class Message; +class EnumValueDescriptor; +class FieldDescriptor; + +namespace util { + +class FieldContext; +class MessageDifferencer; + +// Base class specifying the interface for comparing protocol buffer fields. +// Regular users should consider using or subclassing DefaultFieldComparator +// rather than this interface. +// Currently, this does not support comparing unknown fields. +class PROTOBUF_EXPORT FieldComparator { + public: + FieldComparator(); + virtual ~FieldComparator(); + + enum ComparisonResult { + SAME, // Compared fields are equal. In case of comparing submessages, + // user should not recursively compare their contents. + DIFFERENT, // Compared fields are different. In case of comparing + // submessages, user should not recursively compare their + // contents. + RECURSE, // Compared submessages need to be compared recursively. + // FieldComparator does not specify the semantics of recursive + // comparison. This value should not be returned for simple + // values. + }; + + // Compares the values of a field in two protocol buffer messages. + // Returns SAME or DIFFERENT for simple values, and SAME, DIFFERENT or RECURSE + // for submessages. Returning RECURSE for fields not being submessages is + // illegal. + // In case the given FieldDescriptor points to a repeated field, the indices + // need to be valid. Otherwise they should be ignored. + // + // FieldContext contains information about the specific instances of the + // fields being compared, versus FieldDescriptor which only contains general + // type information about the fields. + virtual ComparisonResult Compare(const Message& message_1, + const Message& message_2, + const FieldDescriptor* field, int index_1, + int index_2, + const util::FieldContext* field_context) = 0; + + private: + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FieldComparator); +}; + +// Basic implementation of FieldComparator. Supports three modes of floating +// point value comparison: exact, approximate using MathUtil::AlmostEqual +// method, and arbitrarily precise using MathUtil::WithinFractionOrMargin. +class PROTOBUF_EXPORT SimpleFieldComparator : public FieldComparator { + public: + enum FloatComparison { + EXACT, // Floats and doubles are compared exactly. + APPROXIMATE, // Floats and doubles are compared using the + // MathUtil::AlmostEqual method or + // MathUtil::WithinFractionOrMargin method. + // TODO(ksroka): Introduce third value to differentiate uses of AlmostEqual + // and WithinFractionOrMargin. + }; + + // Creates new comparator with float comparison set to EXACT. + SimpleFieldComparator(); + + ~SimpleFieldComparator() override; + + void set_float_comparison(FloatComparison float_comparison) { + float_comparison_ = float_comparison; + } + + FloatComparison float_comparison() const { return float_comparison_; } + + // Set whether the FieldComparator shall treat floats or doubles that are both + // NaN as equal (treat_nan_as_equal = true) or as different + // (treat_nan_as_equal = false). Default is treating NaNs always as different. + void set_treat_nan_as_equal(bool treat_nan_as_equal) { + treat_nan_as_equal_ = treat_nan_as_equal; + } + + bool treat_nan_as_equal() const { return treat_nan_as_equal_; } + + // Sets the fraction and margin for the float comparison of a given field. + // Uses MathUtil::WithinFractionOrMargin to compare the values. + // + // REQUIRES: field->cpp_type == FieldDescriptor::CPPTYPE_DOUBLE or + // field->cpp_type == FieldDescriptor::CPPTYPE_FLOAT + // REQUIRES: float_comparison_ == APPROXIMATE + void SetFractionAndMargin(const FieldDescriptor* field, double fraction, + double margin); + + // Sets the fraction and margin for the float comparison of all float and + // double fields, unless a field has been given a specific setting via + // SetFractionAndMargin() above. + // Uses MathUtil::WithinFractionOrMargin to compare the values. + // + // REQUIRES: float_comparison_ == APPROXIMATE + void SetDefaultFractionAndMargin(double fraction, double margin); + + protected: + // Returns the comparison result for the given field in two messages. + // + // This function is called directly by DefaultFieldComparator::Compare. + // Subclasses can call this function to compare fields they do not need to + // handle specially. + ComparisonResult SimpleCompare(const Message& message_1, + const Message& message_2, + const FieldDescriptor* field, int index_1, + int index_2, + const util::FieldContext* field_context); + + // Compare using the provided message_differencer. For example, a subclass can + // use this method to compare some field in a certain way using the same + // message_differencer instance and the field context. + bool CompareWithDifferencer(MessageDifferencer* differencer, + const Message& message1, const Message& message2, + const util::FieldContext* field_context); + + // Returns FieldComparator::SAME if boolean_result is true and + // FieldComparator::DIFFERENT otherwise. + ComparisonResult ResultFromBoolean(bool boolean_result) const; + + private: + // Defines the tolerance for floating point comparison (fraction and margin). + struct Tolerance { + double fraction; + double margin; + Tolerance() : fraction(0.0), margin(0.0) {} + Tolerance(double f, double m) : fraction(f), margin(m) {} + }; + + // Defines the map to store the tolerances for floating point comparison. + typedef std::map<const FieldDescriptor*, Tolerance> ToleranceMap; + + friend class MessageDifferencer; + // The following methods get executed when CompareFields is called for the + // basic types (instead of submessages). They return true on success. One + // can use ResultFromBoolean() to convert that boolean to a ComparisonResult + // value. + bool CompareBool(const FieldDescriptor& /* unused */, bool value_1, + bool value_2) { + return value_1 == value_2; + } + + // Uses CompareDoubleOrFloat, a helper function used by both CompareDouble and + // CompareFloat. + bool CompareDouble(const FieldDescriptor& field, double value_1, + double value_2); + + bool CompareEnum(const FieldDescriptor& field, + const EnumValueDescriptor* value_1, + const EnumValueDescriptor* value_2); + + // Uses CompareDoubleOrFloat, a helper function used by both CompareDouble and + // CompareFloat. + bool CompareFloat(const FieldDescriptor& field, float value_1, float value_2); + + bool CompareInt32(const FieldDescriptor& /* unused */, int32_t value_1, + int32_t value_2) { + return value_1 == value_2; + } + + bool CompareInt64(const FieldDescriptor& /* unused */, int64_t value_1, + int64_t value_2) { + return value_1 == value_2; + } + + bool CompareString(const FieldDescriptor& /* unused */, + const std::string& value_1, const std::string& value_2) { + return value_1 == value_2; + } + + bool CompareUInt32(const FieldDescriptor& /* unused */, uint32_t value_1, + uint32_t value_2) { + return value_1 == value_2; + } + + bool CompareUInt64(const FieldDescriptor& /* unused */, uint64_t value_1, + uint64_t value_2) { + return value_1 == value_2; + } + + // This function is used by CompareDouble and CompareFloat to avoid code + // duplication. There are no checks done against types of the values passed, + // but it's likely to fail if passed non-numeric arguments. + template <typename T> + bool CompareDoubleOrFloat(const FieldDescriptor& field, T value_1, T value_2); + + FloatComparison float_comparison_; + + // If true, floats and doubles that are both NaN are considered to be + // equal. Otherwise, two floats or doubles that are NaN are considered to be + // different. + bool treat_nan_as_equal_; + + // True iff default_tolerance_ has been explicitly set. + // + // If false, then the default tolerance for floats and doubles is that which + // is used by MathUtil::AlmostEquals(). + bool has_default_tolerance_; + + // Default float/double tolerance. Only meaningful if + // has_default_tolerance_ == true. + Tolerance default_tolerance_; + + // Field-specific float/double tolerances, which override any default for + // those particular fields. + ToleranceMap map_tolerance_; + + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(SimpleFieldComparator); +}; + +// Default field comparison: use the basic implementation of FieldComparator. +#ifdef PROTOBUF_FUTURE_BREAKING_CHANGES +class PROTOBUF_EXPORT DefaultFieldComparator final + : public SimpleFieldComparator +#else // PROTOBUF_FUTURE_BREAKING_CHANGES +class PROTOBUF_EXPORT DefaultFieldComparator : public SimpleFieldComparator +#endif // PROTOBUF_FUTURE_BREAKING_CHANGES +{ + public: + ComparisonResult Compare(const Message& message_1, const Message& message_2, + const FieldDescriptor* field, int index_1, + int index_2, + const util::FieldContext* field_context) override { + return SimpleCompare(message_1, message_2, field, index_1, index_2, + field_context); + } +}; + +} // namespace util +} // namespace protobuf +} // namespace google + +#include <google/protobuf/port_undef.inc> + +#endif // GOOGLE_PROTOBUF_UTIL_FIELD_COMPARATOR_H__ diff --git a/toolkit/components/protobuf/src/google/protobuf/util/field_mask_util.cc b/toolkit/components/protobuf/src/google/protobuf/util/field_mask_util.cc new file mode 100644 index 0000000000..700e59004a --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/util/field_mask_util.cc @@ -0,0 +1,720 @@ +// 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. + +#include <google/protobuf/util/field_mask_util.h> + +#include <cstdint> + +#include <google/protobuf/stubs/strutil.h> +#include <google/protobuf/message.h> +#include <google/protobuf/stubs/map_util.h> + +// Must be included last. +#include <google/protobuf/port_def.inc> + +namespace google { +namespace protobuf { +namespace util { + +using google::protobuf::FieldMask; + +std::string FieldMaskUtil::ToString(const FieldMask& mask) { + return Join(mask.paths(), ","); +} + +void FieldMaskUtil::FromString(StringPiece str, FieldMask* out) { + out->Clear(); + std::vector<std::string> paths = Split(str, ","); + for (const std::string& path : paths) { + if (path.empty()) continue; + out->add_paths(path); + } +} + +bool FieldMaskUtil::SnakeCaseToCamelCase(StringPiece input, + std::string* output) { + output->clear(); + bool after_underscore = false; + for (char input_char : input) { + if (input_char >= 'A' && input_char <= 'Z') { + // The field name must not contain uppercase letters. + return false; + } + if (after_underscore) { + if (input_char >= 'a' && input_char <= 'z') { + output->push_back(input_char + 'A' - 'a'); + after_underscore = false; + } else { + // The character after a "_" must be a lowercase letter. + return false; + } + } else if (input_char == '_') { + after_underscore = true; + } else { + output->push_back(input_char); + } + } + if (after_underscore) { + // Trailing "_". + return false; + } + return true; +} + +bool FieldMaskUtil::CamelCaseToSnakeCase(StringPiece input, + std::string* output) { + output->clear(); + for (const char c : input) { + if (c == '_') { + // The field name must not contain "_"s. + return false; + } + if (c >= 'A' && c <= 'Z') { + output->push_back('_'); + output->push_back(c + 'a' - 'A'); + } else { + output->push_back(c); + } + } + return true; +} + +bool FieldMaskUtil::ToJsonString(const FieldMask& mask, std::string* out) { + out->clear(); + for (int i = 0; i < mask.paths_size(); ++i) { + const std::string& path = mask.paths(i); + std::string camelcase_path; + if (!SnakeCaseToCamelCase(path, &camelcase_path)) { + return false; + } + if (i > 0) { + out->push_back(','); + } + out->append(camelcase_path); + } + return true; +} + +bool FieldMaskUtil::FromJsonString(StringPiece str, FieldMask* out) { + out->Clear(); + std::vector<std::string> paths = Split(str, ","); + for (const std::string& path : paths) { + if (path.empty()) continue; + std::string snakecase_path; + if (!CamelCaseToSnakeCase(path, &snakecase_path)) { + return false; + } + out->add_paths(snakecase_path); + } + return true; +} + +bool FieldMaskUtil::GetFieldDescriptors( + const Descriptor* descriptor, StringPiece path, + std::vector<const FieldDescriptor*>* field_descriptors) { + if (field_descriptors != nullptr) { + field_descriptors->clear(); + } + std::vector<std::string> parts = Split(path, "."); + for (const std::string& field_name : parts) { + if (descriptor == nullptr) { + return false; + } + const FieldDescriptor* field = descriptor->FindFieldByName(field_name); + if (field == nullptr) { + return false; + } + if (field_descriptors != nullptr) { + field_descriptors->push_back(field); + } + if (!field->is_repeated() && + field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { + descriptor = field->message_type(); + } else { + descriptor = nullptr; + } + } + return true; +} + +void FieldMaskUtil::GetFieldMaskForAllFields(const Descriptor* descriptor, + FieldMask* out) { + for (int i = 0; i < descriptor->field_count(); ++i) { + out->add_paths(descriptor->field(i)->name()); + } +} + +namespace { +// A FieldMaskTree represents a FieldMask in a tree structure. For example, +// given a FieldMask "foo.bar,foo.baz,bar.baz", the FieldMaskTree will be: +// +// [root] -+- foo -+- bar +// | | +// | +- baz +// | +// +- bar --- baz +// +// In the tree, each leaf node represents a field path. +class FieldMaskTree { + public: + FieldMaskTree(); + ~FieldMaskTree(); + + void MergeFromFieldMask(const FieldMask& mask); + void MergeToFieldMask(FieldMask* mask); + + // Add a field path into the tree. In a FieldMask, each field path matches + // the specified field and also all its sub-fields. If the field path to + // add is a sub-path of an existing field path in the tree (i.e., a leaf + // node), it means the tree already matches the given path so nothing will + // be added to the tree. If the path matches an existing non-leaf node in the + // tree, that non-leaf node will be turned into a leaf node with all its + // children removed because the path matches all the node's children. + void AddPath(const std::string& path); + + // Remove a path from the tree. + // If the path is a sub-path of an existing field path in the tree, it means + // we need remove the existing field path and add all sub-paths except + // specified path. If the path matches an existing node in the tree, this node + // will be moved. + void RemovePath(const std::string& path, const Descriptor* descriptor); + + // Calculate the intersection part of a field path with this tree and add + // the intersection field path into out. + void IntersectPath(const std::string& path, FieldMaskTree* out); + + // Merge all fields specified by this tree from one message to another. + void MergeMessage(const Message& source, + const FieldMaskUtil::MergeOptions& options, + Message* destination) { + // Do nothing if the tree is empty. + if (root_.children.empty()) { + return; + } + MergeMessage(&root_, source, options, destination); + } + + // Add required field path of the message to this tree based on current tree + // structure. If a message is present in the tree, add the path of its + // required field to the tree. This is to make sure that after trimming a + // message with required fields are set, check IsInitialized() will not fail. + void AddRequiredFieldPath(const Descriptor* descriptor) { + // Do nothing if the tree is empty. + if (root_.children.empty()) { + return; + } + AddRequiredFieldPath(&root_, descriptor); + } + + // Trims all fields not specified by this tree from the given message. + // Returns true if the message is modified. + bool TrimMessage(Message* message) { + // Do nothing if the tree is empty. + if (root_.children.empty()) { + return false; + } + return TrimMessage(&root_, message); + } + + private: + struct Node { + Node() {} + + ~Node() { ClearChildren(); } + + void ClearChildren() { + for (std::map<std::string, Node*>::iterator it = children.begin(); + it != children.end(); ++it) { + delete it->second; + } + children.clear(); + } + + std::map<std::string, Node*> children; + + private: + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Node); + }; + + // Merge a sub-tree to mask. This method adds the field paths represented + // by all leaf nodes descended from "node" to mask. + void MergeToFieldMask(const std::string& prefix, const Node* node, + FieldMask* out); + + // Merge all leaf nodes of a sub-tree to another tree. + void MergeLeafNodesToTree(const std::string& prefix, const Node* node, + FieldMaskTree* out); + + // Merge all fields specified by a sub-tree from one message to another. + void MergeMessage(const Node* node, const Message& source, + const FieldMaskUtil::MergeOptions& options, + Message* destination); + + // Add required field path of the message to this tree based on current tree + // structure. If a message is present in the tree, add the path of its + // required field to the tree. This is to make sure that after trimming a + // message with required fields are set, check IsInitialized() will not fail. + void AddRequiredFieldPath(Node* node, const Descriptor* descriptor); + + // Trims all fields not specified by this sub-tree from the given message. + // Returns true if the message is actually modified + bool TrimMessage(const Node* node, Message* message); + + Node root_; + + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FieldMaskTree); +}; + +FieldMaskTree::FieldMaskTree() {} + +FieldMaskTree::~FieldMaskTree() {} + +void FieldMaskTree::MergeFromFieldMask(const FieldMask& mask) { + for (int i = 0; i < mask.paths_size(); ++i) { + AddPath(mask.paths(i)); + } +} + +void FieldMaskTree::MergeToFieldMask(FieldMask* mask) { + MergeToFieldMask("", &root_, mask); +} + +void FieldMaskTree::MergeToFieldMask(const std::string& prefix, + const Node* node, FieldMask* out) { + if (node->children.empty()) { + if (prefix.empty()) { + // This is the root node. + return; + } + out->add_paths(prefix); + return; + } + for (std::map<std::string, Node*>::const_iterator it = node->children.begin(); + it != node->children.end(); ++it) { + std::string current_path = + prefix.empty() ? it->first : prefix + "." + it->first; + MergeToFieldMask(current_path, it->second, out); + } +} + +void FieldMaskTree::AddPath(const std::string& path) { + std::vector<std::string> parts = Split(path, "."); + if (parts.empty()) { + return; + } + bool new_branch = false; + Node* node = &root_; + for (const std::string& node_name : parts) { + if (!new_branch && node != &root_ && node->children.empty()) { + // Path matches an existing leaf node. This means the path is already + // covered by this tree (for example, adding "foo.bar.baz" to a tree + // which already contains "foo.bar"). + return; + } + Node*& child = node->children[node_name]; + if (child == nullptr) { + new_branch = true; + child = new Node(); + } + node = child; + } + if (!node->children.empty()) { + node->ClearChildren(); + } +} + +void FieldMaskTree::RemovePath(const std::string& path, + const Descriptor* descriptor) { + if (root_.children.empty()) { + // Nothing to be removed from an empty tree. We shortcut it here so an empty + // tree won't be interpreted as a field mask containing all fields by the + // code below. + return; + } + std::vector<std::string> parts = Split(path, "."); + if (parts.empty()) { + return; + } + std::vector<Node*> nodes(parts.size()); + Node* node = &root_; + const Descriptor* current_descriptor = descriptor; + Node* new_branch_node = nullptr; + for (int i = 0; i < parts.size(); ++i) { + nodes[i] = node; + const FieldDescriptor* field_descriptor = + current_descriptor->FindFieldByName(parts[i]); + if (field_descriptor == nullptr || + (field_descriptor->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE && + i != parts.size() - 1)) { + // Invalid path. + if (new_branch_node != nullptr) { + // If add any new nodes, cleanup. + new_branch_node->ClearChildren(); + } + return; + } + + if (node->children.empty()) { + if (new_branch_node == nullptr) { + new_branch_node = node; + } + for (int j = 0; j < current_descriptor->field_count(); ++j) { + node->children[current_descriptor->field(j)->name()] = new Node(); + } + } + if (ContainsKey(node->children, parts[i])) { + node = node->children[parts[i]]; + if (field_descriptor->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { + current_descriptor = field_descriptor->message_type(); + } + } else { + // Path does not exist. + return; + } + } + // Remove path. + for (int i = parts.size() - 1; i >= 0; i--) { + delete nodes[i]->children[parts[i]]; + nodes[i]->children.erase(parts[i]); + if (!nodes[i]->children.empty()) { + break; + } + } +} + +void FieldMaskTree::IntersectPath(const std::string& path, FieldMaskTree* out) { + std::vector<std::string> parts = Split(path, "."); + if (parts.empty()) { + return; + } + const Node* node = &root_; + for (const std::string& node_name : parts) { + if (node->children.empty()) { + if (node != &root_) { + out->AddPath(path); + } + return; + } + const Node* result = FindPtrOrNull(node->children, node_name); + if (result == nullptr) { + // No intersection found. + return; + } + node = result; + } + // Now we found a matching node with the given path. Add all leaf nodes + // to out. + MergeLeafNodesToTree(path, node, out); +} + +void FieldMaskTree::MergeLeafNodesToTree(const std::string& prefix, + const Node* node, FieldMaskTree* out) { + if (node->children.empty()) { + out->AddPath(prefix); + } + for (std::map<std::string, Node*>::const_iterator it = node->children.begin(); + it != node->children.end(); ++it) { + std::string current_path = + prefix.empty() ? it->first : prefix + "." + it->first; + MergeLeafNodesToTree(current_path, it->second, out); + } +} + +void FieldMaskTree::MergeMessage(const Node* node, const Message& source, + const FieldMaskUtil::MergeOptions& options, + Message* destination) { + GOOGLE_DCHECK(!node->children.empty()); + const Reflection* source_reflection = source.GetReflection(); + const Reflection* destination_reflection = destination->GetReflection(); + const Descriptor* descriptor = source.GetDescriptor(); + for (std::map<std::string, Node*>::const_iterator it = node->children.begin(); + it != node->children.end(); ++it) { + const std::string& field_name = it->first; + const Node* child = it->second; + const FieldDescriptor* field = descriptor->FindFieldByName(field_name); + if (field == nullptr) { + GOOGLE_LOG(ERROR) << "Cannot find field \"" << field_name << "\" in message " + << descriptor->full_name(); + continue; + } + if (!child->children.empty()) { + // Sub-paths are only allowed for singular message fields. + if (field->is_repeated() || + field->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE) { + GOOGLE_LOG(ERROR) << "Field \"" << field_name << "\" in message " + << descriptor->full_name() + << " is not a singular message field and cannot " + << "have sub-fields."; + continue; + } + MergeMessage(child, source_reflection->GetMessage(source, field), options, + destination_reflection->MutableMessage(destination, field)); + continue; + } + if (!field->is_repeated()) { + switch (field->cpp_type()) { +#define COPY_VALUE(TYPE, Name) \ + case FieldDescriptor::CPPTYPE_##TYPE: { \ + if (source_reflection->HasField(source, field)) { \ + destination_reflection->Set##Name( \ + destination, field, source_reflection->Get##Name(source, field)); \ + } else { \ + destination_reflection->ClearField(destination, field); \ + } \ + break; \ + } + COPY_VALUE(BOOL, Bool) + COPY_VALUE(INT32, Int32) + COPY_VALUE(INT64, Int64) + COPY_VALUE(UINT32, UInt32) + COPY_VALUE(UINT64, UInt64) + COPY_VALUE(FLOAT, Float) + COPY_VALUE(DOUBLE, Double) + COPY_VALUE(ENUM, Enum) + COPY_VALUE(STRING, String) +#undef COPY_VALUE + case FieldDescriptor::CPPTYPE_MESSAGE: { + if (options.replace_message_fields()) { + destination_reflection->ClearField(destination, field); + } + if (source_reflection->HasField(source, field)) { + destination_reflection->MutableMessage(destination, field) + ->MergeFrom(source_reflection->GetMessage(source, field)); + } + break; + } + } + } else { + if (options.replace_repeated_fields()) { + destination_reflection->ClearField(destination, field); + } + switch (field->cpp_type()) { +#define COPY_REPEATED_VALUE(TYPE, Name) \ + case FieldDescriptor::CPPTYPE_##TYPE: { \ + int size = source_reflection->FieldSize(source, field); \ + for (int i = 0; i < size; ++i) { \ + destination_reflection->Add##Name( \ + destination, field, \ + source_reflection->GetRepeated##Name(source, field, i)); \ + } \ + break; \ + } + COPY_REPEATED_VALUE(BOOL, Bool) + COPY_REPEATED_VALUE(INT32, Int32) + COPY_REPEATED_VALUE(INT64, Int64) + COPY_REPEATED_VALUE(UINT32, UInt32) + COPY_REPEATED_VALUE(UINT64, UInt64) + COPY_REPEATED_VALUE(FLOAT, Float) + COPY_REPEATED_VALUE(DOUBLE, Double) + COPY_REPEATED_VALUE(ENUM, Enum) + COPY_REPEATED_VALUE(STRING, String) +#undef COPY_REPEATED_VALUE + case FieldDescriptor::CPPTYPE_MESSAGE: { + int size = source_reflection->FieldSize(source, field); + for (int i = 0; i < size; ++i) { + destination_reflection->AddMessage(destination, field) + ->MergeFrom( + source_reflection->GetRepeatedMessage(source, field, i)); + } + break; + } + } + } + } +} + +void FieldMaskTree::AddRequiredFieldPath(Node* node, + const Descriptor* descriptor) { + const int32_t field_count = descriptor->field_count(); + for (int index = 0; index < field_count; ++index) { + const FieldDescriptor* field = descriptor->field(index); + if (field->is_required()) { + const std::string& node_name = field->name(); + Node*& child = node->children[node_name]; + if (child == nullptr) { + // Add required field path to the tree + child = new Node(); + } else if (child->children.empty()) { + // If the required field is in the tree and does not have any children, + // do nothing. + continue; + } + // Add required field in the children to the tree if the field is message. + if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { + AddRequiredFieldPath(child, field->message_type()); + } + } else if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { + std::map<std::string, Node*>::const_iterator it = + node->children.find(field->name()); + if (it != node->children.end()) { + // Add required fields in the children to the + // tree if the field is a message and present in the tree. + Node* child = it->second; + if (!child->children.empty()) { + AddRequiredFieldPath(child, field->message_type()); + } + } + } + } +} + +bool FieldMaskTree::TrimMessage(const Node* node, Message* message) { + GOOGLE_DCHECK(!node->children.empty()); + const Reflection* reflection = message->GetReflection(); + const Descriptor* descriptor = message->GetDescriptor(); + const int32_t field_count = descriptor->field_count(); + bool modified = false; + for (int index = 0; index < field_count; ++index) { + const FieldDescriptor* field = descriptor->field(index); + std::map<std::string, Node*>::const_iterator it = + node->children.find(field->name()); + if (it == node->children.end()) { + if (field->is_repeated()) { + if (reflection->FieldSize(*message, field) != 0) { + modified = true; + } + } else { + if (reflection->HasField(*message, field)) { + modified = true; + } + } + reflection->ClearField(message, field); + } else { + if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { + Node* child = it->second; + if (!child->children.empty() && reflection->HasField(*message, field)) { + bool nestedMessageChanged = + TrimMessage(child, reflection->MutableMessage(message, field)); + modified = nestedMessageChanged || modified; + } + } + } + } + return modified; +} + +} // namespace + +void FieldMaskUtil::ToCanonicalForm(const FieldMask& mask, FieldMask* out) { + FieldMaskTree tree; + tree.MergeFromFieldMask(mask); + out->Clear(); + tree.MergeToFieldMask(out); +} + +void FieldMaskUtil::Union(const FieldMask& mask1, const FieldMask& mask2, + FieldMask* out) { + FieldMaskTree tree; + tree.MergeFromFieldMask(mask1); + tree.MergeFromFieldMask(mask2); + out->Clear(); + tree.MergeToFieldMask(out); +} + +void FieldMaskUtil::Intersect(const FieldMask& mask1, const FieldMask& mask2, + FieldMask* out) { + FieldMaskTree tree, intersection; + tree.MergeFromFieldMask(mask1); + for (int i = 0; i < mask2.paths_size(); ++i) { + tree.IntersectPath(mask2.paths(i), &intersection); + } + out->Clear(); + intersection.MergeToFieldMask(out); +} + +void FieldMaskUtil::Subtract(const Descriptor* descriptor, + const FieldMask& mask1, const FieldMask& mask2, + FieldMask* out) { + if (mask1.paths().empty()) { + out->Clear(); + return; + } + FieldMaskTree tree; + tree.MergeFromFieldMask(mask1); + for (int i = 0; i < mask2.paths_size(); ++i) { + tree.RemovePath(mask2.paths(i), descriptor); + } + out->Clear(); + tree.MergeToFieldMask(out); +} + +bool FieldMaskUtil::IsPathInFieldMask(StringPiece path, + const FieldMask& mask) { + for (int i = 0; i < mask.paths_size(); ++i) { + const std::string& mask_path = mask.paths(i); + if (path == mask_path) { + return true; + } else if (mask_path.length() < path.length()) { + // Also check whether mask.paths(i) is a prefix of path. + if (path.substr(0, mask_path.length() + 1).compare(mask_path + ".") == + 0) { + return true; + } + } + } + return false; +} + +void FieldMaskUtil::MergeMessageTo(const Message& source, const FieldMask& mask, + const MergeOptions& options, + Message* destination) { + GOOGLE_CHECK(source.GetDescriptor() == destination->GetDescriptor()); + // Build a FieldMaskTree and walk through the tree to merge all specified + // fields. + FieldMaskTree tree; + tree.MergeFromFieldMask(mask); + tree.MergeMessage(source, options, destination); +} + +bool FieldMaskUtil::TrimMessage(const FieldMask& mask, Message* message) { + // Build a FieldMaskTree and walk through the tree to merge all specified + // fields. + FieldMaskTree tree; + tree.MergeFromFieldMask(mask); + return tree.TrimMessage(GOOGLE_CHECK_NOTNULL(message)); +} + +bool FieldMaskUtil::TrimMessage(const FieldMask& mask, Message* message, + const TrimOptions& options) { + // Build a FieldMaskTree and walk through the tree to merge all specified + // fields. + FieldMaskTree tree; + tree.MergeFromFieldMask(mask); + // If keep_required_fields is true, implicitly add required fields of + // a message present in the tree to prevent from trimming. + if (options.keep_required_fields()) { + tree.AddRequiredFieldPath(GOOGLE_CHECK_NOTNULL(message->GetDescriptor())); + } + return tree.TrimMessage(GOOGLE_CHECK_NOTNULL(message)); +} + +} // namespace util +} // namespace protobuf +} // namespace google diff --git a/toolkit/components/protobuf/src/google/protobuf/util/field_mask_util.h b/toolkit/components/protobuf/src/google/protobuf/util/field_mask_util.h new file mode 100644 index 0000000000..d51a332c8b --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/util/field_mask_util.h @@ -0,0 +1,263 @@ +// 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. + +// Defines utilities for the FieldMask well known type. + +#ifndef GOOGLE_PROTOBUF_UTIL_FIELD_MASK_UTIL_H__ +#define GOOGLE_PROTOBUF_UTIL_FIELD_MASK_UTIL_H__ + +#include <cstdint> +#include <string> + +#include <google/protobuf/field_mask.pb.h> +#include <google/protobuf/stubs/strutil.h> +#include <google/protobuf/descriptor.h> + +// Must be included last. +#include <google/protobuf/port_def.inc> + +namespace google { +namespace protobuf { +namespace util { + +class PROTOBUF_EXPORT FieldMaskUtil { + typedef google::protobuf::FieldMask FieldMask; + + public: + // Converts FieldMask to/from string, formatted by separating each path + // with a comma (e.g., "foo_bar,baz.quz"). + static std::string ToString(const FieldMask& mask); + static void FromString(StringPiece str, FieldMask* out); + + // Populates the FieldMask with the paths corresponding to the fields with the + // given numbers, after checking that all field numbers are valid. + template <typename T> + static void FromFieldNumbers(const std::vector<int64_t>& field_numbers, + FieldMask* out) { + for (const auto field_number : field_numbers) { + const FieldDescriptor* field_desc = + T::descriptor()->FindFieldByNumber(field_number); + GOOGLE_CHECK(field_desc != nullptr) + << "Invalid field number for " << T::descriptor()->full_name() << ": " + << field_number; + AddPathToFieldMask<T>(field_desc->lowercase_name(), out); + } + } + + // Converts FieldMask to/from string, formatted according to proto3 JSON + // spec for FieldMask (e.g., "fooBar,baz.quz"). If the field name is not + // style conforming (i.e., not snake_case when converted to string, or not + // camelCase when converted from string), the conversion will fail. + static bool ToJsonString(const FieldMask& mask, std::string* out); + static bool FromJsonString(StringPiece str, FieldMask* out); + + // Get the descriptors of the fields which the given path from the message + // descriptor traverses, if field_descriptors is not null. + // Return false if the path is not valid, and the content of field_descriptors + // is unspecified. + static bool GetFieldDescriptors( + const Descriptor* descriptor, StringPiece path, + std::vector<const FieldDescriptor*>* field_descriptors); + + // Checks whether the given path is valid for type T. + template <typename T> + static bool IsValidPath(StringPiece path) { + return GetFieldDescriptors(T::descriptor(), path, nullptr); + } + + // Checks whether the given FieldMask is valid for type T. + template <typename T> + static bool IsValidFieldMask(const FieldMask& mask) { + for (int i = 0; i < mask.paths_size(); ++i) { + if (!GetFieldDescriptors(T::descriptor(), mask.paths(i), nullptr)) { + return false; + } + } + return true; + } + + // Adds a path to FieldMask after checking whether the given path is valid. + // This method check-fails if the path is not a valid path for type T. + template <typename T> + static void AddPathToFieldMask(StringPiece path, FieldMask* mask) { + GOOGLE_CHECK(IsValidPath<T>(path)) << path; + mask->add_paths(std::string(path)); + } + + // Creates a FieldMask with all fields of type T. This FieldMask only + // contains fields of T but not any sub-message fields. + template <typename T> + static FieldMask GetFieldMaskForAllFields() { + FieldMask out; + GetFieldMaskForAllFields(T::descriptor(), &out); + return out; + } + template <typename T> + PROTOBUF_DEPRECATED_MSG("Use *out = GetFieldMaskForAllFields() instead") + static void GetFieldMaskForAllFields(FieldMask* out) { + GetFieldMaskForAllFields(T::descriptor(), out); + } + // This flavor takes the protobuf type descriptor as an argument. + // Useful when the type is not known at compile time. + static void GetFieldMaskForAllFields(const Descriptor* descriptor, + FieldMask* out); + + // Converts a FieldMask to the canonical form. It will: + // 1. Remove paths that are covered by another path. For example, + // "foo.bar" is covered by "foo" and will be removed if "foo" + // is also in the FieldMask. + // 2. Sort all paths in alphabetical order. + static void ToCanonicalForm(const FieldMask& mask, FieldMask* out); + + // Creates an union of two FieldMasks. + static void Union(const FieldMask& mask1, const FieldMask& mask2, + FieldMask* out); + + // Creates an intersection of two FieldMasks. + static void Intersect(const FieldMask& mask1, const FieldMask& mask2, + FieldMask* out); + + // Subtracts mask2 from mask1 base of type T. + template <typename T> + static void Subtract(const FieldMask& mask1, const FieldMask& mask2, + FieldMask* out) { + Subtract(T::descriptor(), mask1, mask2, out); + } + // This flavor takes the protobuf type descriptor as an argument. + // Useful when the type is not known at compile time. + static void Subtract(const Descriptor* descriptor, const FieldMask& mask1, + const FieldMask& mask2, FieldMask* out); + + // Returns true if path is covered by the given FieldMask. Note that path + // "foo.bar" covers all paths like "foo.bar.baz", "foo.bar.quz.x", etc. + // Also note that parent paths are not covered by explicit child path, i.e. + // "foo.bar" does NOT cover "foo", even if "bar" is the only child. + static bool IsPathInFieldMask(StringPiece path, const FieldMask& mask); + + class MergeOptions; + // Merges fields specified in a FieldMask into another message. + static void MergeMessageTo(const Message& source, const FieldMask& mask, + const MergeOptions& options, Message* destination); + + class TrimOptions; + // Removes from 'message' any field that is not represented in the given + // FieldMask. If the FieldMask is empty, does nothing. + // Returns true if the message is modified. + static bool TrimMessage(const FieldMask& mask, Message* message); + + // Removes from 'message' any field that is not represented in the given + // FieldMask with customized TrimOptions. + // If the FieldMask is empty, does nothing. + // Returns true if the message is modified. + static bool TrimMessage(const FieldMask& mask, Message* message, + const TrimOptions& options); + + private: + friend class SnakeCaseCamelCaseTest; + // Converts a field name from snake_case to camelCase: + // 1. Every character after "_" will be converted to uppercase. + // 2. All "_"s are removed. + // The conversion will fail if: + // 1. The field name contains uppercase letters. + // 2. Any character after a "_" is not a lowercase letter. + // If the conversion succeeds, it's guaranteed that the resulted + // camelCase name will yield the original snake_case name when + // converted using CamelCaseToSnakeCase(). + // + // Note that the input can contain characters not allowed in C identifiers. + // For example, "foo_bar,baz_quz" will be converted to "fooBar,bazQuz" + // successfully. + static bool SnakeCaseToCamelCase(StringPiece input, + std::string* output); + // Converts a field name from camelCase to snake_case: + // 1. Every uppercase letter is converted to lowercase with an additional + // preceding "_". + // The conversion will fail if: + // 1. The field name contains "_"s. + // If the conversion succeeds, it's guaranteed that the resulted + // snake_case name will yield the original camelCase name when + // converted using SnakeCaseToCamelCase(). + // + // Note that the input can contain characters not allowed in C identifiers. + // For example, "fooBar,bazQuz" will be converted to "foo_bar,baz_quz" + // successfully. + static bool CamelCaseToSnakeCase(StringPiece input, + std::string* output); +}; + +class PROTOBUF_EXPORT FieldMaskUtil::MergeOptions { + public: + MergeOptions() + : replace_message_fields_(false), replace_repeated_fields_(false) {} + // When merging message fields, the default behavior is to merge the + // content of two message fields together. If you instead want to use + // the field from the source message to replace the corresponding field + // in the destination message, set this flag to true. When this flag is set, + // specified submessage fields that are missing in source will be cleared in + // destination. + void set_replace_message_fields(bool value) { + replace_message_fields_ = value; + } + bool replace_message_fields() const { return replace_message_fields_; } + // The default merging behavior will append entries from the source + // repeated field to the destination repeated field. If you only want + // to keep the entries from the source repeated field, set this flag + // to true. + void set_replace_repeated_fields(bool value) { + replace_repeated_fields_ = value; + } + bool replace_repeated_fields() const { return replace_repeated_fields_; } + + private: + bool replace_message_fields_; + bool replace_repeated_fields_; +}; + +class PROTOBUF_EXPORT FieldMaskUtil::TrimOptions { + public: + TrimOptions() : keep_required_fields_(false) {} + // When trimming message fields, the default behavior is to trim required + // fields of the present message if they are not specified in the field mask. + // If you instead want to keep required fields of the present message even + // when they are not specified in the field mask, set this flag to true. + void set_keep_required_fields(bool value) { keep_required_fields_ = value; } + bool keep_required_fields() const { return keep_required_fields_; } + + private: + bool keep_required_fields_; +}; + +} // namespace util +} // namespace protobuf +} // namespace google + +#include <google/protobuf/port_undef.inc> + +#endif // GOOGLE_PROTOBUF_UTIL_FIELD_MASK_UTIL_H__ diff --git a/toolkit/components/protobuf/src/google/protobuf/util/internal/constants.h b/toolkit/components/protobuf/src/google/protobuf/util/internal/constants.h new file mode 100644 index 0000000000..8bded86998 --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/util/internal/constants.h @@ -0,0 +1,101 @@ +// 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. + +#ifndef GOOGLE_PROTOBUF_UTIL_INTERNAL_CONSTANTS_H__ +#define GOOGLE_PROTOBUF_UTIL_INTERNAL_CONSTANTS_H__ + +#include <cstdint> + +#include <google/protobuf/stubs/common.h> + +// This file contains constants used by //net/proto2/util/converter. + +namespace google { +namespace protobuf { +namespace util { +namespace converter { +// Prefix for type URLs. +const char kTypeServiceBaseUrl[] = "type.googleapis.com"; + +// Format string for RFC3339 timestamp formatting. +const char kRfc3339TimeFormat[] = "%E4Y-%m-%dT%H:%M:%S"; + +// Same as above, but the year value is not zero-padded i.e. this accepts +// timestamps like "1-01-0001T23:59:59Z" instead of "0001-01-0001T23:59:59Z". +const char kRfc3339TimeFormatNoPadding[] = "%Y-%m-%dT%H:%M:%S"; + +// Minimum seconds allowed in a google.protobuf.Timestamp value. +const int64_t kTimestampMinSeconds = -62135596800LL; + +// Maximum seconds allowed in a google.protobuf.Timestamp value. +const int64_t kTimestampMaxSeconds = 253402300799LL; + +// Minimum seconds allowed in a google.protobuf.Duration value. +const int64_t kDurationMinSeconds = -315576000000LL; + +// Maximum seconds allowed in a google.protobuf.Duration value. +const int64_t kDurationMaxSeconds = 315576000000LL; + +// Nano seconds in a second. +const int32_t kNanosPerSecond = 1000000000; + +// Type url representing NULL values in google.protobuf.Struct type. +const char kStructNullValueTypeUrl[] = + "type.googleapis.com/google.protobuf.NullValue"; + +// Type string for google.protobuf.Struct +const char kStructType[] = "google.protobuf.Struct"; + +// Type string for struct.proto's google.protobuf.Value value type. +const char kStructValueType[] = "google.protobuf.Value"; + +// Type string for struct.proto's google.protobuf.ListValue value type. +const char kStructListValueType[] = "google.protobuf.ListValue"; + +// Type string for google.protobuf.Timestamp +const char kTimestampType[] = "google.protobuf.Timestamp"; + +// Type string for google.protobuf.Duration +const char kDurationType[] = "google.protobuf.Duration"; + +// Type URL for struct value type google.protobuf.Value +const char kStructValueTypeUrl[] = "type.googleapis.com/google.protobuf.Value"; + +// Type string for google.protobuf.Any +const char kAnyType[] = "google.protobuf.Any"; + +// The protobuf option name of jspb.message_id; +const char kOptionJspbMessageId[] = "jspb.message_id"; + +} // namespace converter +} // namespace util +} // namespace protobuf +} // namespace google +#endif // GOOGLE_PROTOBUF_UTIL_INTERNAL_CONSTANTS_H__ diff --git a/toolkit/components/protobuf/src/google/protobuf/util/internal/datapiece.cc b/toolkit/components/protobuf/src/google/protobuf/util/internal/datapiece.cc new file mode 100644 index 0000000000..3e7aa84da7 --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/util/internal/datapiece.cc @@ -0,0 +1,441 @@ +// 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. + +#include <google/protobuf/util/internal/datapiece.h> + +#include <cmath> +#include <cstdint> +#include <limits> + +#include <google/protobuf/struct.pb.h> +#include <google/protobuf/type.pb.h> +#include <google/protobuf/descriptor.h> +#include <google/protobuf/stubs/status.h> +#include <google/protobuf/stubs/strutil.h> +#include <google/protobuf/util/internal/utility.h> +#include <google/protobuf/stubs/mathutil.h> + +namespace google { +namespace protobuf { +namespace util { +namespace converter { + +using util::Status; + +namespace { + +template <typename To, typename From> +util::StatusOr<To> ValidateNumberConversion(To after, From before) { + if (after == before && + MathUtil::Sign<From>(before) == MathUtil::Sign<To>(after)) { + return after; + } else { + return util::InvalidArgumentError( + std::is_integral<From>::value ? ValueAsString(before) + : std::is_same<From, double>::value ? DoubleAsString(before) + : FloatAsString(before)); + } +} + +// For general conversion between +// int32, int64, uint32, uint64, double and float +// except conversion between double and float. +template <typename To, typename From> +util::StatusOr<To> NumberConvertAndCheck(From before) { + if (std::is_same<From, To>::value) return before; + + To after = static_cast<To>(before); + return ValidateNumberConversion(after, before); +} + +// For conversion to integer types (int32, int64, uint32, uint64) from floating +// point types (double, float) only. +template <typename To, typename From> +util::StatusOr<To> FloatingPointToIntConvertAndCheck(From before) { + if (std::is_same<From, To>::value) return before; + + To after = static_cast<To>(before); + return ValidateNumberConversion(after, before); +} + +// For conversion between double and float only. +util::StatusOr<double> FloatToDouble(float before) { + // Casting float to double should just work as double has more precision + // than float. + return static_cast<double>(before); +} + +util::StatusOr<float> DoubleToFloat(double before) { + if (std::isnan(before)) { + return std::numeric_limits<float>::quiet_NaN(); + } else if (!std::isfinite(before)) { + // Converting a double +inf/-inf to float should just work. + return static_cast<float>(before); + } else if (before > std::numeric_limits<float>::max() || + before < -std::numeric_limits<float>::max()) { + // Some doubles are larger than the largest float, but after + // rounding they will be equal to the largest float. + // We can't just attempt the conversion because that has UB if + // the value really is out-of-range. + // Here we take advantage that 1/2-ing a large floating point + // will not lose precision. + double half_before = before * 0.5; + if (half_before < std::numeric_limits<float>::max() && + half_before > -std::numeric_limits<float>::max()) { + const float half_fmax = std::numeric_limits<float>::max() * 0.5f; + // If after being cut in half, the value is less than the largest float, + // then it's safe to convert it to float. Importantly, this conversion + // rounds in the same way that the original does. + float half_after = static_cast<float>(half_before); + if (half_after <= half_fmax && half_after >= -half_fmax) { + return half_after + half_after; + } + } + // Double value outside of the range of float. + return util::InvalidArgumentError(DoubleAsString(before)); + } else { + return static_cast<float>(before); + } +} + +} // namespace + +util::StatusOr<int32_t> DataPiece::ToInt32() const { + if (type_ == TYPE_STRING) + return StringToNumber<int32_t>(safe_strto32); + + if (type_ == TYPE_DOUBLE) + return FloatingPointToIntConvertAndCheck<int32_t, double>(double_); + + if (type_ == TYPE_FLOAT) + return FloatingPointToIntConvertAndCheck<int32_t, float>(float_); + + return GenericConvert<int32_t>(); +} + +util::StatusOr<uint32_t> DataPiece::ToUint32() const { + if (type_ == TYPE_STRING) + return StringToNumber<uint32_t>(safe_strtou32); + + if (type_ == TYPE_DOUBLE) + return FloatingPointToIntConvertAndCheck<uint32_t, double>(double_); + + if (type_ == TYPE_FLOAT) + return FloatingPointToIntConvertAndCheck<uint32_t, float>(float_); + + return GenericConvert<uint32_t>(); +} + +util::StatusOr<int64_t> DataPiece::ToInt64() const { + if (type_ == TYPE_STRING) + return StringToNumber<int64_t>(safe_strto64); + + if (type_ == TYPE_DOUBLE) + return FloatingPointToIntConvertAndCheck<int64_t, double>(double_); + + if (type_ == TYPE_FLOAT) + return FloatingPointToIntConvertAndCheck<int64_t, float>(float_); + + return GenericConvert<int64_t>(); +} + +util::StatusOr<uint64_t> DataPiece::ToUint64() const { + if (type_ == TYPE_STRING) + return StringToNumber<uint64_t>(safe_strtou64); + + if (type_ == TYPE_DOUBLE) + return FloatingPointToIntConvertAndCheck<uint64_t, double>(double_); + + if (type_ == TYPE_FLOAT) + return FloatingPointToIntConvertAndCheck<uint64_t, float>(float_); + + return GenericConvert<uint64_t>(); +} + +util::StatusOr<double> DataPiece::ToDouble() const { + if (type_ == TYPE_FLOAT) { + return FloatToDouble(float_); + } + if (type_ == TYPE_STRING) { + if (str_ == "Infinity") return std::numeric_limits<double>::infinity(); + if (str_ == "-Infinity") return -std::numeric_limits<double>::infinity(); + if (str_ == "NaN") return std::numeric_limits<double>::quiet_NaN(); + util::StatusOr<double> value = StringToNumber<double>(safe_strtod); + if (value.ok() && !std::isfinite(value.value())) { + // safe_strtod converts out-of-range values to +inf/-inf, but we want + // to report them as errors. + return util::InvalidArgumentError(StrCat("\"", str_, "\"")); + } else { + return value; + } + } + return GenericConvert<double>(); +} + +util::StatusOr<float> DataPiece::ToFloat() const { + if (type_ == TYPE_DOUBLE) { + return DoubleToFloat(double_); + } + if (type_ == TYPE_STRING) { + if (str_ == "Infinity") return std::numeric_limits<float>::infinity(); + if (str_ == "-Infinity") return -std::numeric_limits<float>::infinity(); + if (str_ == "NaN") return std::numeric_limits<float>::quiet_NaN(); + // SafeStrToFloat() is used instead of safe_strtof() because the later + // does not fail on inputs like SimpleDtoa(DBL_MAX). + return StringToNumber<float>(SafeStrToFloat); + } + return GenericConvert<float>(); +} + +util::StatusOr<bool> DataPiece::ToBool() const { + switch (type_) { + case TYPE_BOOL: + return bool_; + case TYPE_STRING: + return StringToNumber<bool>(safe_strtob); + default: + return util::InvalidArgumentError( + ValueAsStringOrDefault("Wrong type. Cannot convert to Bool.")); + } +} + +util::StatusOr<std::string> DataPiece::ToString() const { + switch (type_) { + case TYPE_STRING: + return std::string(str_); + case TYPE_BYTES: { + std::string base64; + Base64Escape(str_, &base64); + return base64; + } + default: + return util::InvalidArgumentError( + ValueAsStringOrDefault("Cannot convert to string.")); + } +} + +std::string DataPiece::ValueAsStringOrDefault( + StringPiece default_string) const { + switch (type_) { + case TYPE_INT32: + return StrCat(i32_); + case TYPE_INT64: + return StrCat(i64_); + case TYPE_UINT32: + return StrCat(u32_); + case TYPE_UINT64: + return StrCat(u64_); + case TYPE_DOUBLE: + return DoubleAsString(double_); + case TYPE_FLOAT: + return FloatAsString(float_); + case TYPE_BOOL: + return SimpleBtoa(bool_); + case TYPE_STRING: + return StrCat("\"", str_.ToString(), "\""); + case TYPE_BYTES: { + std::string base64; + WebSafeBase64Escape(str_, &base64); + return StrCat("\"", base64, "\""); + } + case TYPE_NULL: + return "null"; + default: + return std::string(default_string); + } +} + +util::StatusOr<std::string> DataPiece::ToBytes() const { + if (type_ == TYPE_BYTES) return str_.ToString(); + if (type_ == TYPE_STRING) { + std::string decoded; + if (!DecodeBase64(str_, &decoded)) { + return util::InvalidArgumentError( + ValueAsStringOrDefault("Invalid data in input.")); + } + return decoded; + } else { + return util::InvalidArgumentError(ValueAsStringOrDefault( + "Wrong type. Only String or Bytes can be converted to Bytes.")); + } +} + +util::StatusOr<int> DataPiece::ToEnum(const google::protobuf::Enum* enum_type, + bool use_lower_camel_for_enums, + bool case_insensitive_enum_parsing, + bool ignore_unknown_enum_values, + bool* is_unknown_enum_value) const { + if (type_ == TYPE_NULL) return google::protobuf::NULL_VALUE; + + if (type_ == TYPE_STRING) { + // First try the given value as a name. + std::string enum_name = std::string(str_); + const google::protobuf::EnumValue* value = + FindEnumValueByNameOrNull(enum_type, enum_name); + if (value != nullptr) return value->number(); + + // Check if int version of enum is sent as string. + util::StatusOr<int32_t> int_value = ToInt32(); + if (int_value.ok()) { + if (const google::protobuf::EnumValue* enum_value = + FindEnumValueByNumberOrNull(enum_type, int_value.value())) { + return enum_value->number(); + } + } + + // Next try a normalized name. + bool should_normalize_enum = + case_insensitive_enum_parsing || use_lower_camel_for_enums; + if (should_normalize_enum) { + for (std::string::iterator it = enum_name.begin(); it != enum_name.end(); + ++it) { + *it = *it == '-' ? '_' : ascii_toupper(*it); + } + value = FindEnumValueByNameOrNull(enum_type, enum_name); + if (value != nullptr) return value->number(); + } + + // If use_lower_camel_for_enums is true try with enum name without + // underscore. This will also accept camel case names as the enum_name has + // been normalized before. + if (use_lower_camel_for_enums) { + value = FindEnumValueByNameWithoutUnderscoreOrNull(enum_type, enum_name); + if (value != nullptr) return value->number(); + } + + // If ignore_unknown_enum_values is true an unknown enum value is ignored. + if (ignore_unknown_enum_values) { + *is_unknown_enum_value = true; + if (enum_type->enumvalue_size() > 0) { + return enum_type->enumvalue(0).number(); + } + } + } else { + // We don't need to check whether the value is actually declared in the + // enum because we preserve unknown enum values as well. + return ToInt32(); + } + return util::InvalidArgumentError( + ValueAsStringOrDefault("Cannot find enum with given value.")); +} + +template <typename To> +util::StatusOr<To> DataPiece::GenericConvert() const { + switch (type_) { + case TYPE_INT32: + return NumberConvertAndCheck<To, int32_t>(i32_); + case TYPE_INT64: + return NumberConvertAndCheck<To, int64_t>(i64_); + case TYPE_UINT32: + return NumberConvertAndCheck<To, uint32_t>(u32_); + case TYPE_UINT64: + return NumberConvertAndCheck<To, uint64_t>(u64_); + case TYPE_DOUBLE: + return NumberConvertAndCheck<To, double>(double_); + case TYPE_FLOAT: + return NumberConvertAndCheck<To, float>(float_); + default: // TYPE_ENUM, TYPE_STRING, TYPE_CORD, TYPE_BOOL + return util::InvalidArgumentError(ValueAsStringOrDefault( + "Wrong type. Bool, Enum, String and Cord not supported in " + "GenericConvert.")); + } +} + +template <typename To> +util::StatusOr<To> DataPiece::StringToNumber(bool (*func)(StringPiece, + To*)) const { + if (str_.size() > 0 && (str_[0] == ' ' || str_[str_.size() - 1] == ' ')) { + return util::InvalidArgumentError(StrCat("\"", str_, "\"")); + } + To result; + if (func(str_, &result)) return result; + return util::InvalidArgumentError( + StrCat("\"", std::string(str_), "\"")); +} + +bool DataPiece::DecodeBase64(StringPiece src, std::string* dest) const { + // Try web-safe decode first, if it fails, try the non-web-safe decode. + if (WebSafeBase64Unescape(src, dest)) { + if (use_strict_base64_decoding_) { + // In strict mode, check if the escaped version gives us the same value as + // unescaped. + std::string encoded; + // WebSafeBase64Escape does no padding by default. + WebSafeBase64Escape(*dest, &encoded); + // Remove trailing padding '=' characters before comparison. + StringPiece src_no_padding = StringPiece(src).substr( + 0, HasSuffixString(src, "=") ? src.find_last_not_of('=') + 1 + : src.length()); + return encoded == src_no_padding; + } + return true; + } + + if (Base64Unescape(src, dest)) { + if (use_strict_base64_decoding_) { + std::string encoded; + Base64Escape(reinterpret_cast<const unsigned char*>(dest->data()), + dest->length(), &encoded, false); + StringPiece src_no_padding = StringPiece(src).substr( + 0, HasSuffixString(src, "=") ? src.find_last_not_of('=') + 1 + : src.length()); + return encoded == src_no_padding; + } + return true; + } + + return false; +} + +void DataPiece::InternalCopy(const DataPiece& other) { + type_ = other.type_; + use_strict_base64_decoding_ = other.use_strict_base64_decoding_; + switch (type_) { + case TYPE_INT32: + case TYPE_INT64: + case TYPE_UINT32: + case TYPE_UINT64: + case TYPE_DOUBLE: + case TYPE_FLOAT: + case TYPE_BOOL: + case TYPE_ENUM: + case TYPE_NULL: + case TYPE_BYTES: + case TYPE_STRING: { + str_ = other.str_; + break; + } + } +} + +} // namespace converter +} // namespace util +} // namespace protobuf +} // namespace google diff --git a/toolkit/components/protobuf/src/google/protobuf/util/internal/datapiece.h b/toolkit/components/protobuf/src/google/protobuf/util/internal/datapiece.h new file mode 100644 index 0000000000..6d08349acd --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/util/internal/datapiece.h @@ -0,0 +1,219 @@ +// 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. + +#ifndef GOOGLE_PROTOBUF_UTIL_INTERNAL_DATAPIECE_H__ +#define GOOGLE_PROTOBUF_UTIL_INTERNAL_DATAPIECE_H__ + +#include <cstdint> +#include <string> + +#include <google/protobuf/stubs/common.h> +#include <google/protobuf/stubs/logging.h> +#include <google/protobuf/type.pb.h> +#include <google/protobuf/stubs/statusor.h> +#include <google/protobuf/stubs/strutil.h> + +// Must be included last. +#include <google/protobuf/port_def.inc> + +namespace google { +namespace protobuf { +namespace util { +namespace converter { +class ProtoWriter; + +// Container for a single piece of data together with its data type. +// +// For primitive types (int32, int64, uint32, uint64, double, float, bool), +// the data is stored by value. +// +// For string, a StringPiece is stored. For Cord, a pointer to Cord is stored. +// Just like StringPiece, the DataPiece class does not own the storage for +// the actual string or Cord, so it is the user's responsibility to guarantee +// that the underlying storage is still valid when the DataPiece is accessed. +class PROTOBUF_EXPORT DataPiece { + public: + // Identifies data type of the value. + // These are the types supported by DataPiece. + enum Type { + TYPE_INT32 = 1, + TYPE_INT64 = 2, + TYPE_UINT32 = 3, + TYPE_UINT64 = 4, + TYPE_DOUBLE = 5, + TYPE_FLOAT = 6, + TYPE_BOOL = 7, + TYPE_ENUM = 8, + TYPE_STRING = 9, + TYPE_BYTES = 10, + TYPE_NULL = 11, // explicit NULL type + }; + + // Constructors and Destructor + explicit DataPiece(const int32_t value) + : type_(TYPE_INT32), i32_(value), use_strict_base64_decoding_(false) {} + explicit DataPiece(const int64_t value) + : type_(TYPE_INT64), i64_(value), use_strict_base64_decoding_(false) {} + explicit DataPiece(const uint32_t value) + : type_(TYPE_UINT32), u32_(value), use_strict_base64_decoding_(false) {} + explicit DataPiece(const uint64_t value) + : type_(TYPE_UINT64), u64_(value), use_strict_base64_decoding_(false) {} + explicit DataPiece(const double value) + : type_(TYPE_DOUBLE), + double_(value), + use_strict_base64_decoding_(false) {} + explicit DataPiece(const float value) + : type_(TYPE_FLOAT), float_(value), use_strict_base64_decoding_(false) {} + explicit DataPiece(const bool value) + : type_(TYPE_BOOL), bool_(value), use_strict_base64_decoding_(false) {} + DataPiece(StringPiece value, bool use_strict_base64_decoding) + : type_(TYPE_STRING), + str_(value), + use_strict_base64_decoding_(use_strict_base64_decoding) {} + // Constructor for bytes. The second parameter is not used. + DataPiece(StringPiece value, bool /*dummy*/, bool use_strict_base64_decoding) + : type_(TYPE_BYTES), + str_(value), + use_strict_base64_decoding_(use_strict_base64_decoding) {} + + DataPiece(const DataPiece& r) : type_(r.type_) { InternalCopy(r); } + + DataPiece& operator=(const DataPiece& x) { + InternalCopy(x); + return *this; + } + + static DataPiece NullData() { return DataPiece(TYPE_NULL, 0); } + + virtual ~DataPiece() { + } + + // Accessors + Type type() const { return type_; } + + bool use_strict_base64_decoding() { return use_strict_base64_decoding_; } + + StringPiece str() const { + GOOGLE_LOG_IF(DFATAL, type_ != TYPE_STRING) << "Not a string type."; + return str_; + } + + + // Parses, casts or converts the value stored in the DataPiece into an int32. + util::StatusOr<int32_t> ToInt32() const; + + // Parses, casts or converts the value stored in the DataPiece into a uint32. + util::StatusOr<uint32_t> ToUint32() const; + + // Parses, casts or converts the value stored in the DataPiece into an int64. + util::StatusOr<int64_t> ToInt64() const; + + // Parses, casts or converts the value stored in the DataPiece into a uint64. + util::StatusOr<uint64_t> ToUint64() const; + + // Parses, casts or converts the value stored in the DataPiece into a double. + util::StatusOr<double> ToDouble() const; + + // Parses, casts or converts the value stored in the DataPiece into a float. + util::StatusOr<float> ToFloat() const; + + // Parses, casts or converts the value stored in the DataPiece into a bool. + util::StatusOr<bool> ToBool() const; + + // Parses, casts or converts the value stored in the DataPiece into a string. + util::StatusOr<std::string> ToString() const; + + // Tries to convert the value contained in this datapiece to string. If the + // conversion fails, it returns the default_string. + std::string ValueAsStringOrDefault(StringPiece default_string) const; + + util::StatusOr<std::string> ToBytes() const; + + private: + friend class ProtoWriter; + + // Disallow implicit constructor. + DataPiece(); + + // Helper to create NULL or ENUM types. + DataPiece(Type type, int32_t val) + : type_(type), i32_(val), use_strict_base64_decoding_(false) {} + + // Same as the ToEnum() method above but with additional flag to ignore + // unknown enum values. + util::StatusOr<int> ToEnum(const google::protobuf::Enum* enum_type, + bool use_lower_camel_for_enums, + bool case_insensitive_enum_parsing, + bool ignore_unknown_enum_values, + bool* is_unknown_enum_value) const; + + // For numeric conversion between + // int32, int64, uint32, uint64, double, float and bool + template <typename To> + util::StatusOr<To> GenericConvert() const; + + // For conversion from string to + // int32, int64, uint32, uint64, double, float and bool + template <typename To> + util::StatusOr<To> StringToNumber(bool (*func)(StringPiece, To*)) const; + + // Decodes a base64 string. Returns true on success. + bool DecodeBase64(StringPiece src, std::string* dest) const; + + // Helper function to initialize this DataPiece with 'other'. + void InternalCopy(const DataPiece& other); + + // Data type for this piece of data. + Type type_; + + // Stored piece of data. + union { + int32_t i32_; + int64_t i64_; + uint32_t u32_; + uint64_t u64_; + double double_; + float float_; + bool bool_; + StringPiece str_; + }; + + // Uses a stricter version of base64 decoding for byte fields. + bool use_strict_base64_decoding_; +}; + +} // namespace converter +} // namespace util +} // namespace protobuf +} // namespace google + +#include <google/protobuf/port_undef.inc> + +#endif // GOOGLE_PROTOBUF_UTIL_INTERNAL_DATAPIECE_H__ diff --git a/toolkit/components/protobuf/src/google/protobuf/util/internal/default_value_objectwriter.cc b/toolkit/components/protobuf/src/google/protobuf/util/internal/default_value_objectwriter.cc new file mode 100644 index 0000000000..7f61cdafa7 --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/util/internal/default_value_objectwriter.cc @@ -0,0 +1,642 @@ +// 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. + +#include <google/protobuf/util/internal/default_value_objectwriter.h> + +#include <cstdint> +#include <unordered_map> + +#include <google/protobuf/util/internal/constants.h> +#include <google/protobuf/util/internal/utility.h> +#include <google/protobuf/stubs/map_util.h> + +namespace google { +namespace protobuf { +namespace util { +namespace converter { + +namespace { +// Helper function to convert string value to given data type by calling the +// passed converter function on the DataPiece created from "value" argument. +// If value is empty or if conversion fails, the default_value is returned. +template <typename T> +T ConvertTo(StringPiece value, + util::StatusOr<T> (DataPiece::*converter_fn)() const, + T default_value) { + if (value.empty()) return default_value; + util::StatusOr<T> result = (DataPiece(value, true).*converter_fn)(); + return result.ok() ? result.value() : default_value; +} +} // namespace + +DefaultValueObjectWriter::DefaultValueObjectWriter( + TypeResolver* type_resolver, const google::protobuf::Type& type, + ObjectWriter* ow) + : typeinfo_(TypeInfo::NewTypeInfo(type_resolver)), + own_typeinfo_(true), + type_(type), + current_(nullptr), + root_(nullptr), + suppress_empty_list_(false), + preserve_proto_field_names_(false), + use_ints_for_enums_(false), + ow_(ow) {} + +DefaultValueObjectWriter::~DefaultValueObjectWriter() { + if (own_typeinfo_) { + delete typeinfo_; + } +} + +DefaultValueObjectWriter* DefaultValueObjectWriter::RenderBool( + StringPiece name, bool value) { + if (current_ == nullptr) { + ow_->RenderBool(name, value); + } else { + RenderDataPiece(name, DataPiece(value)); + } + return this; +} + +DefaultValueObjectWriter* DefaultValueObjectWriter::RenderInt32( + StringPiece name, int32_t value) { + if (current_ == nullptr) { + ow_->RenderInt32(name, value); + } else { + RenderDataPiece(name, DataPiece(value)); + } + return this; +} + +DefaultValueObjectWriter* DefaultValueObjectWriter::RenderUint32( + StringPiece name, uint32_t value) { + if (current_ == nullptr) { + ow_->RenderUint32(name, value); + } else { + RenderDataPiece(name, DataPiece(value)); + } + return this; +} + +DefaultValueObjectWriter* DefaultValueObjectWriter::RenderInt64( + StringPiece name, int64_t value) { + if (current_ == nullptr) { + ow_->RenderInt64(name, value); + } else { + RenderDataPiece(name, DataPiece(value)); + } + return this; +} + +DefaultValueObjectWriter* DefaultValueObjectWriter::RenderUint64( + StringPiece name, uint64_t value) { + if (current_ == nullptr) { + ow_->RenderUint64(name, value); + } else { + RenderDataPiece(name, DataPiece(value)); + } + return this; +} + +DefaultValueObjectWriter* DefaultValueObjectWriter::RenderDouble( + StringPiece name, double value) { + if (current_ == nullptr) { + ow_->RenderDouble(name, value); + } else { + RenderDataPiece(name, DataPiece(value)); + } + return this; +} + +DefaultValueObjectWriter* DefaultValueObjectWriter::RenderFloat( + StringPiece name, float value) { + if (current_ == nullptr) { + ow_->RenderBool(name, value); + } else { + RenderDataPiece(name, DataPiece(value)); + } + return this; +} + +DefaultValueObjectWriter* DefaultValueObjectWriter::RenderString( + StringPiece name, StringPiece value) { + if (current_ == nullptr) { + ow_->RenderString(name, value); + } else { + // Since StringPiece is essentially a pointer, takes a copy of "value" to + // avoid ownership issues. + string_values_.emplace_back(new std::string(value)); + RenderDataPiece(name, DataPiece(*string_values_.back(), true)); + } + return this; +} + +DefaultValueObjectWriter* DefaultValueObjectWriter::RenderBytes( + StringPiece name, StringPiece value) { + if (current_ == nullptr) { + ow_->RenderBytes(name, value); + } else { + // Since StringPiece is essentially a pointer, takes a copy of "value" to + // avoid ownership issues. + string_values_.emplace_back(new std::string(value)); + RenderDataPiece(name, DataPiece(*string_values_.back(), false, true)); + } + return this; +} + +DefaultValueObjectWriter* DefaultValueObjectWriter::RenderNull( + StringPiece name) { + if (current_ == nullptr) { + ow_->RenderNull(name); + } else { + RenderDataPiece(name, DataPiece::NullData()); + } + return this; +} + +void DefaultValueObjectWriter::RegisterFieldScrubCallBack( + FieldScrubCallBack field_scrub_callback) { + field_scrub_callback_ = std::move(field_scrub_callback); +} + +DefaultValueObjectWriter::Node* DefaultValueObjectWriter::CreateNewNode( + const std::string& name, const google::protobuf::Type* type, NodeKind kind, + const DataPiece& data, bool is_placeholder, + const std::vector<std::string>& path, bool suppress_empty_list, + bool preserve_proto_field_names, bool use_ints_for_enums, + FieldScrubCallBack field_scrub_callback) { + return new Node(name, type, kind, data, is_placeholder, path, + suppress_empty_list, preserve_proto_field_names, + use_ints_for_enums, std::move(field_scrub_callback)); +} + +DefaultValueObjectWriter::Node::Node( + const std::string& name, const google::protobuf::Type* type, NodeKind kind, + const DataPiece& data, bool is_placeholder, + const std::vector<std::string>& path, bool suppress_empty_list, + bool preserve_proto_field_names, bool use_ints_for_enums, + FieldScrubCallBack field_scrub_callback) + : name_(name), + type_(type), + kind_(kind), + is_any_(false), + data_(data), + is_placeholder_(is_placeholder), + path_(path), + suppress_empty_list_(suppress_empty_list), + preserve_proto_field_names_(preserve_proto_field_names), + use_ints_for_enums_(use_ints_for_enums), + field_scrub_callback_(std::move(field_scrub_callback)) {} + +DefaultValueObjectWriter::Node* DefaultValueObjectWriter::Node::FindChild( + StringPiece name) { + if (name.empty() || kind_ != OBJECT) { + return nullptr; + } + for (Node* child : children_) { + if (child->name() == name) { + return child; + } + } + return nullptr; +} + +void DefaultValueObjectWriter::Node::WriteTo(ObjectWriter* ow) { + if (kind_ == PRIMITIVE) { + ObjectWriter::RenderDataPieceTo(data_, name_, ow); + return; + } + + // Render maps. Empty maps are rendered as "{}". + if (kind_ == MAP) { + ow->StartObject(name_); + WriteChildren(ow); + ow->EndObject(); + return; + } + + // Write out lists. If we didn't have any list in response, write out empty + // list. + if (kind_ == LIST) { + // Suppress empty lists if requested. + if (suppress_empty_list_ && is_placeholder_) return; + + ow->StartList(name_); + WriteChildren(ow); + ow->EndList(); + return; + } + + // If is_placeholder_ = true, we didn't see this node in the response, so + // skip output. + if (is_placeholder_) return; + + ow->StartObject(name_); + WriteChildren(ow); + ow->EndObject(); +} + +void DefaultValueObjectWriter::Node::WriteChildren(ObjectWriter* ow) { + for (Node* child : children_) { + child->WriteTo(ow); + } +} + +const google::protobuf::Type* DefaultValueObjectWriter::Node::GetMapValueType( + const google::protobuf::Type& found_type, const TypeInfo* typeinfo) { + // If this field is a map, we should use the type of its "Value" as + // the type of the child node. + for (int i = 0; i < found_type.fields_size(); ++i) { + const google::protobuf::Field& sub_field = found_type.fields(i); + if (sub_field.number() != 2) { + continue; + } + if (sub_field.kind() != google::protobuf::Field::TYPE_MESSAGE) { + // This map's value type is not a message type. We don't need to + // get the field_type in this case. + break; + } + util::StatusOr<const google::protobuf::Type*> sub_type = + typeinfo->ResolveTypeUrl(sub_field.type_url()); + if (!sub_type.ok()) { + GOOGLE_LOG(WARNING) << "Cannot resolve type '" << sub_field.type_url() << "'."; + } else { + return sub_type.value(); + } + break; + } + return nullptr; +} + +void DefaultValueObjectWriter::Node::PopulateChildren( + const TypeInfo* typeinfo) { + // Ignores well known types that don't require automatically populating their + // primitive children. For type "Any", we only populate its children when the + // "@type" field is set. + // TODO(tsun): remove "kStructValueType" from the list. It's being checked + // now because of a bug in the tool-chain that causes the "oneof_index" + // of kStructValueType to not be set correctly. + if (type_ == nullptr || type_->name() == kAnyType || + type_->name() == kStructType || type_->name() == kTimestampType || + type_->name() == kDurationType || type_->name() == kStructValueType) { + return; + } + std::vector<Node*> new_children; + std::unordered_map<std::string, int> orig_children_map; + + // Creates a map of child nodes to speed up lookup. + for (int i = 0; i < children_.size(); ++i) { + InsertIfNotPresent(&orig_children_map, children_[i]->name_, i); + } + + for (int i = 0; i < type_->fields_size(); ++i) { + const google::protobuf::Field& field = type_->fields(i); + + // This code is checking if the field to be added to the tree should be + // scrubbed or not by calling the field_scrub_callback_ callback function. + std::vector<std::string> path; + if (!path_.empty()) { + path.insert(path.begin(), path_.begin(), path_.end()); + } + path.push_back(field.name()); + if (field_scrub_callback_ && field_scrub_callback_(path, &field)) { + continue; + } + + std::unordered_map<std::string, int>::iterator found = + orig_children_map.find(field.name()); + // If the child field has already been set, we just add it to the new list + // of children. + if (found != orig_children_map.end()) { + new_children.push_back(children_[found->second]); + children_[found->second] = nullptr; + continue; + } + + const google::protobuf::Type* field_type = nullptr; + bool is_map = false; + NodeKind kind = PRIMITIVE; + + if (field.kind() == google::protobuf::Field::TYPE_MESSAGE) { + kind = OBJECT; + util::StatusOr<const google::protobuf::Type*> found_result = + typeinfo->ResolveTypeUrl(field.type_url()); + if (!found_result.ok()) { + // "field" is of an unknown type. + GOOGLE_LOG(WARNING) << "Cannot resolve type '" << field.type_url() << "'."; + } else { + const google::protobuf::Type* found_type = found_result.value(); + is_map = IsMap(field, *found_type); + + if (!is_map) { + field_type = found_type; + } else { + // If this field is a map, we should use the type of its "Value" as + // the type of the child node. + field_type = GetMapValueType(*found_type, typeinfo); + kind = MAP; + } + } + } + + if (!is_map && + field.cardinality() == google::protobuf::Field::CARDINALITY_REPEATED) { + kind = LIST; + } + + // If oneof_index() != 0, the child field is part of a "oneof", which means + // the child field is optional and we shouldn't populate its default + // primitive value. + if (field.oneof_index() != 0 && kind == PRIMITIVE) continue; + + // If the child field is of primitive type, sets its data to the default + // value of its type. + std::unique_ptr<Node> child( + new Node(preserve_proto_field_names_ ? field.name() : field.json_name(), + field_type, kind, + kind == PRIMITIVE ? CreateDefaultDataPieceForField( + field, typeinfo, use_ints_for_enums_) + : DataPiece::NullData(), + true, path, suppress_empty_list_, preserve_proto_field_names_, + use_ints_for_enums_, field_scrub_callback_)); + new_children.push_back(child.release()); + } + // Adds all leftover nodes in children_ to the beginning of new_child. + for (int i = 0; i < children_.size(); ++i) { + if (children_[i] == nullptr) { + continue; + } + new_children.insert(new_children.begin(), children_[i]); + children_[i] = nullptr; + } + children_.swap(new_children); +} + +void DefaultValueObjectWriter::MaybePopulateChildrenOfAny(Node* node) { + // If this is an "Any" node with "@type" already given and no other children + // have been added, populates its children. + if (node != nullptr && node->is_any() && node->type() != nullptr && + node->type()->name() != kAnyType && node->number_of_children() == 1) { + node->PopulateChildren(typeinfo_); + } +} + +DataPiece DefaultValueObjectWriter::FindEnumDefault( + const google::protobuf::Field& field, const TypeInfo* typeinfo, + bool use_ints_for_enums) { + const google::protobuf::Enum* enum_type = + typeinfo->GetEnumByTypeUrl(field.type_url()); + if (!enum_type) { + GOOGLE_LOG(WARNING) << "Could not find enum with type '" << field.type_url() + << "'"; + return DataPiece::NullData(); + } + if (!field.default_value().empty()) { + if (!use_ints_for_enums) { + return DataPiece(field.default_value(), true); + } else { + const std::string& enum_default_value_name = field.default_value(); + for (int enum_index = 0; enum_index < enum_type->enumvalue_size(); + ++enum_index) { + auto& enum_value = enum_type->enumvalue(enum_index); + if (enum_value.name() == enum_default_value_name) + return DataPiece(enum_value.number()); + } + GOOGLE_LOG(WARNING) << "Could not find enum value '" << enum_default_value_name + << "' with type '" << field.type_url() << "'"; + return DataPiece::NullData(); + } + } + // We treat the first value as the default if none is specified. + return enum_type->enumvalue_size() > 0 + ? (use_ints_for_enums + ? DataPiece(enum_type->enumvalue(0).number()) + : DataPiece(enum_type->enumvalue(0).name(), true)) + : DataPiece::NullData(); +} + +DataPiece DefaultValueObjectWriter::CreateDefaultDataPieceForField( + const google::protobuf::Field& field, const TypeInfo* typeinfo, + bool use_ints_for_enums) { + switch (field.kind()) { + case google::protobuf::Field::TYPE_DOUBLE: { + return DataPiece(ConvertTo<double>( + field.default_value(), &DataPiece::ToDouble, static_cast<double>(0))); + } + case google::protobuf::Field::TYPE_FLOAT: { + return DataPiece(ConvertTo<float>( + field.default_value(), &DataPiece::ToFloat, static_cast<float>(0))); + } + case google::protobuf::Field::TYPE_INT64: + case google::protobuf::Field::TYPE_SINT64: + case google::protobuf::Field::TYPE_SFIXED64: { + return DataPiece(ConvertTo<int64_t>( + field.default_value(), &DataPiece::ToInt64, static_cast<int64_t>(0))); + } + case google::protobuf::Field::TYPE_UINT64: + case google::protobuf::Field::TYPE_FIXED64: { + return DataPiece(ConvertTo<uint64_t>(field.default_value(), + &DataPiece::ToUint64, + static_cast<uint64_t>(0))); + } + case google::protobuf::Field::TYPE_INT32: + case google::protobuf::Field::TYPE_SINT32: + case google::protobuf::Field::TYPE_SFIXED32: { + return DataPiece(ConvertTo<int32_t>( + field.default_value(), &DataPiece::ToInt32, static_cast<int32_t>(0))); + } + case google::protobuf::Field::TYPE_BOOL: { + return DataPiece( + ConvertTo<bool>(field.default_value(), &DataPiece::ToBool, false)); + } + case google::protobuf::Field::TYPE_STRING: { + return DataPiece(field.default_value(), true); + } + case google::protobuf::Field::TYPE_BYTES: { + return DataPiece(field.default_value(), false, true); + } + case google::protobuf::Field::TYPE_UINT32: + case google::protobuf::Field::TYPE_FIXED32: { + return DataPiece(ConvertTo<uint32_t>(field.default_value(), + &DataPiece::ToUint32, + static_cast<uint32_t>(0))); + } + case google::protobuf::Field::TYPE_ENUM: { + return FindEnumDefault(field, typeinfo, use_ints_for_enums); + } + default: { + return DataPiece::NullData(); + } + } +} + +DefaultValueObjectWriter* DefaultValueObjectWriter::StartObject( + StringPiece name) { + if (current_ == nullptr) { + std::vector<std::string> path; + root_.reset(CreateNewNode(std::string(name), &type_, OBJECT, + DataPiece::NullData(), false, path, + suppress_empty_list_, preserve_proto_field_names_, + use_ints_for_enums_, field_scrub_callback_)); + root_->PopulateChildren(typeinfo_); + current_ = root_.get(); + return this; + } + MaybePopulateChildrenOfAny(current_); + Node* child = current_->FindChild(name); + if (current_->kind() == LIST || current_->kind() == MAP || child == nullptr) { + // If current_ is a list or a map node, we should create a new child and use + // the type of current_ as the type of the new child. + std::unique_ptr<Node> node( + CreateNewNode(std::string(name), + ((current_->kind() == LIST || current_->kind() == MAP) + ? current_->type() + : nullptr), + OBJECT, DataPiece::NullData(), false, + child == nullptr ? current_->path() : child->path(), + suppress_empty_list_, preserve_proto_field_names_, + use_ints_for_enums_, field_scrub_callback_)); + child = node.get(); + current_->AddChild(node.release()); + } + + child->set_is_placeholder(false); + if (child->kind() == OBJECT && child->number_of_children() == 0) { + child->PopulateChildren(typeinfo_); + } + + stack_.push(current_); + current_ = child; + return this; +} + +DefaultValueObjectWriter* DefaultValueObjectWriter::EndObject() { + if (stack_.empty()) { + // The root object ends here. Writes out the tree. + WriteRoot(); + return this; + } + current_ = stack_.top(); + stack_.pop(); + return this; +} + +DefaultValueObjectWriter* DefaultValueObjectWriter::StartList( + StringPiece name) { + if (current_ == nullptr) { + std::vector<std::string> path; + root_.reset(CreateNewNode(std::string(name), &type_, LIST, + DataPiece::NullData(), false, path, + suppress_empty_list_, preserve_proto_field_names_, + use_ints_for_enums_, field_scrub_callback_)); + current_ = root_.get(); + return this; + } + MaybePopulateChildrenOfAny(current_); + Node* child = current_->FindChild(name); + if (child == nullptr || child->kind() != LIST) { + std::unique_ptr<Node> node(CreateNewNode( + std::string(name), nullptr, LIST, DataPiece::NullData(), false, + child == nullptr ? current_->path() : child->path(), + suppress_empty_list_, preserve_proto_field_names_, use_ints_for_enums_, + field_scrub_callback_)); + child = node.get(); + current_->AddChild(node.release()); + } + child->set_is_placeholder(false); + + stack_.push(current_); + current_ = child; + return this; +} + +void DefaultValueObjectWriter::WriteRoot() { + root_->WriteTo(ow_); + root_.reset(nullptr); + current_ = nullptr; +} + +DefaultValueObjectWriter* DefaultValueObjectWriter::EndList() { + if (stack_.empty()) { + WriteRoot(); + return this; + } + current_ = stack_.top(); + stack_.pop(); + return this; +} + +void DefaultValueObjectWriter::RenderDataPiece(StringPiece name, + const DataPiece& data) { + MaybePopulateChildrenOfAny(current_); + if (current_->type() != nullptr && current_->type()->name() == kAnyType && + name == "@type") { + util::StatusOr<std::string> data_string = data.ToString(); + if (data_string.ok()) { + const std::string& string_value = data_string.value(); + // If the type of current_ is "Any" and its "@type" field is being set + // here, sets the type of current_ to be the type specified by the + // "@type". + util::StatusOr<const google::protobuf::Type*> found_type = + typeinfo_->ResolveTypeUrl(string_value); + if (!found_type.ok()) { + GOOGLE_LOG(WARNING) << "Failed to resolve type '" << string_value << "'."; + } else { + current_->set_type(found_type.value()); + } + current_->set_is_any(true); + // If the "@type" field is placed after other fields, we should populate + // other children of primitive type now. Otherwise, we should wait until + // the first value field is rendered before we populate the children, + // because the "value" field of a Any message could be omitted. + if (current_->number_of_children() > 1 && current_->type() != nullptr) { + current_->PopulateChildren(typeinfo_); + } + } + } + Node* child = current_->FindChild(name); + if (child == nullptr || child->kind() != PRIMITIVE) { + // No children are found, creates a new child. + std::unique_ptr<Node> node( + CreateNewNode(std::string(name), nullptr, PRIMITIVE, data, false, + child == nullptr ? current_->path() : child->path(), + suppress_empty_list_, preserve_proto_field_names_, + use_ints_for_enums_, field_scrub_callback_)); + current_->AddChild(node.release()); + } else { + child->set_data(data); + child->set_is_placeholder(false); + } +} + +} // namespace converter +} // namespace util +} // namespace protobuf +} // namespace google diff --git a/toolkit/components/protobuf/src/google/protobuf/util/internal/default_value_objectwriter.h b/toolkit/components/protobuf/src/google/protobuf/util/internal/default_value_objectwriter.h new file mode 100644 index 0000000000..a9e1673fa1 --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/util/internal/default_value_objectwriter.h @@ -0,0 +1,332 @@ +// 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. + +#ifndef GOOGLE_PROTOBUF_UTIL_INTERNAL_DEFAULT_VALUE_OBJECTWRITER_H__ +#define GOOGLE_PROTOBUF_UTIL_INTERNAL_DEFAULT_VALUE_OBJECTWRITER_H__ + +#include <cstdint> +#include <functional> +#include <memory> +#include <stack> +#include <vector> + +#include <google/protobuf/stubs/common.h> +#include <google/protobuf/stubs/strutil.h> +#include <google/protobuf/util/internal/datapiece.h> +#include <google/protobuf/util/internal/object_writer.h> +#include <google/protobuf/util/internal/type_info.h> +#include <google/protobuf/util/internal/utility.h> +#include <google/protobuf/util/type_resolver.h> + +// Must be included last. +#include <google/protobuf/port_def.inc> + +namespace google { +namespace protobuf { +namespace util { +namespace converter { + +// An ObjectWriter that renders non-repeated primitive fields of proto messages +// with their default values. DefaultValueObjectWriter holds objects, lists and +// fields it receives in a tree structure and writes them out to another +// ObjectWriter when EndObject() is called on the root object. It also writes +// out all non-repeated primitive fields that haven't been explicitly rendered +// with their default values (0 for numbers, "" for strings, etc). +class PROTOBUF_EXPORT DefaultValueObjectWriter : public ObjectWriter { + public: + // A Callback function to check whether a field needs to be scrubbed. + // + // Returns true if the field should not be present in the output. Returns + // false otherwise. + // + // The 'path' parameter is a vector of path to the field from root. For + // example: if a nested field "a.b.c" (b is the parent message field of c and + // a is the parent message field of b), then the vector should contain { "a", + // "b", "c" }. + // + // The Field* should point to the google::protobuf::Field of "c". + typedef std::function<bool( + const std::vector<std::string>& /*path of the field*/, + const google::protobuf::Field* /*field*/)> + FieldScrubCallBack; + + DefaultValueObjectWriter(TypeResolver* type_resolver, + const google::protobuf::Type& type, + ObjectWriter* ow); + + ~DefaultValueObjectWriter() override; + + // ObjectWriter methods. + DefaultValueObjectWriter* StartObject(StringPiece name) override; + + DefaultValueObjectWriter* EndObject() override; + + DefaultValueObjectWriter* StartList(StringPiece name) override; + + DefaultValueObjectWriter* EndList() override; + + DefaultValueObjectWriter* RenderBool(StringPiece name, + bool value) override; + + DefaultValueObjectWriter* RenderInt32(StringPiece name, + int32_t value) override; + + DefaultValueObjectWriter* RenderUint32(StringPiece name, + uint32_t value) override; + + DefaultValueObjectWriter* RenderInt64(StringPiece name, + int64_t value) override; + + DefaultValueObjectWriter* RenderUint64(StringPiece name, + uint64_t value) override; + + DefaultValueObjectWriter* RenderDouble(StringPiece name, + double value) override; + + DefaultValueObjectWriter* RenderFloat(StringPiece name, + float value) override; + + DefaultValueObjectWriter* RenderString(StringPiece name, + StringPiece value) override; + DefaultValueObjectWriter* RenderBytes(StringPiece name, + StringPiece value) override; + + DefaultValueObjectWriter* RenderNull(StringPiece name) override; + + // Register the callback for scrubbing of fields. + void RegisterFieldScrubCallBack(FieldScrubCallBack field_scrub_callback); + + // If set to true, empty lists are suppressed from output when default values + // are written. + void set_suppress_empty_list(bool value) { suppress_empty_list_ = value; } + + // If set to true, original proto field names are used + void set_preserve_proto_field_names(bool value) { + preserve_proto_field_names_ = value; + } + + // If set to true, enums are rendered as ints from output when default values + // are written. + void set_print_enums_as_ints(bool value) { use_ints_for_enums_ = value; } + + protected: + enum NodeKind { + PRIMITIVE = 0, + OBJECT = 1, + LIST = 2, + MAP = 3, + }; + + // "Node" represents a node in the tree that holds the input of + // DefaultValueObjectWriter. + class PROTOBUF_EXPORT Node { + public: + Node(const std::string& name, const google::protobuf::Type* type, + NodeKind kind, const DataPiece& data, bool is_placeholder, + const std::vector<std::string>& path, bool suppress_empty_list, + bool preserve_proto_field_names, bool use_ints_for_enums, + FieldScrubCallBack field_scrub_callback); + virtual ~Node() { + for (int i = 0; i < children_.size(); ++i) { + delete children_[i]; + } + } + + // Adds a child to this node. Takes ownership of this child. + void AddChild(Node* child) { children_.push_back(child); } + + // Finds the child given its name. + Node* FindChild(StringPiece name); + + // Populates children of this Node based on its type. If there are already + // children created, they will be merged to the result. Caller should pass + // in TypeInfo for looking up types of the children. + virtual void PopulateChildren(const TypeInfo* typeinfo); + + // If this node is a leaf (has data), writes the current node to the + // ObjectWriter; if not, then recursively writes the children to the + // ObjectWriter. + virtual void WriteTo(ObjectWriter* ow); + + // Accessors + const std::string& name() const { return name_; } + + const std::vector<std::string>& path() const { return path_; } + + const google::protobuf::Type* type() const { return type_; } + + void set_type(const google::protobuf::Type* type) { type_ = type; } + + NodeKind kind() const { return kind_; } + + int number_of_children() const { return children_.size(); } + + void set_data(const DataPiece& data) { data_ = data; } + + bool is_any() const { return is_any_; } + + void set_is_any(bool is_any) { is_any_ = is_any; } + + void set_is_placeholder(bool is_placeholder) { + is_placeholder_ = is_placeholder; + } + + protected: + // Returns the Value Type of a map given the Type of the map entry and a + // TypeInfo instance. + const google::protobuf::Type* GetMapValueType( + const google::protobuf::Type& found_type, const TypeInfo* typeinfo); + + // Calls WriteTo() on every child in children_. + void WriteChildren(ObjectWriter* ow); + + // The name of this node. + std::string name_; + // google::protobuf::Type of this node. Owned by TypeInfo. + const google::protobuf::Type* type_; + // The kind of this node. + NodeKind kind_; + // Whether this is a node for "Any". + bool is_any_; + // The data of this node when it is a leaf node. + DataPiece data_; + // Children of this node. + std::vector<Node*> children_; + // Whether this node is a placeholder for an object or list automatically + // generated when creating the parent node. Should be set to false after + // the parent node's StartObject()/StartList() method is called with this + // node's name. + bool is_placeholder_; + + // Path of the field of this node + std::vector<std::string> path_; + + // Whether to suppress empty list output. + bool suppress_empty_list_; + + // Whether to preserve original proto field names + bool preserve_proto_field_names_; + + // Whether to always print enums as ints + bool use_ints_for_enums_; + + // Function for determining whether a field needs to be scrubbed or not. + FieldScrubCallBack field_scrub_callback_; + + private: + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Node); + }; + + // Creates a new Node and returns it. Caller owns memory of returned object. + virtual Node* CreateNewNode(const std::string& name, + const google::protobuf::Type* type, NodeKind kind, + const DataPiece& data, bool is_placeholder, + const std::vector<std::string>& path, + bool suppress_empty_list, + bool preserve_proto_field_names, + bool use_ints_for_enums, + FieldScrubCallBack field_scrub_callback); + + // Creates a DataPiece containing the default value of the type of the field. + static DataPiece CreateDefaultDataPieceForField( + const google::protobuf::Field& field, const TypeInfo* typeinfo) { + return CreateDefaultDataPieceForField(field, typeinfo, false); + } + + // Same as the above but with a flag to use ints instead of enum names. + static DataPiece CreateDefaultDataPieceForField( + const google::protobuf::Field& field, const TypeInfo* typeinfo, + bool use_ints_for_enums); + + protected: + // Returns a pointer to current Node in tree. + Node* current() { return current_; } + + private: + // Populates children of "node" if it is an "any" Node and its real type has + // been given. + void MaybePopulateChildrenOfAny(Node* node); + + // Writes the root_ node to ow_ and resets the root_ and current_ pointer to + // nullptr. + void WriteRoot(); + + // Adds or replaces the data_ of a primitive child node. + void RenderDataPiece(StringPiece name, const DataPiece& data); + + // Returns the default enum value as a DataPiece, or the first enum value if + // there is no default. For proto3, where we cannot specify an explicit + // default, a zero value will always be returned. + static DataPiece FindEnumDefault(const google::protobuf::Field& field, + const TypeInfo* typeinfo, + bool use_ints_for_enums); + + // Type information for all the types used in the descriptor. Used to find + // google::protobuf::Type of nested messages/enums. + const TypeInfo* typeinfo_; + // Whether the TypeInfo object is owned by this class. + bool own_typeinfo_; + // google::protobuf::Type of the root message type. + const google::protobuf::Type& type_; + // Holds copies of strings passed to RenderString. + std::vector<std::unique_ptr<std::string>> string_values_; + + // The current Node. Owned by its parents. + Node* current_; + // The root Node. + std::unique_ptr<Node> root_; + // The stack to hold the path of Nodes from current_ to root_; + std::stack<Node*> stack_; + + // Whether to suppress output of empty lists. + bool suppress_empty_list_; + + // Whether to preserve original proto field names + bool preserve_proto_field_names_; + + // Whether to always print enums as ints + bool use_ints_for_enums_; + + // Function for determining whether a field needs to be scrubbed or not. + FieldScrubCallBack field_scrub_callback_; + + ObjectWriter* ow_; + + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(DefaultValueObjectWriter); +}; + +} // namespace converter +} // namespace util +} // namespace protobuf +} // namespace google + +#include <google/protobuf/port_undef.inc> + +#endif // GOOGLE_PROTOBUF_UTIL_INTERNAL_DEFAULT_VALUE_OBJECTWRITER_H__ diff --git a/toolkit/components/protobuf/src/google/protobuf/util/internal/error_listener.cc b/toolkit/components/protobuf/src/google/protobuf/util/internal/error_listener.cc new file mode 100644 index 0000000000..538307bae2 --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/util/internal/error_listener.cc @@ -0,0 +1,42 @@ +// 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. + +#include <google/protobuf/util/internal/error_listener.h> + +namespace google { +namespace protobuf { +namespace util { +namespace converter { + + +} // namespace converter +} // namespace util +} // namespace protobuf +} // namespace google diff --git a/toolkit/components/protobuf/src/google/protobuf/util/internal/error_listener.h b/toolkit/components/protobuf/src/google/protobuf/util/internal/error_listener.h new file mode 100644 index 0000000000..8c9c501682 --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/util/internal/error_listener.h @@ -0,0 +1,109 @@ +// 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. + +#ifndef GOOGLE_PROTOBUF_UTIL_INTERNAL_ERROR_LISTENER_H__ +#define GOOGLE_PROTOBUF_UTIL_INTERNAL_ERROR_LISTENER_H__ + +#include <algorithm> +#include <memory> +#include <string> +#include <vector> + +#include <google/protobuf/stubs/callback.h> +#include <google/protobuf/stubs/common.h> +#include <google/protobuf/stubs/logging.h> +#include <google/protobuf/stubs/strutil.h> +#include <google/protobuf/util/internal/location_tracker.h> + +// Must be included last. +#include <google/protobuf/port_def.inc> + +namespace google { +namespace protobuf { +namespace util { +namespace converter { + +// Interface for error listener. +class PROTOBUF_EXPORT ErrorListener { + public: + virtual ~ErrorListener() {} + + // Reports an invalid name at the given location. + virtual void InvalidName(const LocationTrackerInterface& loc, + StringPiece invalid_name, + StringPiece message) = 0; + + // Reports an invalid value for a field. + virtual void InvalidValue(const LocationTrackerInterface& loc, + StringPiece type_name, + StringPiece value) = 0; + + // Reports a missing required field. + virtual void MissingField(const LocationTrackerInterface& loc, + StringPiece missing_name) = 0; + + protected: + ErrorListener() {} + + private: + // Do not add any data members to this class. + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ErrorListener); +}; + +// An error listener that ignores all errors. +class PROTOBUF_EXPORT NoopErrorListener : public ErrorListener { + public: + NoopErrorListener() {} + ~NoopErrorListener() override {} + + void InvalidName(const LocationTrackerInterface& /*loc*/, + StringPiece /* invalid_name */, + StringPiece /* message */) override {} + + void InvalidValue(const LocationTrackerInterface& /*loc*/, + StringPiece /* type_name */, + StringPiece /* value */) override {} + + void MissingField(const LocationTrackerInterface& /* loc */, + StringPiece /* missing_name */) override {} + + private: + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(NoopErrorListener); +}; + + +} // namespace converter +} // namespace util +} // namespace protobuf +} // namespace google + +#include <google/protobuf/port_undef.inc> + +#endif // GOOGLE_PROTOBUF_UTIL_INTERNAL_ERROR_LISTENER_H__ diff --git a/toolkit/components/protobuf/src/google/protobuf/util/internal/expecting_objectwriter.h b/toolkit/components/protobuf/src/google/protobuf/util/internal/expecting_objectwriter.h new file mode 100644 index 0000000000..76fe2b6049 --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/util/internal/expecting_objectwriter.h @@ -0,0 +1,250 @@ +// 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. + +#ifndef GOOGLE_PROTOBUF_UTIL_INTERNAL_EXPECTING_OBJECTWRITER_H__ +#define GOOGLE_PROTOBUF_UTIL_INTERNAL_EXPECTING_OBJECTWRITER_H__ + +// An implementation of ObjectWriter that automatically sets the +// gmock expectations for the response to a method. Every method +// returns the object itself for chaining. +// +// Usage: +// // Setup +// MockObjectWriter mock; +// ExpectingObjectWriter ow(&mock); +// +// // Set expectation +// ow.StartObject("") +// ->RenderString("key", "value") +// ->EndObject(); +// +// // Actual testing +// mock.StartObject(StringPiece()) +// ->RenderString("key", "value") +// ->EndObject(); + +#include <cstdint> + +#include <google/protobuf/stubs/common.h> +#include <gmock/gmock.h> +#include <google/protobuf/stubs/strutil.h> +#include <google/protobuf/util/internal/object_writer.h> + +namespace google { +namespace protobuf { +namespace util { +namespace converter { + +using testing::Eq; +using testing::IsEmpty; +using testing::NanSensitiveDoubleEq; +using testing::NanSensitiveFloatEq; +using testing::Return; +using testing::StrEq; +using testing::TypedEq; + +class MockObjectWriter : public ObjectWriter { + public: + MockObjectWriter() {} + + MOCK_METHOD(ObjectWriter*, StartObject, (StringPiece), (override)); + MOCK_METHOD(ObjectWriter*, EndObject, (), (override)); + MOCK_METHOD(ObjectWriter*, StartList, (StringPiece), (override)); + MOCK_METHOD(ObjectWriter*, EndList, (), (override)); + MOCK_METHOD(ObjectWriter*, RenderBool, (StringPiece, bool), (override)); + MOCK_METHOD(ObjectWriter*, RenderInt32, (StringPiece, int32_t), + (override)); + MOCK_METHOD(ObjectWriter*, RenderUint32, (StringPiece, uint32_t), + (override)); + MOCK_METHOD(ObjectWriter*, RenderInt64, (StringPiece, int64_t), + (override)); + MOCK_METHOD(ObjectWriter*, RenderUint64, (StringPiece, uint64_t), + (override)); + MOCK_METHOD(ObjectWriter*, RenderDouble, (StringPiece, double), + (override)); + MOCK_METHOD(ObjectWriter*, RenderFloat, (StringPiece, float), + (override)); + MOCK_METHOD(ObjectWriter*, RenderString, + (StringPiece, StringPiece), (override)); + MOCK_METHOD(ObjectWriter*, RenderBytes, (StringPiece, StringPiece), + (override)); + MOCK_METHOD(ObjectWriter*, RenderNull, (StringPiece), (override)); +}; + +class ExpectingObjectWriter : public ObjectWriter { + public: + explicit ExpectingObjectWriter(MockObjectWriter* mock) : mock_(mock) {} + + ObjectWriter* StartObject(StringPiece name) override { + (name.empty() ? EXPECT_CALL(*mock_, StartObject(IsEmpty())) + : EXPECT_CALL(*mock_, StartObject(Eq(std::string(name))))) + .WillOnce(Return(mock_)) + .RetiresOnSaturation(); + return this; + } + + ObjectWriter* EndObject() override { + EXPECT_CALL(*mock_, EndObject()) + .WillOnce(Return(mock_)) + .RetiresOnSaturation(); + return this; + } + + ObjectWriter* StartList(StringPiece name) override { + (name.empty() ? EXPECT_CALL(*mock_, StartList(IsEmpty())) + : EXPECT_CALL(*mock_, StartList(Eq(std::string(name))))) + .WillOnce(Return(mock_)) + .RetiresOnSaturation(); + return this; + } + + ObjectWriter* EndList() override { + EXPECT_CALL(*mock_, EndList()) + .WillOnce(Return(mock_)) + .RetiresOnSaturation(); + return this; + } + + ObjectWriter* RenderBool(StringPiece name, bool value) override { + (name.empty() + ? EXPECT_CALL(*mock_, RenderBool(IsEmpty(), TypedEq<bool>(value))) + : EXPECT_CALL(*mock_, + RenderBool(Eq(std::string(name)), TypedEq<bool>(value)))) + .WillOnce(Return(mock_)) + .RetiresOnSaturation(); + return this; + } + + ObjectWriter* RenderInt32(StringPiece name, int32_t value) override { + (name.empty() + ? EXPECT_CALL(*mock_, RenderInt32(IsEmpty(), TypedEq<int32_t>(value))) + : EXPECT_CALL(*mock_, RenderInt32(Eq(std::string(name)), + TypedEq<int32_t>(value)))) + .WillOnce(Return(mock_)) + .RetiresOnSaturation(); + return this; + } + + ObjectWriter* RenderUint32(StringPiece name, uint32_t value) override { + (name.empty() ? EXPECT_CALL(*mock_, RenderUint32(IsEmpty(), + TypedEq<uint32_t>(value))) + : EXPECT_CALL(*mock_, RenderUint32(Eq(std::string(name)), + TypedEq<uint32_t>(value)))) + .WillOnce(Return(mock_)) + .RetiresOnSaturation(); + return this; + } + + ObjectWriter* RenderInt64(StringPiece name, int64_t value) override { + (name.empty() + ? EXPECT_CALL(*mock_, RenderInt64(IsEmpty(), TypedEq<int64_t>(value))) + : EXPECT_CALL(*mock_, RenderInt64(Eq(std::string(name)), + TypedEq<int64_t>(value)))) + .WillOnce(Return(mock_)) + .RetiresOnSaturation(); + return this; + } + + ObjectWriter* RenderUint64(StringPiece name, uint64_t value) override { + (name.empty() ? EXPECT_CALL(*mock_, RenderUint64(IsEmpty(), + TypedEq<uint64_t>(value))) + : EXPECT_CALL(*mock_, RenderUint64(Eq(std::string(name)), + TypedEq<uint64_t>(value)))) + .WillOnce(Return(mock_)) + .RetiresOnSaturation(); + return this; + } + + ObjectWriter* RenderDouble(StringPiece name, double value) override { + (name.empty() + ? EXPECT_CALL(*mock_, + RenderDouble(IsEmpty(), NanSensitiveDoubleEq(value))) + : EXPECT_CALL(*mock_, RenderDouble(Eq(std::string(name)), + NanSensitiveDoubleEq(value)))) + .WillOnce(Return(mock_)) + .RetiresOnSaturation(); + return this; + } + + ObjectWriter* RenderFloat(StringPiece name, float value) override { + (name.empty() + ? EXPECT_CALL(*mock_, + RenderFloat(IsEmpty(), NanSensitiveFloatEq(value))) + : EXPECT_CALL(*mock_, RenderFloat(Eq(std::string(name)), + NanSensitiveFloatEq(value)))) + .WillOnce(Return(mock_)) + .RetiresOnSaturation(); + return this; + } + + ObjectWriter* RenderString(StringPiece name, + StringPiece value) override { + (name.empty() ? EXPECT_CALL(*mock_, RenderString(IsEmpty(), + TypedEq<StringPiece>( + std::string(value)))) + : EXPECT_CALL(*mock_, RenderString(Eq(std::string(name)), + TypedEq<StringPiece>( + std::string(value))))) + .WillOnce(Return(mock_)) + .RetiresOnSaturation(); + return this; + } + virtual ObjectWriter* RenderBytes(StringPiece name, StringPiece value) { + (name.empty() + ? EXPECT_CALL(*mock_, RenderBytes(IsEmpty(), TypedEq<StringPiece>( + value.ToString()))) + : EXPECT_CALL(*mock_, + RenderBytes(Eq(std::string(name)), + TypedEq<StringPiece>(value.ToString())))) + .WillOnce(Return(mock_)) + .RetiresOnSaturation(); + return this; + } + + ObjectWriter* RenderNull(StringPiece name) override { + (name.empty() ? EXPECT_CALL(*mock_, RenderNull(IsEmpty())) + : EXPECT_CALL(*mock_, RenderNull(Eq(std::string(name)))) + .WillOnce(Return(mock_)) + .RetiresOnSaturation()); + return this; + } + + private: + MockObjectWriter* mock_; + + GOOGLE_DISALLOW_IMPLICIT_CONSTRUCTORS(ExpectingObjectWriter); +}; + +} // namespace converter +} // namespace util +} // namespace protobuf +} // namespace google + +#endif // GOOGLE_PROTOBUF_UTIL_INTERNAL_EXPECTING_OBJECTWRITER_H__ diff --git a/toolkit/components/protobuf/src/google/protobuf/util/internal/field_mask_utility.cc b/toolkit/components/protobuf/src/google/protobuf/util/internal/field_mask_utility.cc new file mode 100644 index 0000000000..521bf48b7e --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/util/internal/field_mask_utility.cc @@ -0,0 +1,218 @@ +// 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. + +#include <google/protobuf/util/internal/field_mask_utility.h> + +#include <google/protobuf/stubs/status.h> +#include <google/protobuf/stubs/strutil.h> +#include <google/protobuf/util/internal/utility.h> +#include <google/protobuf/stubs/status_macros.h> + +// Must be included last. +#include <google/protobuf/port_def.inc> + +namespace google { +namespace protobuf { +namespace util { +namespace converter { + +namespace { + +// Appends a FieldMask path segment to a prefix. +std::string AppendPathSegmentToPrefix(StringPiece prefix, + StringPiece segment) { + if (prefix.empty()) { + return std::string(segment); + } + if (segment.empty()) { + return std::string(prefix); + } + // If the segment is a map key, appends it to the prefix without the ".". + if (HasPrefixString(segment, "[\"")) { + return StrCat(prefix, segment); + } + return StrCat(prefix, ".", segment); +} + +} // namespace + +std::string ConvertFieldMaskPath(const StringPiece path, + ConverterCallback converter) { + std::string result; + result.reserve(path.size() << 1); + + bool is_quoted = false; + bool is_escaping = false; + int current_segment_start = 0; + + // Loops until 1 passed the end of the input to make handling the last + // segment easier. + for (size_t i = 0; i <= path.size(); ++i) { + // Outputs quoted string as-is. + if (is_quoted) { + if (i == path.size()) { + break; + } + result.push_back(path[i]); + if (is_escaping) { + is_escaping = false; + } else if (path[i] == '\\') { + is_escaping = true; + } else if (path[i] == '\"') { + current_segment_start = i + 1; + is_quoted = false; + } + continue; + } + if (i == path.size() || path[i] == '.' || path[i] == '(' || + path[i] == ')' || path[i] == '\"') { + result += converter( + path.substr(current_segment_start, i - current_segment_start)); + if (i < path.size()) { + result.push_back(path[i]); + } + current_segment_start = i + 1; + } + if (i < path.size() && path[i] == '\"') { + is_quoted = true; + } + } + return result; +} + +util::Status DecodeCompactFieldMaskPaths(StringPiece paths, + PathSinkCallback path_sink) { + std::stack<std::string> prefix; + int length = paths.length(); + int previous_position = 0; + bool in_map_key = false; + bool is_escaping = false; + // Loops until 1 passed the end of the input to make the handle of the last + // segment easier. + for (int i = 0; i <= length; ++i) { + if (i != length) { + // Skips everything in a map key until we hit the end of it, which is + // marked by an un-escaped '"' immediately followed by a ']'. + if (in_map_key) { + if (is_escaping) { + is_escaping = false; + continue; + } + if (paths[i] == '\\') { + is_escaping = true; + continue; + } + if (paths[i] != '\"') { + continue; + } + // Un-escaped '"' must be followed with a ']'. + if (i >= length - 1 || paths[i + 1] != ']') { + return util::InvalidArgumentError(StrCat( + "Invalid FieldMask '", paths, + "'. Map keys should be represented as [\"some_key\"].")); + } + // The end of the map key ("\"]") has been found. + in_map_key = false; + // Skips ']'. + i++; + // Checks whether the key ends at the end of a path segment. + if (i < length - 1 && paths[i + 1] != '.' && paths[i + 1] != ',' && + paths[i + 1] != ')' && paths[i + 1] != '(') { + return util::InvalidArgumentError(StrCat( + "Invalid FieldMask '", paths, + "'. Map keys should be at the end of a path segment.")); + } + is_escaping = false; + continue; + } + + // We are not in a map key, look for the start of one. + if (paths[i] == '[') { + if (i >= length - 1 || paths[i + 1] != '\"') { + return util::InvalidArgumentError(StrCat( + "Invalid FieldMask '", paths, + "'. Map keys should be represented as [\"some_key\"].")); + } + // "[\"" starts a map key. + in_map_key = true; + i++; // Skips the '\"'. + continue; + } + // If the current character is not a special character (',', '(' or ')'), + // continue to the next. + if (paths[i] != ',' && paths[i] != ')' && paths[i] != '(') { + continue; + } + } + // Gets the current segment - sub-string between previous position (after + // '(', ')', ',', or the beginning of the input) and the current position. + StringPiece segment = + paths.substr(previous_position, i - previous_position); + std::string current_prefix = prefix.empty() ? "" : prefix.top(); + + if (i < length && paths[i] == '(') { + // Builds a prefix and save it into the stack. + prefix.push(AppendPathSegmentToPrefix(current_prefix, segment)); + } else if (!segment.empty()) { + // When the current character is ')', ',' or the current position has + // passed the end of the input, builds and outputs a new paths by + // concatenating the last prefix with the current segment. + RETURN_IF_ERROR( + path_sink(AppendPathSegmentToPrefix(current_prefix, segment))); + } + + // Removes the last prefix after seeing a ')'. + if (i < length && paths[i] == ')') { + if (prefix.empty()) { + return util::InvalidArgumentError( + StrCat("Invalid FieldMask '", paths, + "'. Cannot find matching '(' for all ')'.")); + } + prefix.pop(); + } + previous_position = i + 1; + } + if (in_map_key) { + return util::InvalidArgumentError( + StrCat("Invalid FieldMask '", paths, + "'. Cannot find matching ']' for all '['.")); + } + if (!prefix.empty()) { + return util::InvalidArgumentError( + StrCat("Invalid FieldMask '", paths, + "'. Cannot find matching ')' for all '('.")); + } + return util::Status(); +} + +} // namespace converter +} // namespace util +} // namespace protobuf +} // namespace google diff --git a/toolkit/components/protobuf/src/google/protobuf/util/internal/field_mask_utility.h b/toolkit/components/protobuf/src/google/protobuf/util/internal/field_mask_utility.h new file mode 100644 index 0000000000..1882333787 --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/util/internal/field_mask_utility.h @@ -0,0 +1,74 @@ +// 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. + +// FieldMask related utility methods. + +#ifndef GOOGLE_PROTOBUF_UTIL_INTERNAL_FIELD_MASK_UTILITY_H__ +#define GOOGLE_PROTOBUF_UTIL_INTERNAL_FIELD_MASK_UTILITY_H__ + +#include <functional> +#include <stack> + +#include <google/protobuf/stubs/callback.h> +#include <google/protobuf/stubs/common.h> +#include <google/protobuf/stubs/status.h> +#include <google/protobuf/stubs/strutil.h> +#include <google/protobuf/stubs/status.h> + +namespace google { +namespace protobuf { +namespace util { +namespace converter { + +typedef std::function<std::string(StringPiece)> ConverterCallback; +typedef std::function<util::Status(StringPiece)> PathSinkCallback; + +// Applies a 'converter' to each segment of a FieldMask path and returns the +// result. Quoted strings in the 'path' are copied to the output as-is without +// converting their content. Escaping is supported within quoted strings. +// For example, "ab\"_c" will be returned as "ab\"_c" without any changes. +std::string ConvertFieldMaskPath(const StringPiece path, + ConverterCallback converter); + +// Decodes a compact list of FieldMasks. For example, "a.b,a.c.d,a.c.e" will be +// decoded into a list of field paths - "a.b", "a.c.d", "a.c.e". And the results +// will be sent to 'path_sink', i.e. 'path_sink' will be called once per +// resulting path. +// Note that we also support Apiary style FieldMask form. The above example in +// the Apiary style will look like "a.b,a.c(d,e)". +util::Status DecodeCompactFieldMaskPaths(StringPiece paths, + PathSinkCallback path_sink); + +} // namespace converter +} // namespace util +} // namespace protobuf +} // namespace google + +#endif // GOOGLE_PROTOBUF_UTIL_INTERNAL_FIELD_MASK_UTILITY_H__ diff --git a/toolkit/components/protobuf/src/google/protobuf/util/internal/json_escaping.cc b/toolkit/components/protobuf/src/google/protobuf/util/internal/json_escaping.cc new file mode 100644 index 0000000000..e4fa8cf788 --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/util/internal/json_escaping.cc @@ -0,0 +1,372 @@ +// 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. + +#include <google/protobuf/util/internal/json_escaping.h> + +#include <cstdint> + +#include <google/protobuf/stubs/logging.h> +#include <google/protobuf/stubs/common.h> + +namespace google { +namespace protobuf { +namespace util { +namespace converter { + +namespace { + +// Array of hex characters for conversion to hex. +static const char kHex[] = "0123456789abcdef"; + +// Characters 0x00 to 0x9f are very commonly used, so we provide a special +// table lookup. +// +// For unicode code point ch < 0xa0: +// kCommonEscapes[ch] is the escaped string of ch, if escaping is needed; +// or an empty string, if escaping is not needed. +static const char kCommonEscapes[160][7] = { + // C0 (ASCII and derivatives) control characters + "\\u0000", "\\u0001", "\\u0002", "\\u0003", // 0x00 + "\\u0004", "\\u0005", "\\u0006", "\\u0007", "\\b", "\\t", "\\n", "\\u000b", + "\\f", "\\r", "\\u000e", "\\u000f", "\\u0010", "\\u0011", "\\u0012", + "\\u0013", // 0x10 + "\\u0014", "\\u0015", "\\u0016", "\\u0017", "\\u0018", "\\u0019", "\\u001a", + "\\u001b", "\\u001c", "\\u001d", "\\u001e", "\\u001f", + // Escaping of " and \ are required by www.json.org string definition. + // Escaping of < and > are required for HTML security. + "", "", "\\\"", "", "", "", "", "", // 0x20 + "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", // 0x30 + "", "", "", "", "\\u003c", "", "\\u003e", "", "", "", "", "", "", "", "", + "", // 0x40 + "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", // 0x50 + "", "", "", "", "\\\\", "", "", "", "", "", "", "", "", "", "", "", // 0x60 + "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", // 0x70 + "", "", "", "", "", "", "", "\\u007f", + // C1 (ISO 8859 and Unicode) extended control characters + "\\u0080", "\\u0081", "\\u0082", "\\u0083", // 0x80 + "\\u0084", "\\u0085", "\\u0086", "\\u0087", "\\u0088", "\\u0089", "\\u008a", + "\\u008b", "\\u008c", "\\u008d", "\\u008e", "\\u008f", "\\u0090", "\\u0091", + "\\u0092", "\\u0093", // 0x90 + "\\u0094", "\\u0095", "\\u0096", "\\u0097", "\\u0098", "\\u0099", "\\u009a", + "\\u009b", "\\u009c", "\\u009d", "\\u009e", "\\u009f"}; + +// Determines if the given char value is a unicode surrogate code unit (either +// high-surrogate or low-surrogate). +inline bool IsSurrogate(uint32_t c) { + // Optimized form of: + // return c >= kMinHighSurrogate && c <= kMaxLowSurrogate; + // (Reduced from 3 ALU instructions to 2 ALU instructions) + return (c & 0xfffff800) == JsonEscaping::kMinHighSurrogate; +} + +// Returns true if the given unicode code point cp is a valid +// unicode code point (i.e. in the range 0 <= cp <= kMaxCodePoint). +inline bool IsValidCodePoint(uint32_t cp) { + return cp <= JsonEscaping::kMaxCodePoint; +} + +// Returns the low surrogate for the given unicode code point. The result is +// meaningless if the given code point is not a supplementary character. +inline uint16_t ToLowSurrogate(uint32_t cp) { + return (cp & + (JsonEscaping::kMaxLowSurrogate - JsonEscaping::kMinLowSurrogate)) + + JsonEscaping::kMinLowSurrogate; +} + +// Returns the high surrogate for the given unicode code point. The result is +// meaningless if the given code point is not a supplementary character. +inline uint16_t ToHighSurrogate(uint32_t cp) { + return (cp >> 10) + (JsonEscaping::kMinHighSurrogate - + (JsonEscaping::kMinSupplementaryCodePoint >> 10)); +} + +// Input str is encoded in UTF-8. A unicode code point could be encoded in +// UTF-8 using anywhere from 1 to 4 characters, and it could span multiple +// reads of the ByteSource. +// +// This function reads the next unicode code point from the input (str) at +// the given position (index), taking into account any left-over partial +// code point from the previous iteration (cp), together with the number +// of characters left to read to complete this code point (num_left). +// +// This function assumes that the input (str) is valid at the given position +// (index). In order words, at least one character could be read successfully. +// +// The code point read (partial or complete) is stored in (cp). Upon return, +// (num_left) stores the number of characters that has yet to be read in +// order to complete the current unicode code point. If the read is complete, +// then (num_left) is 0. Also, (num_read) is the number of characters read. +// +// Returns false if we encounter an invalid UTF-8 string. Returns true +// otherwise, including the case when we reach the end of the input (str) +// before a complete unicode code point is read. +bool ReadCodePoint(StringPiece str, int index, uint32_t* cp, + int* num_left, int* num_read) { + if (*num_left == 0) { + // Last read was complete. Start reading a new unicode code point. + *cp = static_cast<uint8_t>(str[index++]); + *num_read = 1; + // The length of the code point is determined from reading the first byte. + // + // If the first byte is between: + // 0..0x7f: that's the value of the code point. + // 0x80..0xbf: <invalid> + // 0xc0..0xdf: 11-bit code point encoded in 2 bytes. + // bit 10-6, bit 5-0 + // 0xe0..0xef: 16-bit code point encoded in 3 bytes. + // bit 15-12, bit 11-6, bit 5-0 + // 0xf0..0xf7: 21-bit code point encoded in 4 bytes. + // bit 20-18, bit 17-12, bit 11-6, bit 5-0 + // 0xf8..0xff: <invalid> + // + // Meaning of each bit: + // <msb> bit 7: 0 - single byte code point: bits 6-0 are values. + // 1 - multibyte code point + // bit 6: 0 - subsequent bytes of multibyte code point: + // bits 5-0 are values. + // 1 - first byte of multibyte code point + // bit 5: 0 - first byte of 2-byte code point: bits 4-0 are values. + // 1 - first byte of code point with >= 3 bytes. + // bit 4: 0 - first byte of 3-byte code point: bits 3-0 are values. + // 1 - first byte of code point with >= 4 bytes. + // bit 3: 0 - first byte of 4-byte code point: bits 2-0 are values. + // 1 - reserved for future expansion. + if (*cp <= 0x7f) { + return true; + } else if (*cp <= 0xbf) { + return false; + } else if (*cp <= 0xdf) { + *cp &= 0x1f; + *num_left = 1; + } else if (*cp <= 0xef) { + *cp &= 0x0f; + *num_left = 2; + } else if (*cp <= 0xf7) { + *cp &= 0x07; + *num_left = 3; + } else { + return false; + } + } else { + // Last read was partial. Initialize num_read to 0 and continue reading + // the last unicode code point. + *num_read = 0; + } + while (*num_left > 0 && index < str.size()) { + uint32_t ch = static_cast<uint8_t>(str[index++]); + --(*num_left); + ++(*num_read); + *cp = (*cp << 6) | (ch & 0x3f); + if (ch < 0x80 || ch > 0xbf) return false; + } + return *num_left > 0 || (!IsSurrogate(*cp) && IsValidCodePoint(*cp)); +} + +// Stores the 16-bit unicode code point as its hexadecimal digits in buffer +// and returns a StringPiece that points to this buffer. The input buffer needs +// to be at least 6 bytes long. +StringPiece ToHex(uint16_t cp, char* buffer) { + buffer[5] = kHex[cp & 0x0f]; + cp >>= 4; + buffer[4] = kHex[cp & 0x0f]; + cp >>= 4; + buffer[3] = kHex[cp & 0x0f]; + cp >>= 4; + buffer[2] = kHex[cp & 0x0f]; + return StringPiece(buffer, 6); +} + +// Stores the 32-bit unicode code point as its hexadecimal digits in buffer +// and returns a StringPiece that points to this buffer. The input buffer needs +// to be at least 12 bytes long. +StringPiece ToSurrogateHex(uint32_t cp, char* buffer) { + uint16_t low = ToLowSurrogate(cp); + uint16_t high = ToHighSurrogate(cp); + + buffer[11] = kHex[low & 0x0f]; + low >>= 4; + buffer[10] = kHex[low & 0x0f]; + low >>= 4; + buffer[9] = kHex[low & 0x0f]; + low >>= 4; + buffer[8] = kHex[low & 0x0f]; + + buffer[5] = kHex[high & 0x0f]; + high >>= 4; + buffer[4] = kHex[high & 0x0f]; + high >>= 4; + buffer[3] = kHex[high & 0x0f]; + high >>= 4; + buffer[2] = kHex[high & 0x0f]; + + return StringPiece(buffer, 12); +} + +// If the given unicode code point needs escaping, then returns the +// escaped form. The returned StringPiece either points to statically +// pre-allocated char[] or to the given buffer. The input buffer needs +// to be at least 12 bytes long. +// +// If the given unicode code point does not need escaping, an empty +// StringPiece is returned. +StringPiece EscapeCodePoint(uint32_t cp, char* buffer) { + if (cp < 0xa0) return kCommonEscapes[cp]; + switch (cp) { + // These are not required by json spec + // but used to prevent security bugs in javascript. + case 0xfeff: // Zero width no-break space + case 0xfff9: // Interlinear annotation anchor + case 0xfffa: // Interlinear annotation separator + case 0xfffb: // Interlinear annotation terminator + + case 0x00ad: // Soft-hyphen + case 0x06dd: // Arabic end of ayah + case 0x070f: // Syriac abbreviation mark + case 0x17b4: // Khmer vowel inherent Aq + case 0x17b5: // Khmer vowel inherent Aa + return ToHex(cp, buffer); + + default: + if ((cp >= 0x0600 && cp <= 0x0603) || // Arabic signs + (cp >= 0x200b && cp <= 0x200f) || // Zero width etc. + (cp >= 0x2028 && cp <= 0x202e) || // Separators etc. + (cp >= 0x2060 && cp <= 0x2064) || // Invisible etc. + (cp >= 0x206a && cp <= 0x206f)) { // Shaping etc. + return ToHex(cp, buffer); + } + + if (cp == 0x000e0001 || // Language tag + (cp >= 0x0001d173 && cp <= 0x0001d17a) || // Music formatting + (cp >= 0x000e0020 && cp <= 0x000e007f)) { // TAG symbols + return ToSurrogateHex(cp, buffer); + } + } + return StringPiece(); +} + +// Tries to escape the given code point first. If the given code point +// does not need to be escaped, but force_output is true, then render +// the given multi-byte code point in UTF8 in the buffer and returns it. +StringPiece EscapeCodePoint(uint32_t cp, char* buffer, + bool force_output) { + StringPiece sp = EscapeCodePoint(cp, buffer); + if (force_output && sp.empty()) { + buffer[5] = (cp & 0x3f) | 0x80; + cp >>= 6; + if (cp <= 0x1f) { + buffer[4] = cp | 0xc0; + sp = StringPiece(buffer + 4, 2); + return sp; + } + buffer[4] = (cp & 0x3f) | 0x80; + cp >>= 6; + if (cp <= 0x0f) { + buffer[3] = cp | 0xe0; + sp = StringPiece(buffer + 3, 3); + return sp; + } + buffer[3] = (cp & 0x3f) | 0x80; + buffer[2] = ((cp >> 6) & 0x07) | 0xf0; + sp = StringPiece(buffer + 2, 4); + } + return sp; +} + +} // namespace + +void JsonEscaping::Escape(strings::ByteSource* input, + strings::ByteSink* output) { + char buffer[12] = "\\udead\\ubee"; + uint32_t cp = 0; // Current unicode code point. + int num_left = 0; // Num of chars to read to complete the code point. + while (input->Available() > 0) { + StringPiece str = input->Peek(); + StringPiece escaped; + int i = 0; + int num_read; + bool ok; + bool cp_was_split = num_left > 0; + // Loop until we encounter either + // i) a code point that needs to be escaped; or + // ii) a split code point is completely read; or + // iii) a character that is not a valid utf8; or + // iv) end of the StringPiece str is reached. + do { + ok = ReadCodePoint(str, i, &cp, &num_left, &num_read); + if (num_left > 0 || !ok) break; // case iii or iv + escaped = EscapeCodePoint(cp, buffer, cp_was_split); + if (!escaped.empty()) break; // case i or ii + i += num_read; + num_read = 0; + } while (i < str.length()); // case iv + // First copy the un-escaped prefix, if any, to the output ByteSink. + if (i > 0) input->CopyTo(output, i); + if (num_read > 0) input->Skip(num_read); + if (!ok) { + // Case iii: Report error. + // TODO(wpoon): Add error reporting. + num_left = 0; + } else if (num_left == 0 && !escaped.empty()) { + // Case i or ii: Append the escaped code point to the output ByteSink. + output->Append(escaped.data(), escaped.size()); + } + } + if (num_left > 0) { + // Treat as case iii: report error. + // TODO(wpoon): Add error reporting. + } +} + +void JsonEscaping::Escape(StringPiece input, strings::ByteSink* output) { + const size_t len = input.length(); + const char* p = input.data(); + + bool can_skip_escaping = true; + for (int i = 0; i < len; i++) { + char c = p[i]; + if (c < 0x20 || c >= 0x7F || c == '"' || c == '<' || c == '>' || + c == '\\') { + can_skip_escaping = false; + break; + } + } + + if (can_skip_escaping) { + output->Append(input.data(), input.length()); + } else { + strings::ArrayByteSource source(input); + Escape(&source, output); + } +} + +} // namespace converter +} // namespace util +} // namespace protobuf +} // namespace google diff --git a/toolkit/components/protobuf/src/google/protobuf/util/internal/json_escaping.h b/toolkit/components/protobuf/src/google/protobuf/util/internal/json_escaping.h new file mode 100644 index 0000000000..7d54f22a38 --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/util/internal/json_escaping.h @@ -0,0 +1,98 @@ +// 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. + +#ifndef GOOGLE_PROTOBUF_UTIL_INTERNAL_JSON_ESCAPING_H__ +#define GOOGLE_PROTOBUF_UTIL_INTERNAL_JSON_ESCAPING_H__ + +#include <cstdint> + +#include <google/protobuf/stubs/common.h> +#include <google/protobuf/stubs/bytestream.h> + +namespace google { +namespace protobuf { +namespace util { +namespace converter { + +class JsonEscaping { + public: + // The minimum value of a unicode high-surrogate code unit in the utf-16 + // encoding. A high-surrogate is also known as a leading-surrogate. + // See http://www.unicode.org/glossary/#high_surrogate_code_unit + static constexpr uint16_t kMinHighSurrogate = 0xd800; + + // The maximum value of a unicide high-surrogate code unit in the utf-16 + // encoding. A high-surrogate is also known as a leading-surrogate. + // See http://www.unicode.org/glossary/#high_surrogate_code_unit + static constexpr uint16_t kMaxHighSurrogate = 0xdbff; + + // The minimum value of a unicode low-surrogate code unit in the utf-16 + // encoding. A low-surrogate is also known as a trailing-surrogate. + // See http://www.unicode.org/glossary/#low_surrogate_code_unit + static constexpr uint16_t kMinLowSurrogate = 0xdc00; + + // The maximum value of a unicode low-surrogate code unit in the utf-16 + // encoding. A low-surrogate is also known as a trailing surrogate. + // See http://www.unicode.org/glossary/#low_surrogate_code_unit + static constexpr uint16_t kMaxLowSurrogate = 0xdfff; + + // The minimum value of a unicode supplementary code point. + // See http://www.unicode.org/glossary/#supplementary_code_point + static constexpr uint32_t kMinSupplementaryCodePoint = 0x010000; + + // The minimum value of a unicode code point. + // See http://www.unicode.org/glossary/#code_point + static constexpr uint32_t kMinCodePoint = 0x000000; + + // The maximum value of a unicode code point. + // See http://www.unicode.org/glossary/#code_point + static constexpr uint32_t kMaxCodePoint = 0x10ffff; + + JsonEscaping() {} + virtual ~JsonEscaping() {} + + // Escape the given ByteSource to the given ByteSink. + static void Escape(strings::ByteSource* input, strings::ByteSink* output); + + // Escape the given ByteSource to the given ByteSink. + // This is optimized for the case where the string is all printable 7-bit + // ASCII and does not contain a few other characters (such as quotes). + static void Escape(StringPiece input, strings::ByteSink* output); + + private: + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(JsonEscaping); +}; + +} // namespace converter +} // namespace util +} // namespace protobuf +} // namespace google + +#endif // GOOGLE_PROTOBUF_UTIL_INTERNAL_JSON_ESCAPING_H__ diff --git a/toolkit/components/protobuf/src/google/protobuf/util/internal/json_objectwriter.cc b/toolkit/components/protobuf/src/google/protobuf/util/internal/json_objectwriter.cc new file mode 100644 index 0000000000..1a86f00533 --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/util/internal/json_objectwriter.cc @@ -0,0 +1,190 @@ +// 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. + +#include <google/protobuf/util/internal/json_objectwriter.h> + +#include <cmath> +#include <cstdint> +#include <limits> + +#include <google/protobuf/stubs/casts.h> +#include <google/protobuf/stubs/logging.h> +#include <google/protobuf/stubs/common.h> +#include <google/protobuf/util/internal/utility.h> +#include <google/protobuf/stubs/strutil.h> +#include <google/protobuf/util/internal/json_escaping.h> + +namespace google { +namespace protobuf { +namespace util { +namespace converter { + + +JsonObjectWriter::~JsonObjectWriter() { + if (element_ && !element_->is_root()) { + GOOGLE_LOG(WARNING) << "JsonObjectWriter was not fully closed."; + } +} + +JsonObjectWriter* JsonObjectWriter::StartObject(StringPiece name) { + WritePrefix(name); + WriteChar('{'); + PushObject(); + return this; +} + +JsonObjectWriter* JsonObjectWriter::EndObject() { + Pop(); + WriteChar('}'); + if (element() && element()->is_root()) NewLine(); + return this; +} + +JsonObjectWriter* JsonObjectWriter::StartList(StringPiece name) { + WritePrefix(name); + WriteChar('['); + PushArray(); + return this; +} + +JsonObjectWriter* JsonObjectWriter::EndList() { + Pop(); + WriteChar(']'); + if (element()->is_root()) NewLine(); + return this; +} + +JsonObjectWriter* JsonObjectWriter::RenderBool(StringPiece name, + bool value) { + return RenderSimple(name, value ? "true" : "false"); +} + +JsonObjectWriter* JsonObjectWriter::RenderInt32(StringPiece name, + int32_t value) { + return RenderSimple(name, StrCat(value)); +} + +JsonObjectWriter* JsonObjectWriter::RenderUint32(StringPiece name, + uint32_t value) { + return RenderSimple(name, StrCat(value)); +} + +JsonObjectWriter* JsonObjectWriter::RenderInt64(StringPiece name, + int64_t value) { + WritePrefix(name); + WriteChar('"'); + WriteRawString(StrCat(value)); + WriteChar('"'); + return this; +} + +JsonObjectWriter* JsonObjectWriter::RenderUint64(StringPiece name, + uint64_t value) { + WritePrefix(name); + WriteChar('"'); + WriteRawString(StrCat(value)); + WriteChar('"'); + return this; +} + +JsonObjectWriter* JsonObjectWriter::RenderDouble(StringPiece name, + double value) { + if (std::isfinite(value)) { + return RenderSimple(name, SimpleDtoa(value)); + } + + // Render quoted with NaN/Infinity-aware DoubleAsString. + return RenderString(name, DoubleAsString(value)); +} + +JsonObjectWriter* JsonObjectWriter::RenderFloat(StringPiece name, + float value) { + if (std::isfinite(value)) { + return RenderSimple(name, SimpleFtoa(value)); + } + + // Render quoted with NaN/Infinity-aware FloatAsString. + return RenderString(name, FloatAsString(value)); +} + +JsonObjectWriter* JsonObjectWriter::RenderString(StringPiece name, + StringPiece value) { + WritePrefix(name); + WriteChar('"'); + JsonEscaping::Escape(value, &sink_); + WriteChar('"'); + return this; +} + +JsonObjectWriter* JsonObjectWriter::RenderBytes(StringPiece name, + StringPiece value) { + WritePrefix(name); + std::string base64; + + if (use_websafe_base64_for_bytes_) + WebSafeBase64EscapeWithPadding(std::string(value), &base64); + else + Base64Escape(value, &base64); + + WriteChar('"'); + // TODO(wpoon): Consider a ByteSink solution that writes the base64 bytes + // directly to the stream, rather than first putting them + // into a string and then writing them to the stream. + stream_->WriteRaw(base64.data(), base64.size()); + WriteChar('"'); + return this; +} + +JsonObjectWriter* JsonObjectWriter::RenderNull(StringPiece name) { + return RenderSimple(name, "null"); +} + +JsonObjectWriter* JsonObjectWriter::RenderNullAsEmpty(StringPiece name) { + return RenderSimple(name, ""); +} + +void JsonObjectWriter::WritePrefix(StringPiece name) { + bool not_first = !element()->is_first(); + if (not_first) WriteChar(','); + if (not_first || !element()->is_root()) NewLine(); + if (!name.empty() || element()->is_json_object()) { + WriteChar('"'); + if (!name.empty()) { + JsonEscaping::Escape(name, &sink_); + } + WriteRawString("\":"); + if (!indent_string_.empty()) WriteChar(' '); + } +} + +} // namespace converter +} // namespace util +} // namespace protobuf +} // namespace google diff --git a/toolkit/components/protobuf/src/google/protobuf/util/internal/json_objectwriter.h b/toolkit/components/protobuf/src/google/protobuf/util/internal/json_objectwriter.h new file mode 100644 index 0000000000..cb7dff6e9f --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/util/internal/json_objectwriter.h @@ -0,0 +1,278 @@ +// 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. + +#ifndef GOOGLE_PROTOBUF_UTIL_INTERNAL_JSON_OBJECTWRITER_H__ +#define GOOGLE_PROTOBUF_UTIL_INTERNAL_JSON_OBJECTWRITER_H__ + +#include <cstdint> +#include <memory> +#include <string> + +#include <google/protobuf/io/coded_stream.h> +#include <google/protobuf/stubs/bytestream.h> +#include <google/protobuf/util/internal/structured_objectwriter.h> + +// clang-format off +#include <google/protobuf/port_def.inc> +// clang-format on + +namespace google { +namespace protobuf { +namespace util { +namespace converter { + + +// An ObjectWriter implementation that outputs JSON. This ObjectWriter +// supports writing a compact form or a pretty printed form. +// +// Sample usage: +// string output; +// StringOutputStream* str_stream = new StringOutputStream(&output); +// CodedOutputStream* out_stream = new CodedOutputStream(str_stream); +// JsonObjectWriter* ow = new JsonObjectWriter(" ", out_stream); +// ow->StartObject("") +// ->RenderString("name", "value") +// ->RenderString("emptystring", string()) +// ->StartObject("nested") +// ->RenderInt64("light", 299792458); +// ->RenderDouble("pi", 3.141592653589793); +// ->EndObject() +// ->StartList("empty") +// ->EndList() +// ->EndObject(); +// +// And then the output string would become: +// { +// "name": "value", +// "emptystring": "", +// "nested": { +// "light": "299792458", +// "pi": 3.141592653589793 +// }, +// "empty": [] +// } +// +// JsonObjectWriter does not validate if calls actually result in valid JSON. +// For example, passing an empty name when one would be required won't result +// in an error, just an invalid output. +// +// Note that all int64 and uint64 are rendered as strings instead of numbers. +// This is because JavaScript parses numbers as 64-bit float thus int64 and +// uint64 would lose precision if rendered as numbers. +// +// JsonObjectWriter is thread-unsafe. +class PROTOBUF_EXPORT JsonObjectWriter : public StructuredObjectWriter { + public: + JsonObjectWriter(StringPiece indent_string, io::CodedOutputStream* out) + : element_(new Element(/*parent=*/nullptr, /*is_json_object=*/false)), + stream_(out), + sink_(out), + indent_string_(indent_string), + indent_char_('\0'), + indent_count_(0), + use_websafe_base64_for_bytes_(false) { + // See if we have a trivial sequence of indent characters. + if (!indent_string.empty()) { + indent_char_ = indent_string[0]; + indent_count_ = indent_string.length(); + for (int i = 1; i < indent_string.length(); i++) { + if (indent_char_ != indent_string_[i]) { + indent_char_ = '\0'; + indent_count_ = 0; + break; + } + } + } + } + ~JsonObjectWriter() override; + + // ObjectWriter methods. + JsonObjectWriter* StartObject(StringPiece name) override; + JsonObjectWriter* EndObject() override; + JsonObjectWriter* StartList(StringPiece name) override; + JsonObjectWriter* EndList() override; + JsonObjectWriter* RenderBool(StringPiece name, bool value) override; + JsonObjectWriter* RenderInt32(StringPiece name, int32_t value) override; + JsonObjectWriter* RenderUint32(StringPiece name, + uint32_t value) override; + JsonObjectWriter* RenderInt64(StringPiece name, int64_t value) override; + JsonObjectWriter* RenderUint64(StringPiece name, + uint64_t value) override; + JsonObjectWriter* RenderDouble(StringPiece name, double value) override; + JsonObjectWriter* RenderFloat(StringPiece name, float value) override; + JsonObjectWriter* RenderString(StringPiece name, + StringPiece value) override; + JsonObjectWriter* RenderBytes(StringPiece name, StringPiece value) override; + JsonObjectWriter* RenderNull(StringPiece name) override; + virtual JsonObjectWriter* RenderNullAsEmpty(StringPiece name); + + void set_use_websafe_base64_for_bytes(bool value) { + use_websafe_base64_for_bytes_ = value; + } + + protected: + class PROTOBUF_EXPORT Element : public BaseElement { + public: + Element(Element* parent, bool is_json_object) + : BaseElement(parent), + is_first_(true), + is_json_object_(is_json_object) {} + + // Called before each field of the Element is to be processed. + // Returns true if this is the first call (processing the first field). + bool is_first() { + if (is_first_) { + is_first_ = false; + return true; + } + return false; + } + + // Whether we are currently rendering inside a JSON object (i.e., between + // StartObject() and EndObject()). + bool is_json_object() const { return is_json_object_; } + + private: + bool is_first_; + bool is_json_object_; + + GOOGLE_DISALLOW_IMPLICIT_CONSTRUCTORS(Element); + }; + + Element* element() override { return element_.get(); } + + private: + class PROTOBUF_EXPORT ByteSinkWrapper : public strings::ByteSink { + public: + explicit ByteSinkWrapper(io::CodedOutputStream* stream) : stream_(stream) {} + ~ByteSinkWrapper() override {} + + // ByteSink methods. + void Append(const char* bytes, size_t n) override { + stream_->WriteRaw(bytes, n); + } + + private: + io::CodedOutputStream* stream_; + + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ByteSinkWrapper); + }; + + // Renders a simple value as a string. By default all non-string Render + // methods convert their argument to a string and call this method. This + // method can then be used to render the simple value without escaping it. + JsonObjectWriter* RenderSimple(StringPiece name, + StringPiece value) { + WritePrefix(name); + WriteRawString(value); + return this; + } + + // Pushes a new JSON array element to the stack. + void PushArray() { + element_.reset(new Element(element_.release(), /*is_json_object=*/false)); + } + + // Pushes a new JSON object element to the stack. + void PushObject() { + element_.reset(new Element(element_.release(), /*is_json_object=*/true)); + } + + // Pops an element off of the stack and deletes the popped element. + void Pop() { + bool needs_newline = !element_->is_first(); + element_.reset(element_->pop<Element>()); + if (needs_newline) NewLine(); + } + + // If pretty printing is enabled, this will write a newline to the output, + // followed by optional indentation. Otherwise this method is a noop. + void NewLine() { + if (!indent_string_.empty()) { + size_t len = sizeof('\n') + (indent_string_.size() * element()->level()); + + // Take the slow-path if we don't have sufficient characters remaining in + // our buffer or we have a non-trivial indent string which would prevent + // us from using memset. + uint8_t* out = nullptr; + if (indent_count_ > 0) { + out = stream_->GetDirectBufferForNBytesAndAdvance(len); + } + + if (out != nullptr) { + out[0] = '\n'; + memset(&out[1], indent_char_, len - 1); + } else { + // Slow path, no contiguous output buffer available. + WriteChar('\n'); + for (int i = 0; i < element()->level(); i++) { + stream_->WriteRaw(indent_string_.c_str(), indent_string_.length()); + } + } + } + } + + // Writes a prefix. This will write out any pretty printing and + // commas that are required, followed by the name and a ':' if + // the name is not null. + void WritePrefix(StringPiece name); + + // Writes an individual character to the output. + void WriteChar(const char c) { stream_->WriteRaw(&c, sizeof(c)); } + + // Writes a string to the output. + void WriteRawString(StringPiece s) { + stream_->WriteRaw(s.data(), s.length()); + } + + std::unique_ptr<Element> element_; + io::CodedOutputStream* stream_; + ByteSinkWrapper sink_; + const std::string indent_string_; + + // For the common case of indent being a single character repeated. + char indent_char_; + int indent_count_; + + // Whether to use regular or websafe base64 encoding for byte fields. Defaults + // to regular base64 encoding. + bool use_websafe_base64_for_bytes_; + + GOOGLE_DISALLOW_IMPLICIT_CONSTRUCTORS(JsonObjectWriter); +}; + +} // namespace converter +} // namespace util +} // namespace protobuf +} // namespace google + +#include <google/protobuf/port_undef.inc> + +#endif // GOOGLE_PROTOBUF_UTIL_INTERNAL_JSON_OBJECTWRITER_H__ diff --git a/toolkit/components/protobuf/src/google/protobuf/util/internal/json_stream_parser.cc b/toolkit/components/protobuf/src/google/protobuf/util/internal/json_stream_parser.cc new file mode 100644 index 0000000000..5c34dbccaf --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/util/internal/json_stream_parser.cc @@ -0,0 +1,995 @@ +// 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. + +#include <google/protobuf/util/internal/json_stream_parser.h> + +#include <algorithm> +#include <cctype> +#include <cmath> +#include <memory> +#include <stack> +#include <string> + +#include <google/protobuf/stubs/common.h> +#include <google/protobuf/stubs/logging.h> +#include <google/protobuf/stubs/strutil.h> +#include <google/protobuf/stubs/status.h> +#include <google/protobuf/util/internal/object_writer.h> +#include <google/protobuf/util/internal/json_escaping.h> + + +namespace google { +namespace protobuf { +namespace util { + +namespace converter { + +// Number of digits in an escaped UTF-16 code unit ('\\' 'u' X X X X) +static const int kUnicodeEscapedLength = 6; + +static const int kDefaultMaxRecursionDepth = 100; + +// These cannot be constexpr for portability with VS2015. +static const StringPiece kKeywordTrue = "true"; +static const StringPiece kKeywordFalse = "false"; +static const StringPiece kKeywordNull = "null"; + +inline bool IsLetter(char c) { + return ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z') || (c == '_') || + (c == '$'); +} + +inline bool IsAlphanumeric(char c) { + return IsLetter(c) || ('0' <= c && c <= '9'); +} + +// Indicates a character may not be part of an unquoted key. +inline bool IsKeySeparator(char c) { + return (ascii_isspace(c) || c == '"' || c == '\'' || c == '{' || + c == '}' || c == '[' || c == ']' || c == ':' || c == ','); +} + +inline void ReplaceInvalidCodePoints(StringPiece str, + const std::string& replacement, + std::string* dst) { + while (!str.empty()) { + int n_valid_bytes = internal::UTF8SpnStructurallyValid(str); + StringPiece valid_part = str.substr(0, n_valid_bytes); + StrAppend(dst, valid_part); + + if (n_valid_bytes == str.size()) { + break; + } + + // Append replacement value. + StrAppend(dst, replacement); + + // Move past valid bytes + one invalid byte. + str.remove_prefix(n_valid_bytes + 1); + } +} + +static bool ConsumeKey(StringPiece* input, StringPiece* key) { + if (input->empty() || !IsLetter((*input)[0])) return false; + int len = 1; + for (; len < input->size(); ++len) { + if (!IsAlphanumeric((*input)[len])) { + break; + } + } + *key = StringPiece(input->data(), len); + *input = StringPiece(input->data() + len, input->size() - len); + return true; +} + +// Same as 'ConsumeKey', but allows a widened set of key characters. +static bool ConsumeKeyPermissive(StringPiece* input, + StringPiece* key) { + if (input->empty() || !IsLetter((*input)[0])) return false; + int len = 1; + for (; len < input->size(); ++len) { + if (IsKeySeparator((*input)[len])) { + break; + } + } + *key = StringPiece(input->data(), len); + *input = StringPiece(input->data() + len, input->size() - len); + return true; +} + +static bool MatchKey(StringPiece input) { + return !input.empty() && IsLetter(input[0]); +} + +JsonStreamParser::JsonStreamParser(ObjectWriter* ow) + : ow_(ow), + stack_(), + leftover_(), + json_(), + p_(), + key_(), + key_storage_(), + finishing_(false), + seen_non_whitespace_(false), + allow_no_root_element_(false), + parsed_(), + parsed_storage_(), + string_open_(0), + chunk_storage_(), + coerce_to_utf8_(false), + utf8_replacement_character_(" "), + allow_empty_null_(false), + allow_permissive_key_naming_(false), + loose_float_number_conversion_(false), + recursion_depth_(0), + max_recursion_depth_(kDefaultMaxRecursionDepth) { + // Initialize the stack with a single value to be parsed. + stack_.push(VALUE); +} + +JsonStreamParser::~JsonStreamParser() {} + + +util::Status JsonStreamParser::Parse(StringPiece json) { + StringPiece chunk = json; + // If we have leftovers from a previous chunk, append the new chunk to it + // and create a new StringPiece pointing at the string's data. This could + // be large but we rely on the chunks to be small, assuming they are + // fragments of a Cord. + if (!leftover_.empty()) { + // Don't point chunk to leftover_ because leftover_ will be updated in + // ParseChunk(chunk). + chunk_storage_.swap(leftover_); + StrAppend(&chunk_storage_, json); + chunk = StringPiece(chunk_storage_); + } + + // Find the structurally valid UTF8 prefix and parse only that. + int n = internal::UTF8SpnStructurallyValid(chunk); + if (n > 0) { + util::Status status = ParseChunk(chunk.substr(0, n)); + + // Any leftover characters are stashed in leftover_ for later parsing when + // there is more data available. + StrAppend(&leftover_, chunk.substr(n)); + return status; + } else { + leftover_.assign(chunk.data(), chunk.size()); + return util::Status(); + } +} + +util::Status JsonStreamParser::FinishParse() { + // If we do not expect anything and there is nothing left to parse we're all + // done. + if (stack_.empty() && leftover_.empty()) { + return util::Status(); + } + + // Lifetime needs to last until RunParser returns, so keep this variable + // outside of the coerce_to_utf8 block. + std::unique_ptr<std::string> scratch; + + bool is_valid_utf8 = internal::IsStructurallyValidUTF8(leftover_); + if (coerce_to_utf8_ && !is_valid_utf8) { + scratch.reset(new std::string); + scratch->reserve(leftover_.size() * utf8_replacement_character_.size()); + ReplaceInvalidCodePoints(leftover_, utf8_replacement_character_, + scratch.get()); + p_ = json_ = *scratch; + } else { + p_ = json_ = leftover_; + if (!is_valid_utf8) { + return ReportFailure("Encountered non UTF-8 code points.", + ParseErrorType::NON_UTF_8); + } + } + + // Parse the remainder in finishing mode, which reports errors for things like + // unterminated strings or unknown tokens that would normally be retried. + finishing_ = true; + util::Status result = RunParser(); + if (result.ok()) { + SkipWhitespace(); + if (!p_.empty()) { + result = + ReportFailure("Parsing terminated before end of input.", + ParseErrorType::PARSING_TERMINATED_BEFORE_END_OF_INPUT); + } + } + return result; +} + +util::Status JsonStreamParser::ParseChunk(StringPiece chunk) { + // Do not do any work if the chunk is empty. + if (chunk.empty()) return util::Status(); + + p_ = json_ = chunk; + + finishing_ = false; + util::Status result = RunParser(); + if (!result.ok()) return result; + + SkipWhitespace(); + if (p_.empty()) { + // If we parsed everything we had, clear the leftover. + leftover_.clear(); + } else { + // If we do not expect anything i.e. stack is empty, and we have non-empty + // string left to parse, we report an error. + if (stack_.empty()) { + return ReportFailure( + "Parsing terminated before end of input.", + ParseErrorType::PARSING_TERMINATED_BEFORE_END_OF_INPUT); + } + // If we expect future data i.e. stack is non-empty, and we have some + // unparsed data left, we save it for later parse. + leftover_ = std::string(p_); + } + return util::Status(); +} + +bool JsonStreamParser::IsInputAllWhiteSpaces(TokenType type) { + // Conclude the whole input is full of white spaces by: + // - it is at the finishing stage + // - we have run out of the input data + // - haven't seen non-whitespace char so far + if (finishing_ && p_.empty() && type == UNKNOWN && !seen_non_whitespace_) { + return true; + } + return false; +} + +util::Status JsonStreamParser::RunParser() { + while (!stack_.empty()) { + ParseType type = stack_.top(); + TokenType t = (string_open_ == 0) ? GetNextTokenType() : BEGIN_STRING; + stack_.pop(); + util::Status result; + switch (type) { + case VALUE: + if (allow_no_root_element_ && IsInputAllWhiteSpaces(t)) { + return util::Status(); + } + result = ParseValue(t); + break; + + case OBJ_MID: + result = ParseObjectMid(t); + break; + + case ENTRY: + result = ParseEntry(t); + break; + + case ENTRY_MID: + result = ParseEntryMid(t); + break; + + case ARRAY_VALUE: + result = ParseArrayValue(t); + break; + + case ARRAY_MID: + result = ParseArrayMid(t); + break; + + default: + result = + util::InternalError(StrCat("Unknown parse type: ", type)); + break; + } + if (!result.ok()) { + // If we were cancelled, save our state and try again later. + if (!finishing_ && util::IsCancelled(result)) { + stack_.push(type); + // If we have a key we still need to render, make sure to save off the + // contents in our own storage. + if (!key_.empty() && key_storage_.empty()) { + StrAppend(&key_storage_, key_); + key_ = StringPiece(key_storage_); + } + result = util::Status(); + } + return result; + } + } + return util::Status(); +} + +util::Status JsonStreamParser::ParseValue(TokenType type) { + switch (type) { + case BEGIN_OBJECT: + return HandleBeginObject(); + case BEGIN_ARRAY: + return HandleBeginArray(); + case BEGIN_STRING: + return ParseString(); + case BEGIN_NUMBER: + return ParseNumber(); + case BEGIN_TRUE: + return ParseTrue(); + case BEGIN_FALSE: + return ParseFalse(); + case BEGIN_NULL: + return ParseNull(); + case UNKNOWN: + return ReportUnknown("Expected a value.", ParseErrorType::EXPECTED_VALUE); + default: { + // Special case for having been cut off while parsing, wait for more data. + // This handles things like 'fals' being at the end of the string, we + // don't know if the next char would be e, completing it, or something + // else, making it invalid. + if (!finishing_ && p_.length() < kKeywordFalse.length()) { + return util::CancelledError(""); + } + + if (allow_empty_null_ && IsEmptyNullAllowed(type)) { + return ParseEmptyNull(); + } + return ReportFailure("Unexpected token.", + ParseErrorType::UNEXPECTED_TOKEN); + } + } +} + +util::Status JsonStreamParser::ParseString() { + util::Status result = ParseStringHelper(); + if (result.ok()) { + ow_->RenderString(key_, parsed_); + key_ = StringPiece(); + parsed_ = StringPiece(); + parsed_storage_.clear(); + } + return result; +} + +util::Status JsonStreamParser::ParseStringHelper() { + // If we haven't seen the start quote, grab it and remember it for later. + if (string_open_ == 0) { + string_open_ = *p_.data(); + GOOGLE_DCHECK(string_open_ == '\"' || string_open_ == '\''); + Advance(); + } + // Track where we last copied data from so we can minimize copying. + const char* last = p_.data(); + while (!p_.empty()) { + const char* data = p_.data(); + if (*data == '\\') { + // We're about to handle an escape, copy all bytes from last to data. + if (last < data) { + parsed_storage_.append(last, data - last); + } + // If we ran out of string after the \, cancel or report an error + // depending on if we expect more data later. + if (p_.length() == 1) { + if (!finishing_) { + return util::CancelledError(""); + } + return ReportFailure("Closing quote expected in string.", + ParseErrorType::EXPECTED_CLOSING_QUOTE); + } + // Parse a unicode escape if we found \u in the string. + if (data[1] == 'u') { + util::Status result = ParseUnicodeEscape(); + if (!result.ok()) { + return result; + } + // Move last pointer past the unicode escape and continue. + last = p_.data(); + continue; + } + // Handle the standard set of backslash-escaped characters. + switch (data[1]) { + case 'b': + parsed_storage_.push_back('\b'); + break; + case 'f': + parsed_storage_.push_back('\f'); + break; + case 'n': + parsed_storage_.push_back('\n'); + break; + case 'r': + parsed_storage_.push_back('\r'); + break; + case 't': + parsed_storage_.push_back('\t'); + break; + case 'v': + parsed_storage_.push_back('\v'); + break; + default: + parsed_storage_.push_back(data[1]); + } + // We handled two characters, so advance past them and continue. + p_.remove_prefix(2); + last = p_.data(); + continue; + } + // If we found the closing quote note it, advance past it, and return. + if (*data == string_open_) { + // If we didn't copy anything, reuse the input buffer. + if (parsed_storage_.empty()) { + parsed_ = StringPiece(last, data - last); + } else { + if (last < data) { + parsed_storage_.append(last, data - last); + } + parsed_ = StringPiece(parsed_storage_); + } + // Clear the quote char so next time we try to parse a string we'll + // start fresh. + string_open_ = 0; + Advance(); + return util::Status(); + } + // Normal character, just advance past it. + Advance(); + } + // If we ran out of characters, copy over what we have so far. + if (last < p_.data()) { + parsed_storage_.append(last, p_.data() - last); + } + // If we didn't find the closing quote but we expect more data, cancel for now + if (!finishing_) { + return util::CancelledError(""); + } + // End of string reached without a closing quote, report an error. + string_open_ = 0; + return ReportFailure("Closing quote expected in string.", + ParseErrorType::EXPECTED_CLOSING_QUOTE); +} + +// Converts a unicode escaped character to a decimal value stored in a char32 +// for use in UTF8 encoding utility. We assume that str begins with \uhhhh and +// convert that from the hex number to a decimal value. +// +// There are some security exploits with UTF-8 that we should be careful of: +// - http://www.unicode.org/reports/tr36/#UTF-8_Exploit +// - http://sites/intl-eng/design-guide/core-application +util::Status JsonStreamParser::ParseUnicodeEscape() { + if (p_.length() < kUnicodeEscapedLength) { + if (!finishing_) { + return util::CancelledError(""); + } + return ReportFailure("Illegal hex string.", + ParseErrorType::ILLEGAL_HEX_STRING); + } + GOOGLE_DCHECK_EQ('\\', p_.data()[0]); + GOOGLE_DCHECK_EQ('u', p_.data()[1]); + uint32_t code = 0; + for (int i = 2; i < kUnicodeEscapedLength; ++i) { + if (!isxdigit(p_.data()[i])) { + return ReportFailure("Invalid escape sequence.", + ParseErrorType::INVALID_ESCAPE_SEQUENCE); + } + code = (code << 4) + hex_digit_to_int(p_.data()[i]); + } + if (code >= JsonEscaping::kMinHighSurrogate && + code <= JsonEscaping::kMaxHighSurrogate) { + if (p_.length() < 2 * kUnicodeEscapedLength) { + if (!finishing_) { + return util::CancelledError(""); + } + if (!coerce_to_utf8_) { + return ReportFailure("Missing low surrogate.", + ParseErrorType::MISSING_LOW_SURROGATE); + } + } else if (p_.data()[kUnicodeEscapedLength] == '\\' && + p_.data()[kUnicodeEscapedLength + 1] == 'u') { + uint32_t low_code = 0; + for (int i = kUnicodeEscapedLength + 2; i < 2 * kUnicodeEscapedLength; + ++i) { + if (!isxdigit(p_.data()[i])) { + return ReportFailure("Invalid escape sequence.", + ParseErrorType::INVALID_ESCAPE_SEQUENCE); + } + low_code = (low_code << 4) + hex_digit_to_int(p_.data()[i]); + } + if (low_code >= JsonEscaping::kMinLowSurrogate && + low_code <= JsonEscaping::kMaxLowSurrogate) { + // Convert UTF-16 surrogate pair to 21-bit Unicode codepoint. + code = (((code & 0x3FF) << 10) | (low_code & 0x3FF)) + + JsonEscaping::kMinSupplementaryCodePoint; + // Advance past the first code unit escape. + p_.remove_prefix(kUnicodeEscapedLength); + } else if (!coerce_to_utf8_) { + return ReportFailure("Invalid low surrogate.", + ParseErrorType::INVALID_LOW_SURROGATE); + } + } else if (!coerce_to_utf8_) { + return ReportFailure("Missing low surrogate.", + ParseErrorType::MISSING_LOW_SURROGATE); + } + } + if (!coerce_to_utf8_ && !IsValidCodePoint(code)) { + return ReportFailure("Invalid unicode code point.", + ParseErrorType::INVALID_UNICODE); + } + char buf[UTFmax]; + int len = EncodeAsUTF8Char(code, buf); + // Advance past the [final] code unit escape. + p_.remove_prefix(kUnicodeEscapedLength); + parsed_storage_.append(buf, len); + return util::Status(); +} + +util::Status JsonStreamParser::ParseNumber() { + NumberResult number; + util::Status result = ParseNumberHelper(&number); + if (result.ok()) { + switch (number.type) { + case NumberResult::DOUBLE: + ow_->RenderDouble(key_, number.double_val); + key_ = StringPiece(); + break; + + case NumberResult::INT: + ow_->RenderInt64(key_, number.int_val); + key_ = StringPiece(); + break; + + case NumberResult::UINT: + ow_->RenderUint64(key_, number.uint_val); + key_ = StringPiece(); + break; + + default: + return ReportFailure("Unable to parse number.", + ParseErrorType::UNABLE_TO_PARSE_NUMBER); + } + } + return result; +} + +util::Status JsonStreamParser::ParseDoubleHelper(const std::string& number, + NumberResult* result) { + if (!safe_strtod(number, &result->double_val)) { + return ReportFailure("Unable to parse number.", + ParseErrorType::UNABLE_TO_PARSE_NUMBER); + } + if (!loose_float_number_conversion_ && !std::isfinite(result->double_val)) { + return ReportFailure("Number exceeds the range of double.", + ParseErrorType::NUMBER_EXCEEDS_RANGE_DOUBLE); + } + result->type = NumberResult::DOUBLE; + return util::Status(); +} + +util::Status JsonStreamParser::ParseNumberHelper(NumberResult* result) { + const char* data = p_.data(); + int length = p_.length(); + + // Look for the first non-numeric character, or the end of the string. + int index = 0; + bool floating = false; + bool negative = data[index] == '-'; + // Find the first character that cannot be part of the number. Along the way + // detect if the number needs to be parsed as a double. + // Note that this restricts numbers to the JSON specification, so for example + // we do not support hex or octal notations. + for (; index < length; ++index) { + char c = data[index]; + if (isdigit(c)) continue; + if (c == '.' || c == 'e' || c == 'E') { + floating = true; + continue; + } + if (c == '+' || c == '-' || c == 'x') continue; + // Not a valid number character, break out. + break; + } + + // If the entire input is a valid number, and we may have more content in the + // future, we abort for now and resume when we know more. + if (index == length && !finishing_) { + return util::CancelledError(""); + } + + // Create a string containing just the number, so we can use safe_strtoX + std::string number = std::string(p_.substr(0, index)); + + // Floating point number, parse as a double. + if (floating) { + util::Status status = ParseDoubleHelper(number, result); + if (status.ok()) { + p_.remove_prefix(index); + } + return status; + } + + // Positive non-floating point number, parse as a uint64_t. + if (!negative) { + // Octal/Hex numbers are not valid JSON values. + if (number.length() >= 2 && number[0] == '0') { + return ReportFailure( + "Octal/hex numbers are not valid JSON values.", + ParseErrorType::OCTAL_OR_HEX_ARE_NOT_VALID_JSON_VALUES); + } + if (safe_strtou64(number, &result->uint_val)) { + result->type = NumberResult::UINT; + p_.remove_prefix(index); + return util::Status(); + } else { + // If the value is too large, parse it as double. + util::Status status = ParseDoubleHelper(number, result); + if (status.ok()) { + p_.remove_prefix(index); + } + return status; + } + } + + // Octal/Hex numbers are not valid JSON values. + if (number.length() >= 3 && number[1] == '0') { + return ReportFailure( + "Octal/hex numbers are not valid JSON values.", + ParseErrorType::OCTAL_OR_HEX_ARE_NOT_VALID_JSON_VALUES); + } + // Negative non-floating point number, parse as an int64_t. + if (safe_strto64(number, &result->int_val)) { + result->type = NumberResult::INT; + p_.remove_prefix(index); + return util::Status(); + } else { + // If the value is too large, parse it as double. + util::Status status = ParseDoubleHelper(number, result); + if (status.ok()) { + p_.remove_prefix(index); + } + return status; + } +} + +util::Status JsonStreamParser::HandleBeginObject() { + GOOGLE_DCHECK_EQ('{', *p_.data()); + Advance(); + ow_->StartObject(key_); + auto status = IncrementRecursionDepth(key_); + if (!status.ok()) { + return status; + } + key_ = StringPiece(); + stack_.push(ENTRY); + return util::Status(); +} + +util::Status JsonStreamParser::ParseObjectMid(TokenType type) { + if (type == UNKNOWN) { + return ReportUnknown("Expected , or } after key:value pair.", + ParseErrorType::EXPECTED_COMMA_OR_BRACES); + } + + // Object is complete, advance past the comma and render the EndObject. + if (type == END_OBJECT) { + Advance(); + ow_->EndObject(); + --recursion_depth_; + return util::Status(); + } + // Found a comma, advance past it and get ready for an entry. + if (type == VALUE_SEPARATOR) { + Advance(); + stack_.push(ENTRY); + return util::Status(); + } + // Illegal token after key:value pair. + return ReportFailure("Expected , or } after key:value pair.", + ParseErrorType::EXPECTED_COMMA_OR_BRACES); +} + +util::Status JsonStreamParser::ParseEntry(TokenType type) { + if (type == UNKNOWN) { + return ReportUnknown("Expected an object key or }.", + ParseErrorType::EXPECTED_OBJECT_KEY_OR_BRACES); + } + + // Close the object and return. This allows for trailing commas. + if (type == END_OBJECT) { + ow_->EndObject(); + Advance(); + --recursion_depth_; + return util::Status(); + } + + util::Status result; + if (type == BEGIN_STRING) { + // Key is a string (standard JSON), parse it and store the string. + result = ParseStringHelper(); + if (result.ok()) { + key_storage_.clear(); + if (!parsed_storage_.empty()) { + parsed_storage_.swap(key_storage_); + key_ = StringPiece(key_storage_); + } else { + key_ = parsed_; + } + parsed_ = StringPiece(); + } + } else if (type == BEGIN_KEY) { + // Key is a bare key (back compat), create a StringPiece pointing to it. + result = ParseKey(); + } else if (type == BEGIN_NULL || type == BEGIN_TRUE || type == BEGIN_FALSE) { + // Key may be a bare key that begins with a reserved word. + result = ParseKey(); + if (result.ok() && (key_ == kKeywordNull || key_ == kKeywordTrue || + key_ == kKeywordFalse)) { + result = ReportFailure("Expected an object key or }.", + ParseErrorType::EXPECTED_OBJECT_KEY_OR_BRACES); + } + } else { + // Unknown key type, report an error. + result = ReportFailure("Expected an object key or }.", + ParseErrorType::EXPECTED_OBJECT_KEY_OR_BRACES); + } + // On success we next expect an entry mid ':' then an object mid ',' or '}' + if (result.ok()) { + stack_.push(OBJ_MID); + stack_.push(ENTRY_MID); + } + return result; +} + +util::Status JsonStreamParser::ParseEntryMid(TokenType type) { + if (type == UNKNOWN) { + return ReportUnknown("Expected : between key:value pair.", + ParseErrorType::EXPECTED_COLON); + } + if (type == ENTRY_SEPARATOR) { + Advance(); + stack_.push(VALUE); + return util::Status(); + } + return ReportFailure("Expected : between key:value pair.", + ParseErrorType::EXPECTED_COLON); +} + +util::Status JsonStreamParser::HandleBeginArray() { + GOOGLE_DCHECK_EQ('[', *p_.data()); + Advance(); + ow_->StartList(key_); + key_ = StringPiece(); + stack_.push(ARRAY_VALUE); + return util::Status(); +} + +util::Status JsonStreamParser::ParseArrayValue(TokenType type) { + if (type == UNKNOWN) { + return ReportUnknown("Expected a value or ] within an array.", + ParseErrorType::EXPECTED_VALUE_OR_BRACKET); + } + + if (type == END_ARRAY) { + ow_->EndList(); + Advance(); + return util::Status(); + } + + // The ParseValue call may push something onto the stack so we need to make + // sure an ARRAY_MID is after it, so we push it on now. Also, the parsing of + // empty-null array value is relying on this ARRAY_MID token. + stack_.push(ARRAY_MID); + util::Status result = ParseValue(type); + if (util::IsCancelled(result)) { + // If we were cancelled, pop back off the ARRAY_MID so we don't try to + // push it on again when we try over. + stack_.pop(); + } + return result; +} + +util::Status JsonStreamParser::ParseArrayMid(TokenType type) { + if (type == UNKNOWN) { + return ReportUnknown("Expected , or ] after array value.", + ParseErrorType::EXPECTED_COMMA_OR_BRACKET); + } + + if (type == END_ARRAY) { + ow_->EndList(); + Advance(); + return util::Status(); + } + + // Found a comma, advance past it and expect an array value next. + if (type == VALUE_SEPARATOR) { + Advance(); + stack_.push(ARRAY_VALUE); + return util::Status(); + } + // Illegal token after array value. + return ReportFailure("Expected , or ] after array value.", + ParseErrorType::EXPECTED_COMMA_OR_BRACKET); +} + +util::Status JsonStreamParser::ParseTrue() { + ow_->RenderBool(key_, true); + key_ = StringPiece(); + p_.remove_prefix(kKeywordTrue.length()); + return util::Status(); +} + +util::Status JsonStreamParser::ParseFalse() { + ow_->RenderBool(key_, false); + key_ = StringPiece(); + p_.remove_prefix(kKeywordFalse.length()); + return util::Status(); +} + +util::Status JsonStreamParser::ParseNull() { + ow_->RenderNull(key_); + key_ = StringPiece(); + p_.remove_prefix(kKeywordNull.length()); + return util::Status(); +} + +util::Status JsonStreamParser::ParseEmptyNull() { + ow_->RenderNull(key_); + key_ = StringPiece(); + return util::Status(); +} + +bool JsonStreamParser::IsEmptyNullAllowed(TokenType type) { + if (stack_.empty()) return false; + return (stack_.top() == ARRAY_MID && type == VALUE_SEPARATOR) || + stack_.top() == OBJ_MID; +} + +util::Status JsonStreamParser::ReportFailure(StringPiece message, + ParseErrorType parse_code) { + (void)parse_code; // Parameter is used in Google-internal code. + static const int kContextLength = 20; + const char* p_start = p_.data(); + const char* json_start = json_.data(); + const char* begin = std::max(p_start - kContextLength, json_start); + const char* end = + std::min(p_start + kContextLength, json_start + json_.size()); + StringPiece segment(begin, end - begin); + std::string location(p_start - begin, ' '); + location.push_back('^'); + auto status = util::InvalidArgumentError( + StrCat(message, "\n", segment, "\n", location)); + return status; +} + +util::Status JsonStreamParser::ReportUnknown(StringPiece message, + ParseErrorType parse_code) { + // If we aren't finishing the parse, cancel parsing and try later. + if (!finishing_) { + return util::CancelledError(""); + } + if (p_.empty()) { + return ReportFailure(StrCat("Unexpected end of string. ", message), + parse_code); + } + return ReportFailure(message, parse_code); +} + +util::Status JsonStreamParser::IncrementRecursionDepth( + StringPiece key) const { + if (++recursion_depth_ > max_recursion_depth_) { + return util::InvalidArgumentError(StrCat( + "Message too deep. Max recursion depth reached for key '", key, "'")); + } + return util::Status(); +} + +void JsonStreamParser::SkipWhitespace() { + while (!p_.empty() && ascii_isspace(*p_.data())) { + Advance(); + } + if (!p_.empty() && !ascii_isspace(*p_.data())) { + seen_non_whitespace_ = true; + } +} + +void JsonStreamParser::Advance() { + // Advance by moving one UTF8 character while making sure we don't go beyond + // the length of StringPiece. + p_.remove_prefix(std::min<int>( + p_.length(), UTF8FirstLetterNumBytes(p_.data(), p_.length()))); +} + +util::Status JsonStreamParser::ParseKey() { + StringPiece original = p_; + + if (allow_permissive_key_naming_) { + if (!ConsumeKeyPermissive(&p_, &key_)) { + return ReportFailure("Invalid key or variable name.", + ParseErrorType::INVALID_KEY_OR_VARIABLE_NAME); + } + } else { + if (!ConsumeKey(&p_, &key_)) { + return ReportFailure("Invalid key or variable name.", + ParseErrorType::INVALID_KEY_OR_VARIABLE_NAME); + } + } + + // If we consumed everything but expect more data, reset p_ and cancel since + // we can't know if the key was complete or not. + if (!finishing_ && p_.empty()) { + p_ = original; + return util::CancelledError(""); + } + // Since we aren't using the key storage, clear it out. + key_storage_.clear(); + return util::Status(); +} + +JsonStreamParser::TokenType JsonStreamParser::GetNextTokenType() { + SkipWhitespace(); + + int size = p_.size(); + if (size == 0) { + // If we ran out of data, report unknown and we'll place the previous parse + // type onto the stack and try again when we have more data. + return UNKNOWN; + } + // TODO(sven): Split this method based on context since different contexts + // support different tokens. Would slightly speed up processing? + const char* data = p_.data(); + StringPiece data_view = StringPiece(data, size); + if (*data == '\"' || *data == '\'') return BEGIN_STRING; + if (*data == '-' || ('0' <= *data && *data <= '9')) { + return BEGIN_NUMBER; + } + if (size >= kKeywordTrue.length() && + HasPrefixString(data_view, kKeywordTrue)) { + return BEGIN_TRUE; + } + if (size >= kKeywordFalse.length() && + HasPrefixString(data_view, kKeywordFalse)) { + return BEGIN_FALSE; + } + if (size >= kKeywordNull.length() && + HasPrefixString(data_view, kKeywordNull)) { + return BEGIN_NULL; + } + if (*data == '{') return BEGIN_OBJECT; + if (*data == '}') return END_OBJECT; + if (*data == '[') return BEGIN_ARRAY; + if (*data == ']') return END_ARRAY; + if (*data == ':') return ENTRY_SEPARATOR; + if (*data == ',') return VALUE_SEPARATOR; + if (MatchKey(p_)) { + return BEGIN_KEY; + } + + // We don't know that we necessarily have an invalid token here, just that we + // can't parse what we have so far. So we don't report an error and just + // return UNKNOWN so we can try again later when we have more data, or if we + // finish and we have leftovers. + return UNKNOWN; +} + +} // namespace converter +} // namespace util +} // namespace protobuf +} // namespace google diff --git a/toolkit/components/protobuf/src/google/protobuf/util/internal/json_stream_parser.h b/toolkit/components/protobuf/src/google/protobuf/util/internal/json_stream_parser.h new file mode 100644 index 0000000000..09f17ad085 --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/util/internal/json_stream_parser.h @@ -0,0 +1,350 @@ +// 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. + +#ifndef GOOGLE_PROTOBUF_UTIL_INTERNAL_JSON_STREAM_PARSER_H__ +#define GOOGLE_PROTOBUF_UTIL_INTERNAL_JSON_STREAM_PARSER_H__ + +#include <cstdint> +#include <stack> +#include <string> + +#include <google/protobuf/stubs/common.h> +#include <google/protobuf/stubs/status.h> +#include <google/protobuf/stubs/strutil.h> +#include <google/protobuf/stubs/status.h> + +// Must be included last. +#include <google/protobuf/port_def.inc> + +namespace google { +namespace protobuf { +namespace util { +namespace converter { + + +class ObjectWriter; + +// A JSON parser that can parse a stream of JSON chunks rather than needing the +// entire JSON string up front. It is a modified version of the parser in +// //net/proto/json/json-parser.h that has been changed in the following ways: +// - Changed from recursion to an explicit stack to allow resumption +// - Added support for int64 and uint64 numbers +// - Removed support for octal and decimal escapes +// - Removed support for numeric keys +// - Removed support for functions (javascript) +// - Removed some lax-comma support (but kept trailing comma support) +// - Writes directly to an ObjectWriter rather than using subclassing +// +// Here is an example usage: +// JsonStreamParser parser(ow_.get()); +// util::Status result = parser.Parse(chunk1); +// result.Update(parser.Parse(chunk2)); +// result.Update(parser.FinishParse()); +// GOOGLE_DCHECK(result.ok()) << "Failed to parse JSON"; +// +// This parser is thread-compatible as long as only one thread is calling a +// Parse() method at a time. +class PROTOBUF_EXPORT JsonStreamParser { + public: + // Creates a JsonStreamParser that will write to the given ObjectWriter. + explicit JsonStreamParser(ObjectWriter* ow); + virtual ~JsonStreamParser(); + + // Parses a UTF-8 encoded JSON string from a StringPiece. If the returned + // status is non-ok, the status might contain a payload ParseErrorType with + // type_url kParseErrorTypeUrl and a payload containing string snippet of the + // error with type_url kParseErrorSnippetUrl. + util::Status Parse(StringPiece json); + + + // Finish parsing the JSON string. If the returned status is non-ok, the + // status might contain a payload ParseErrorType with type_url + // kParseErrorTypeUrl and a payload containing string snippet of the error + // with type_url kParseErrorSnippetUrl. + util::Status FinishParse(); + + + // Sets the max recursion depth of JSON message to be deserialized. JSON + // messages over this depth will fail to be deserialized. + // Default value is 100. + void set_max_recursion_depth(int max_depth) { + max_recursion_depth_ = max_depth; + } + + // Denotes the cause of error. + enum ParseErrorType { + UNKNOWN_PARSE_ERROR, + OCTAL_OR_HEX_ARE_NOT_VALID_JSON_VALUES, + EXPECTED_COLON, + EXPECTED_COMMA_OR_BRACKET, + EXPECTED_VALUE, + EXPECTED_COMMA_OR_BRACES, + EXPECTED_OBJECT_KEY_OR_BRACES, + EXPECTED_VALUE_OR_BRACKET, + INVALID_KEY_OR_VARIABLE_NAME, + NON_UTF_8, + PARSING_TERMINATED_BEFORE_END_OF_INPUT, + UNEXPECTED_TOKEN, + EXPECTED_CLOSING_QUOTE, + ILLEGAL_HEX_STRING, + INVALID_ESCAPE_SEQUENCE, + MISSING_LOW_SURROGATE, + INVALID_LOW_SURROGATE, + INVALID_UNICODE, + UNABLE_TO_PARSE_NUMBER, + NUMBER_EXCEEDS_RANGE_DOUBLE + }; + + private: + friend class JsonStreamParserTest; + // Return the current recursion depth. + int recursion_depth() { return recursion_depth_; } + + enum TokenType { + BEGIN_STRING, // " or ' + BEGIN_NUMBER, // - or digit + BEGIN_TRUE, // true + BEGIN_FALSE, // false + BEGIN_NULL, // null + BEGIN_OBJECT, // { + END_OBJECT, // } + BEGIN_ARRAY, // [ + END_ARRAY, // ] + ENTRY_SEPARATOR, // : + VALUE_SEPARATOR, // , + BEGIN_KEY, // letter, _, $ or digit. Must begin with non-digit + UNKNOWN // Unknown token or we ran out of the stream. + }; + + enum ParseType { + VALUE, // Expects a {, [, true, false, null, string or number + OBJ_MID, // Expects a ',' or } + ENTRY, // Expects a key or } + ENTRY_MID, // Expects a : + ARRAY_VALUE, // Expects a value or ] + ARRAY_MID // Expects a ',' or ] + }; + + // Holds the result of parsing a number + struct NumberResult { + enum Type { DOUBLE, INT, UINT }; + Type type; + union { + double double_val; + int64_t int_val; + uint64_t uint_val; + }; + }; + + // Parses a single chunk of JSON, returning an error if the JSON was invalid. + util::Status ParseChunk(StringPiece chunk); + + // Runs the parser based on stack_ and p_, until the stack is empty or p_ runs + // out of data. If we unexpectedly run out of p_ we push the latest back onto + // the stack and return. + util::Status RunParser(); + + // Parses a value from p_ and writes it to ow_. + // A value may be an object, array, true, false, null, string or number. + util::Status ParseValue(TokenType type); + + // Parses a string and writes it out to the ow_. + util::Status ParseString(); + + // Parses a string, storing the result in parsed_. + util::Status ParseStringHelper(); + + // This function parses unicode escape sequences in strings. It returns an + // error when there's a parsing error, either the size is not the expected + // size or a character is not a hex digit. When it returns str will contain + // what has been successfully parsed so far. + util::Status ParseUnicodeEscape(); + + // Expects p_ to point to a JSON number, writes the number to the writer using + // the appropriate Render method based on the type of number. + util::Status ParseNumber(); + + // Parse a number into a NumberResult, reporting an error if no number could + // be parsed. This method will try to parse into a uint64, int64, or double + // based on whether the number was positive or negative or had a decimal + // component. + util::Status ParseNumberHelper(NumberResult* result); + + // Parse a number as double into a NumberResult. + util::Status ParseDoubleHelper(const std::string& number, + NumberResult* result); + + // Handles a { during parsing of a value. + util::Status HandleBeginObject(); + + // Parses from the ENTRY state. + util::Status ParseEntry(TokenType type); + + // Parses from the ENTRY_MID state. + util::Status ParseEntryMid(TokenType type); + + // Parses from the OBJ_MID state. + util::Status ParseObjectMid(TokenType type); + + // Handles a [ during parsing of a value. + util::Status HandleBeginArray(); + + // Parses from the ARRAY_VALUE state. + util::Status ParseArrayValue(TokenType type); + + // Parses from the ARRAY_MID state. + util::Status ParseArrayMid(TokenType type); + + // Expects p_ to point to an unquoted literal + util::Status ParseTrue(); + util::Status ParseFalse(); + util::Status ParseNull(); + util::Status ParseEmptyNull(); + + // Whether an empty-null is allowed in the current state. + bool IsEmptyNullAllowed(TokenType type); + + // Whether the whole input is all whitespaces. + bool IsInputAllWhiteSpaces(TokenType type); + + // Report a failure as a util::Status. + util::Status ReportFailure(StringPiece message, + ParseErrorType parse_code); + + // Report a failure due to an UNKNOWN token type. We check if we hit the + // end of the stream and if we're finishing or not to detect what type of + // status to return in this case. + util::Status ReportUnknown(StringPiece message, + ParseErrorType parse_code); + + // Helper function to check recursion depth and increment it. It will return + // OkStatus() if the current depth is allowed. Otherwise an error is returned. + // key is used for error reporting. + util::Status IncrementRecursionDepth(StringPiece key) const; + + // Advance p_ past all whitespace or until the end of the string. + void SkipWhitespace(); + + // Advance p_ one UTF-8 character + void Advance(); + + // Expects p_ to point to the beginning of a key. + util::Status ParseKey(); + + // Return the type of the next token at p_. + TokenType GetNextTokenType(); + + // The object writer to write parse events to. + ObjectWriter* ow_; + + // The stack of parsing we still need to do. When the stack runs empty we will + // have parsed a single value from the root (e.g. an object or list). + std::stack<ParseType> stack_; + + // Contains any leftover text from a previous chunk that we weren't able to + // fully parse, for example the start of a key or number. + std::string leftover_; + + // The current chunk of JSON being parsed. Primarily used for providing + // context during error reporting. + StringPiece json_; + + // A pointer within the current JSON being parsed, used to track location. + StringPiece p_; + + // Stores the last key read, as we separate parsing of keys and values. + StringPiece key_; + + // Storage for key_ if we need to keep ownership, for example between chunks + // or if the key was unescaped from a JSON string. + std::string key_storage_; + + // True during the FinishParse() call, so we know that any errors are fatal. + // For example an unterminated string will normally result in cancelling and + // trying during the next chunk, but during FinishParse() it is an error. + bool finishing_; + + // Whether non whitespace tokens have been seen during parsing. + // It is used to handle the case of a pure whitespace stream input. + bool seen_non_whitespace_; + + // The JsonStreamParser requires a root element by default and it will raise + // error if the root element is missing. If `allow_no_root_element_` is true, + // the JsonStreamParser can also handle this case. + bool allow_no_root_element_; + + // String we parsed during a call to ParseStringHelper(). + StringPiece parsed_; + + // Storage for the string we parsed. This may be empty if the string was able + // to be parsed directly from the input. + std::string parsed_storage_; + + // The character that opened the string, either ' or ". + // A value of 0 indicates that string parsing is not in process. + char string_open_; + + // Storage for the chunk that are being parsed in ParseChunk(). + std::string chunk_storage_; + + // Whether to allow non UTF-8 encoded input and replace invalid code points. + bool coerce_to_utf8_; + + // Replacement character for invalid UTF-8 code points. + std::string utf8_replacement_character_; + + // Whether allows empty string represented null array value or object entry + // value. + bool allow_empty_null_; + + // Whether unquoted object keys can contain embedded non-alphanumeric + // characters when this is unambiguous for parsing. + bool allow_permissive_key_naming_; + + // Whether allows out-of-range floating point numbers or reject them. + bool loose_float_number_conversion_; + + // Tracks current recursion depth. + mutable int recursion_depth_; + + // Maximum allowed recursion depth. + int max_recursion_depth_; + + GOOGLE_DISALLOW_IMPLICIT_CONSTRUCTORS(JsonStreamParser); +}; + +} // namespace converter +} // namespace util +} // namespace protobuf +} // namespace google + +#include <google/protobuf/port_undef.inc> + +#endif // GOOGLE_PROTOBUF_UTIL_INTERNAL_JSON_STREAM_PARSER_H__ diff --git a/toolkit/components/protobuf/src/google/protobuf/util/internal/location_tracker.h b/toolkit/components/protobuf/src/google/protobuf/util/internal/location_tracker.h new file mode 100644 index 0000000000..68fefcc85c --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/util/internal/location_tracker.h @@ -0,0 +1,70 @@ +// 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. + +#ifndef GOOGLE_PROTOBUF_UTIL_INTERNAL_LOCATION_TRACKER_H__ +#define GOOGLE_PROTOBUF_UTIL_INTERNAL_LOCATION_TRACKER_H__ + +#include <string> + +#include <google/protobuf/stubs/common.h> + +// Must be included last. +#include <google/protobuf/port_def.inc> + +namespace google { +namespace protobuf { +namespace util { +namespace converter { + +// LocationTrackerInterface is an interface for classes that track +// the location information for the purpose of error reporting. +class PROTOBUF_EXPORT LocationTrackerInterface { + public: + virtual ~LocationTrackerInterface() {} + + // Returns the object location as human readable string. + virtual std::string ToString() const = 0; + + protected: + LocationTrackerInterface() {} + + private: + // Please do not add any data members to this class. + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(LocationTrackerInterface); +}; + +} // namespace converter +} // namespace util +} // namespace protobuf +} // namespace google + +#include <google/protobuf/port_undef.inc> + +#endif // GOOGLE_PROTOBUF_UTIL_INTERNAL_LOCATION_TRACKER_H__ diff --git a/toolkit/components/protobuf/src/google/protobuf/util/internal/mock_error_listener.h b/toolkit/components/protobuf/src/google/protobuf/util/internal/mock_error_listener.h new file mode 100644 index 0000000000..3fbdd883eb --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/util/internal/mock_error_listener.h @@ -0,0 +1,68 @@ +// 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. + +#ifndef GOOGLE_PROTOBUF_UTIL_INTERNAL_MOCK_ERROR_LISTENER_H__ +#define GOOGLE_PROTOBUF_UTIL_INTERNAL_MOCK_ERROR_LISTENER_H__ + +#include <gmock/gmock.h> +#include <google/protobuf/stubs/strutil.h> +#include <google/protobuf/util/internal/error_listener.h> +#include <google/protobuf/util/internal/location_tracker.h> + +namespace google { +namespace protobuf { +namespace util { +namespace converter { + +class MockErrorListener : public ErrorListener { + public: + MockErrorListener() {} + ~MockErrorListener() override {} + + MOCK_METHOD(void, InvalidName, + (const LocationTrackerInterface& loc, + StringPiece unknown_name, StringPiece message), + (override)); + MOCK_METHOD(void, InvalidValue, + (const LocationTrackerInterface& loc, StringPiece type_name, + StringPiece value), + (override)); + MOCK_METHOD(void, MissingField, + (const LocationTrackerInterface& loc, + StringPiece missing_name), + (override)); +}; + +} // namespace converter +} // namespace util +} // namespace protobuf +} // namespace google + +#endif // GOOGLE_PROTOBUF_UTIL_INTERNAL_MOCK_ERROR_LISTENER_H__ diff --git a/toolkit/components/protobuf/src/google/protobuf/util/internal/object_location_tracker.h b/toolkit/components/protobuf/src/google/protobuf/util/internal/object_location_tracker.h new file mode 100644 index 0000000000..47821e6cb2 --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/util/internal/object_location_tracker.h @@ -0,0 +1,64 @@ +// 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. + +#ifndef GOOGLE_PROTOBUF_UTIL_INTERNAL_OBJECT_LOCATION_TRACKER_H__ +#define GOOGLE_PROTOBUF_UTIL_INTERNAL_OBJECT_LOCATION_TRACKER_H__ + +#include <string> + +#include <google/protobuf/stubs/common.h> +#include <google/protobuf/util/internal/location_tracker.h> + +namespace google { +namespace protobuf { +namespace util { +namespace converter { + +// An empty concrete implementation of LocationTrackerInterface. +class ObjectLocationTracker : public LocationTrackerInterface { + public: + // Creates an empty location tracker. + ObjectLocationTracker() {} + + ~ObjectLocationTracker() override {} + + // Returns empty because nothing is tracked. + std::string ToString() const override { return ""; } + + private: + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ObjectLocationTracker); +}; + +} // namespace converter +} // namespace util +} // namespace protobuf +} // namespace google + +#endif // GOOGLE_PROTOBUF_UTIL_INTERNAL_OBJECT_LOCATION_TRACKER_H__ diff --git a/toolkit/components/protobuf/src/google/protobuf/util/internal/object_source.h b/toolkit/components/protobuf/src/google/protobuf/util/internal/object_source.h new file mode 100644 index 0000000000..fc7672e5fa --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/util/internal/object_source.h @@ -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. + +#ifndef GOOGLE_PROTOBUF_UTIL_INTERNAL_OBJECT_SOURCE_H__ +#define GOOGLE_PROTOBUF_UTIL_INTERNAL_OBJECT_SOURCE_H__ + +#include <google/protobuf/stubs/common.h> +#include <google/protobuf/stubs/status.h> +#include <google/protobuf/stubs/strutil.h> +#include <google/protobuf/stubs/status.h> + +// Must be included last. +#include <google/protobuf/port_def.inc> + +namespace google { +namespace protobuf { +namespace util { +namespace converter { + +class ObjectWriter; + +// An ObjectSource is anything that can write to an ObjectWriter. +// Implementation of this interface typically provide constructors or +// factory methods to create an instance based on some source data, for +// example, a character stream, or protobuf. +// +// Derived classes could be thread-unsafe. +class PROTOBUF_EXPORT ObjectSource { + public: + virtual ~ObjectSource() {} + + // Writes to the ObjectWriter + virtual util::Status WriteTo(ObjectWriter* ow) const { + return NamedWriteTo("", ow); + } + + // Writes to the ObjectWriter with a custom name for the message. + // This is useful when you chain ObjectSource together by embedding one + // within another. + virtual util::Status NamedWriteTo(StringPiece name, + ObjectWriter* ow) const = 0; + + protected: + ObjectSource() {} + + private: + // Do not add any data members to this class. + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ObjectSource); +}; + +} // namespace converter +} // namespace util +} // namespace protobuf +} // namespace google + +#include <google/protobuf/port_undef.inc> + +#endif // GOOGLE_PROTOBUF_UTIL_INTERNAL_OBJECT_SOURCE_H__ diff --git a/toolkit/components/protobuf/src/google/protobuf/util/internal/object_writer.cc b/toolkit/components/protobuf/src/google/protobuf/util/internal/object_writer.cc new file mode 100644 index 0000000000..4dabd378e4 --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/util/internal/object_writer.cc @@ -0,0 +1,93 @@ +// 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. + +#include <google/protobuf/util/internal/object_writer.h> + +#include <google/protobuf/util/internal/datapiece.h> + +namespace google { +namespace protobuf { +namespace util { +namespace converter { + +// static +void ObjectWriter::RenderDataPieceTo(const DataPiece& data, + StringPiece name, ObjectWriter* ow) { + switch (data.type()) { + case DataPiece::TYPE_INT32: { + ow->RenderInt32(name, data.ToInt32().value()); + break; + } + case DataPiece::TYPE_INT64: { + ow->RenderInt64(name, data.ToInt64().value()); + break; + } + case DataPiece::TYPE_UINT32: { + ow->RenderUint32(name, data.ToUint32().value()); + break; + } + case DataPiece::TYPE_UINT64: { + ow->RenderUint64(name, data.ToUint64().value()); + break; + } + case DataPiece::TYPE_DOUBLE: { + ow->RenderDouble(name, data.ToDouble().value()); + break; + } + case DataPiece::TYPE_FLOAT: { + ow->RenderFloat(name, data.ToFloat().value()); + break; + } + case DataPiece::TYPE_BOOL: { + ow->RenderBool(name, data.ToBool().value()); + break; + } + case DataPiece::TYPE_STRING: { + ow->RenderString(name, data.ToString().value()); + break; + } + case DataPiece::TYPE_BYTES: { + ow->RenderBytes(name, data.ToBytes().value()); + break; + } + case DataPiece::TYPE_NULL: { + ow->RenderNull(name); + break; + } + default: + break; + } +} + + +} // namespace converter +} // namespace util +} // namespace protobuf +} // namespace google diff --git a/toolkit/components/protobuf/src/google/protobuf/util/internal/object_writer.h b/toolkit/components/protobuf/src/google/protobuf/util/internal/object_writer.h new file mode 100644 index 0000000000..bc4095b6d4 --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/util/internal/object_writer.h @@ -0,0 +1,151 @@ +// 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. + +#ifndef GOOGLE_PROTOBUF_UTIL_INTERNAL_OBJECT_WRITER_H__ +#define GOOGLE_PROTOBUF_UTIL_INTERNAL_OBJECT_WRITER_H__ + +#include <cstdint> + +#include <google/protobuf/stubs/common.h> +#include <google/protobuf/stubs/strutil.h> + +// Must be included last. +#include <google/protobuf/port_def.inc> + +namespace google { +namespace protobuf { +namespace util { +namespace converter { + + +class DataPiece; + +// An ObjectWriter is an interface for writing a stream of events +// representing objects and collections. Implementation of this +// interface can be used to write an object stream to an in-memory +// structure, protobufs, JSON, XML, or any other output format +// desired. The ObjectSource interface is typically used as the +// source of an object stream. +// +// See JsonObjectWriter for a sample implementation of ObjectWriter +// and its use. +// +// Derived classes could be thread-unsafe. +// +// TODO(xinb): seems like a prime candidate to apply the RAII paradigm +// and get rid the need to call EndXXX(). +class PROTOBUF_EXPORT ObjectWriter { + public: + virtual ~ObjectWriter() {} + + // Starts an object. If the name is empty, the object will not be named. + virtual ObjectWriter* StartObject(StringPiece name) = 0; + + // Ends an object. + virtual ObjectWriter* EndObject() = 0; + + // Starts a list. If the name is empty, the list will not be named. + virtual ObjectWriter* StartList(StringPiece name) = 0; + + // Ends a list. + virtual ObjectWriter* EndList() = 0; + + // Renders a boolean value. + virtual ObjectWriter* RenderBool(StringPiece name, bool value) = 0; + + // Renders an 32-bit integer value. + virtual ObjectWriter* RenderInt32(StringPiece name, int32_t value) = 0; + + // Renders an 32-bit unsigned integer value. + virtual ObjectWriter* RenderUint32(StringPiece name, + uint32_t value) = 0; + + // Renders a 64-bit integer value. + virtual ObjectWriter* RenderInt64(StringPiece name, int64_t value) = 0; + + // Renders an 64-bit unsigned integer value. + virtual ObjectWriter* RenderUint64(StringPiece name, + uint64_t value) = 0; + + + // Renders a double value. + virtual ObjectWriter* RenderDouble(StringPiece name, double value) = 0; + // Renders a float value. + virtual ObjectWriter* RenderFloat(StringPiece name, float value) = 0; + + // Renders a StringPiece value. This is for rendering strings. + virtual ObjectWriter* RenderString(StringPiece name, + StringPiece value) = 0; + + // Renders a bytes value. + virtual ObjectWriter* RenderBytes(StringPiece name, StringPiece value) = 0; + + // Renders a Null value. + virtual ObjectWriter* RenderNull(StringPiece name) = 0; + + + // Renders a DataPiece object to a ObjectWriter. + static void RenderDataPieceTo(const DataPiece& data, StringPiece name, + ObjectWriter* ow); + + + // Indicates whether this ObjectWriter has completed writing the root message, + // usually this means writing of one complete object. Subclasses must override + // this behavior appropriately. + virtual bool done() { return false; } + + void set_use_strict_base64_decoding(bool value) { + use_strict_base64_decoding_ = value; + } + + bool use_strict_base64_decoding() const { + return use_strict_base64_decoding_; + } + + protected: + ObjectWriter() : use_strict_base64_decoding_(true) {} + + private: + // If set to true, we use the stricter version of base64 decoding for byte + // fields by making sure decoded version encodes back to the original string. + bool use_strict_base64_decoding_; + + // Do not add any data members to this class. + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ObjectWriter); +}; + +} // namespace converter +} // namespace util +} // namespace protobuf +} // namespace google + +#include <google/protobuf/port_undef.inc> + +#endif // GOOGLE_PROTOBUF_UTIL_INTERNAL_OBJECT_WRITER_H__ diff --git a/toolkit/components/protobuf/src/google/protobuf/util/internal/proto_writer.cc b/toolkit/components/protobuf/src/google/protobuf/util/internal/proto_writer.cc new file mode 100644 index 0000000000..afa5e2e474 --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/util/internal/proto_writer.cc @@ -0,0 +1,827 @@ +// 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. + +#include <google/protobuf/util/internal/proto_writer.h> + +#include <cstdint> +#include <functional> +#include <stack> +#include <unordered_set> + +#include <google/protobuf/stubs/once.h> +#include <google/protobuf/wire_format_lite.h> +#include <google/protobuf/stubs/strutil.h> +#include <google/protobuf/stubs/statusor.h> +#include <google/protobuf/stubs/time.h> +#include <google/protobuf/util/internal/constants.h> +#include <google/protobuf/util/internal/field_mask_utility.h> +#include <google/protobuf/util/internal/object_location_tracker.h> +#include <google/protobuf/util/internal/utility.h> +#include <google/protobuf/stubs/map_util.h> + + +// Must be included last. +#include <google/protobuf/port_def.inc> + +namespace google { +namespace protobuf { +namespace util { +namespace converter { + +using io::CodedOutputStream; +using ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite; + +ProtoWriter::ProtoWriter(TypeResolver* type_resolver, + const google::protobuf::Type& type, + strings::ByteSink* output, ErrorListener* listener) + : master_type_(type), + typeinfo_(TypeInfo::NewTypeInfo(type_resolver)), + own_typeinfo_(true), + done_(false), + ignore_unknown_fields_(false), + ignore_unknown_enum_values_(false), + use_lower_camel_for_enums_(false), + case_insensitive_enum_parsing_(true), + use_json_name_in_missing_fields_(false), + element_(nullptr), + size_insert_(), + output_(output), + buffer_(), + adapter_(&buffer_), + stream_(new CodedOutputStream(&adapter_)), + listener_(listener), + invalid_depth_(0), + tracker_(new ObjectLocationTracker()) {} + +ProtoWriter::ProtoWriter(const TypeInfo* typeinfo, + const google::protobuf::Type& type, + strings::ByteSink* output, ErrorListener* listener) + : master_type_(type), + typeinfo_(typeinfo), + own_typeinfo_(false), + done_(false), + ignore_unknown_fields_(false), + ignore_unknown_enum_values_(false), + use_lower_camel_for_enums_(false), + case_insensitive_enum_parsing_(true), + use_json_name_in_missing_fields_(false), + element_(nullptr), + size_insert_(), + output_(output), + buffer_(), + adapter_(&buffer_), + stream_(new CodedOutputStream(&adapter_)), + listener_(listener), + invalid_depth_(0), + tracker_(new ObjectLocationTracker()) {} + +ProtoWriter::~ProtoWriter() { + if (own_typeinfo_) { + delete typeinfo_; + } + if (element_ == nullptr) return; + // Cleanup explicitly in order to avoid destructor stack overflow when input + // is deeply nested. + // Cast to BaseElement to avoid doing additional checks (like missing fields) + // during pop(). + std::unique_ptr<BaseElement> element( + static_cast<BaseElement*>(element_.get())->pop<BaseElement>()); + while (element != nullptr) { + element.reset(element->pop<BaseElement>()); + } +} + +namespace { + +// Writes an INT32 field, including tag to the stream. +inline util::Status WriteInt32(int field_number, const DataPiece& data, + CodedOutputStream* stream) { + util::StatusOr<int32_t> i32 = data.ToInt32(); + if (i32.ok()) { + WireFormatLite::WriteInt32(field_number, i32.value(), stream); + } + return i32.status(); +} + +// writes an SFIXED32 field, including tag, to the stream. +inline util::Status WriteSFixed32(int field_number, const DataPiece& data, + CodedOutputStream* stream) { + util::StatusOr<int32_t> i32 = data.ToInt32(); + if (i32.ok()) { + WireFormatLite::WriteSFixed32(field_number, i32.value(), stream); + } + return i32.status(); +} + +// Writes an SINT32 field, including tag, to the stream. +inline util::Status WriteSInt32(int field_number, const DataPiece& data, + CodedOutputStream* stream) { + util::StatusOr<int32_t> i32 = data.ToInt32(); + if (i32.ok()) { + WireFormatLite::WriteSInt32(field_number, i32.value(), stream); + } + return i32.status(); +} + +// Writes a FIXED32 field, including tag, to the stream. +inline util::Status WriteFixed32(int field_number, const DataPiece& data, + CodedOutputStream* stream) { + util::StatusOr<uint32_t> u32 = data.ToUint32(); + if (u32.ok()) { + WireFormatLite::WriteFixed32(field_number, u32.value(), stream); + } + return u32.status(); +} + +// Writes a UINT32 field, including tag, to the stream. +inline util::Status WriteUInt32(int field_number, const DataPiece& data, + CodedOutputStream* stream) { + util::StatusOr<uint32_t> u32 = data.ToUint32(); + if (u32.ok()) { + WireFormatLite::WriteUInt32(field_number, u32.value(), stream); + } + return u32.status(); +} + +// Writes an INT64 field, including tag, to the stream. +inline util::Status WriteInt64(int field_number, const DataPiece& data, + CodedOutputStream* stream) { + util::StatusOr<int64_t> i64 = data.ToInt64(); + if (i64.ok()) { + WireFormatLite::WriteInt64(field_number, i64.value(), stream); + } + return i64.status(); +} + +// Writes an SFIXED64 field, including tag, to the stream. +inline util::Status WriteSFixed64(int field_number, const DataPiece& data, + CodedOutputStream* stream) { + util::StatusOr<int64_t> i64 = data.ToInt64(); + if (i64.ok()) { + WireFormatLite::WriteSFixed64(field_number, i64.value(), stream); + } + return i64.status(); +} + +// Writes an SINT64 field, including tag, to the stream. +inline util::Status WriteSInt64(int field_number, const DataPiece& data, + CodedOutputStream* stream) { + util::StatusOr<int64_t> i64 = data.ToInt64(); + if (i64.ok()) { + WireFormatLite::WriteSInt64(field_number, i64.value(), stream); + } + return i64.status(); +} + +// Writes a FIXED64 field, including tag, to the stream. +inline util::Status WriteFixed64(int field_number, const DataPiece& data, + CodedOutputStream* stream) { + util::StatusOr<uint64_t> u64 = data.ToUint64(); + if (u64.ok()) { + WireFormatLite::WriteFixed64(field_number, u64.value(), stream); + } + return u64.status(); +} + +// Writes a UINT64 field, including tag, to the stream. +inline util::Status WriteUInt64(int field_number, const DataPiece& data, + CodedOutputStream* stream) { + util::StatusOr<uint64_t> u64 = data.ToUint64(); + if (u64.ok()) { + WireFormatLite::WriteUInt64(field_number, u64.value(), stream); + } + return u64.status(); +} + +// Writes a DOUBLE field, including tag, to the stream. +inline util::Status WriteDouble(int field_number, const DataPiece& data, + CodedOutputStream* stream) { + util::StatusOr<double> d = data.ToDouble(); + if (d.ok()) { + WireFormatLite::WriteDouble(field_number, d.value(), stream); + } + return d.status(); +} + +// Writes a FLOAT field, including tag, to the stream. +inline util::Status WriteFloat(int field_number, const DataPiece& data, + CodedOutputStream* stream) { + util::StatusOr<float> f = data.ToFloat(); + if (f.ok()) { + WireFormatLite::WriteFloat(field_number, f.value(), stream); + } + return f.status(); +} + +// Writes a BOOL field, including tag, to the stream. +inline util::Status WriteBool(int field_number, const DataPiece& data, + CodedOutputStream* stream) { + util::StatusOr<bool> b = data.ToBool(); + if (b.ok()) { + WireFormatLite::WriteBool(field_number, b.value(), stream); + } + return b.status(); +} + +// Writes a BYTES field, including tag, to the stream. +inline util::Status WriteBytes(int field_number, const DataPiece& data, + CodedOutputStream* stream) { + util::StatusOr<std::string> c = data.ToBytes(); + if (c.ok()) { + WireFormatLite::WriteBytes(field_number, c.value(), stream); + } + return c.status(); +} + +// Writes a STRING field, including tag, to the stream. +inline util::Status WriteString(int field_number, const DataPiece& data, + CodedOutputStream* stream) { + util::StatusOr<std::string> s = data.ToString(); + if (s.ok()) { + WireFormatLite::WriteString(field_number, s.value(), stream); + } + return s.status(); +} + +// Given a google::protobuf::Type, returns the set of all required fields. +std::unordered_set<const google::protobuf::Field*> GetRequiredFields( + const google::protobuf::Type& type) { + std::unordered_set<const google::protobuf::Field*> required; + for (int i = 0; i < type.fields_size(); i++) { + const google::protobuf::Field& field = type.fields(i); + if (field.cardinality() == google::protobuf::Field::CARDINALITY_REQUIRED) { + required.insert(&field); + } + } + return required; +} + +} // namespace + +ProtoWriter::ProtoElement::ProtoElement(const TypeInfo* typeinfo, + const google::protobuf::Type& type, + ProtoWriter* enclosing) + : BaseElement(nullptr), + ow_(enclosing), + parent_field_(nullptr), + typeinfo_(typeinfo), + proto3_(type.syntax() == google::protobuf::SYNTAX_PROTO3), + type_(type), + size_index_(-1), + array_index_(-1), + // oneof_indices_ values are 1-indexed (0 means not present). + oneof_indices_(type.oneofs_size() + 1) { + if (!proto3_) { + required_fields_ = GetRequiredFields(type_); + } +} + +ProtoWriter::ProtoElement::ProtoElement(ProtoWriter::ProtoElement* parent, + const google::protobuf::Field* field, + const google::protobuf::Type& type, + bool is_list) + : BaseElement(parent), + ow_(this->parent()->ow_), + parent_field_(field), + typeinfo_(this->parent()->typeinfo_), + proto3_(type.syntax() == google::protobuf::SYNTAX_PROTO3), + type_(type), + size_index_(!is_list && + field->kind() == google::protobuf::Field::TYPE_MESSAGE + ? ow_->size_insert_.size() + : -1), + array_index_(is_list ? 0 : -1), + // oneof_indices_ values are 1-indexed (0 means not present). + oneof_indices_(type_.oneofs_size() + 1) { + if (!is_list) { + if (ow_->IsRepeated(*field)) { + // Update array_index_ if it is an explicit list. + if (this->parent()->array_index_ >= 0) this->parent()->array_index_++; + } else if (!proto3_) { + // For required fields tracking. + this->parent()->RegisterField(field); + } + + if (field->kind() == google::protobuf::Field::TYPE_MESSAGE) { + if (!proto3_) { + required_fields_ = GetRequiredFields(type_); + } + int start_pos = ow_->stream_->ByteCount(); + // length of serialized message is the final buffer position minus + // starting buffer position, plus length adjustments for size fields + // of any nested messages. We start with -start_pos here, so we only + // need to add the final buffer position to it at the end. + SizeInfo info = {start_pos, -start_pos}; + ow_->size_insert_.push_back(info); + } + } +} + +ProtoWriter::ProtoElement* ProtoWriter::ProtoElement::pop() { + if (!proto3_) { + // Calls the registered error listener for any required field(s) not yet + // seen. + for (std::unordered_set<const google::protobuf::Field*>::iterator it = + required_fields_.begin(); + it != required_fields_.end(); ++it) { + ow_->MissingField(ow_->use_json_name_in_missing_fields_ + ? (*it)->json_name() + : (*it)->name()); + } + } + // Computes the total number of proto bytes used by a message, also adjusts + // the size of all parent messages by the length of this size field. + // If size_index_ < 0, this is not a message, so no size field is added. + if (size_index_ >= 0) { + // Add the final buffer position to compute the total length of this + // serialized message. The stored value (before this addition) already + // contains the total length of the size fields of all nested messages + // minus the initial buffer position. + ow_->size_insert_[size_index_].size += ow_->stream_->ByteCount(); + // Calculate the length required to serialize the size field of the + // message, and propagate this additional size information upward to + // all enclosing messages. + int size = ow_->size_insert_[size_index_].size; + int length = CodedOutputStream::VarintSize32(size); + for (ProtoElement* e = parent(); e != nullptr; e = e->parent()) { + // Only nested messages have size field, lists do not have size field. + if (e->size_index_ >= 0) { + ow_->size_insert_[e->size_index_].size += length; + } + } + } + return BaseElement::pop<ProtoElement>(); +} + +void ProtoWriter::ProtoElement::RegisterField( + const google::protobuf::Field* field) { + if (!required_fields_.empty() && + field->cardinality() == google::protobuf::Field::CARDINALITY_REQUIRED) { + required_fields_.erase(field); + } +} + +std::string ProtoWriter::ProtoElement::ToString() const { + std::string loc = ""; + + // first populate a stack with the nodes since we need to process them + // from root to leaf when generating the string location + const ProtoWriter::ProtoElement* now = this; + std::stack<const ProtoWriter::ProtoElement*> element_stack; + while (now->parent() != nullptr) { + element_stack.push(now); + now = now->parent(); + } + + // now pop each node from the stack and append to the location string + while (!element_stack.empty()) { + now = element_stack.top(); + element_stack.pop(); + + if (!ow_->IsRepeated(*(now->parent_field_)) || + now->parent()->parent_field_ != now->parent_field_) { + std::string name = now->parent_field_->name(); + int i = 0; + while (i < name.size() && + (ascii_isalnum(name[i]) || name[i] == '_')) + ++i; + if (i > 0 && i == name.size()) { // safe field name + if (loc.empty()) { + loc = name; + } else { + StrAppend(&loc, ".", name); + } + } else { + StrAppend(&loc, "[\"", CEscape(name), "\"]"); + } + } + + int array_index_now = now->array_index_; + if (ow_->IsRepeated(*(now->parent_field_)) && array_index_now > 0) { + StrAppend(&loc, "[", array_index_now - 1, "]"); + } + } + + return loc; +} + +bool ProtoWriter::ProtoElement::IsOneofIndexTaken(int32_t index) { + return oneof_indices_[index]; +} + +void ProtoWriter::ProtoElement::TakeOneofIndex(int32_t index) { + oneof_indices_[index] = true; +} + +void ProtoWriter::InvalidName(StringPiece unknown_name, + StringPiece message) { + listener_->InvalidName(location(), unknown_name, message); +} + +void ProtoWriter::InvalidValue(StringPiece type_name, + StringPiece value) { + listener_->InvalidValue(location(), type_name, value); +} + +void ProtoWriter::MissingField(StringPiece missing_name) { + listener_->MissingField(location(), missing_name); +} + +ProtoWriter* ProtoWriter::StartObject( + StringPiece name) { + // Starting the root message. Create the root ProtoElement and return. + if (element_ == nullptr) { + if (!name.empty()) { + InvalidName(name, "Root element should not be named."); + } + element_.reset(new ProtoElement(typeinfo_, master_type_, this)); + return this; + } + + const google::protobuf::Field* field = BeginNamed(name, false); + + if (field == nullptr) return this; + + // Check to see if this field is a oneof and that no oneof in that group has + // already been set. + if (!ValidOneof(*field, name)) { + ++invalid_depth_; + return this; + } + + const google::protobuf::Type* type = LookupType(field); + if (type == nullptr) { + ++invalid_depth_; + InvalidName(name, StrCat("Missing descriptor for field: ", + field->type_url())); + return this; + } + + return StartObjectField(*field, *type); +} + + +ProtoWriter* ProtoWriter::EndObject() { + if (invalid_depth_ > 0) { + --invalid_depth_; + return this; + } + + if (element_ != nullptr) { + element_.reset(element_->pop()); + } + + + // If ending the root element, + // then serialize the full message with calculated sizes. + if (element_ == nullptr) { + WriteRootMessage(); + } + return this; +} + +ProtoWriter* ProtoWriter::StartList( + StringPiece name) { + + const google::protobuf::Field* field = BeginNamed(name, true); + + if (field == nullptr) return this; + + if (!ValidOneof(*field, name)) { + ++invalid_depth_; + return this; + } + + const google::protobuf::Type* type = LookupType(field); + if (type == nullptr) { + ++invalid_depth_; + InvalidName(name, StrCat("Missing descriptor for field: ", + field->type_url())); + return this; + } + + return StartListField(*field, *type); +} + + +ProtoWriter* ProtoWriter::EndList() { + if (invalid_depth_ > 0) { + --invalid_depth_; + } else if (element_ != nullptr) { + element_.reset(element_->pop()); + } + return this; +} + +ProtoWriter* ProtoWriter::RenderDataPiece( + StringPiece name, const DataPiece& data) { + util::Status status; + if (invalid_depth_ > 0) return this; + + const google::protobuf::Field* field = Lookup(name); + + if (field == nullptr) return this; + + if (!ValidOneof(*field, name)) return this; + + const google::protobuf::Type* type = LookupType(field); + if (type == nullptr) { + InvalidName(name, StrCat("Missing descriptor for field: ", + field->type_url())); + return this; + } + + return RenderPrimitiveField(*field, *type, data); +} + +bool ProtoWriter::ValidOneof(const google::protobuf::Field& field, + StringPiece unnormalized_name) { + if (element_ == nullptr) return true; + + if (field.oneof_index() > 0) { + if (element_->IsOneofIndexTaken(field.oneof_index())) { + InvalidValue( + "oneof", + StrCat( + "oneof field '", element_->type().oneofs(field.oneof_index() - 1), + "' is already set. Cannot set '", unnormalized_name, "'")); + return false; + } + element_->TakeOneofIndex(field.oneof_index()); + } + return true; +} + +bool ProtoWriter::IsRepeated(const google::protobuf::Field& field) { + return field.cardinality() == google::protobuf::Field::CARDINALITY_REPEATED; +} + +ProtoWriter* ProtoWriter::StartObjectField(const google::protobuf::Field& field, + const google::protobuf::Type& type) { + WriteTag(field); + element_.reset(new ProtoElement(element_.release(), &field, type, false)); + return this; +} + +ProtoWriter* ProtoWriter::StartListField(const google::protobuf::Field& field, + const google::protobuf::Type& type) { + element_.reset(new ProtoElement(element_.release(), &field, type, true)); + return this; +} + +util::Status ProtoWriter::WriteEnum(int field_number, const DataPiece& data, + const google::protobuf::Enum* enum_type, + CodedOutputStream* stream, + bool use_lower_camel_for_enums, + bool case_insensitive_enum_parsing, + bool ignore_unknown_values) { + bool is_unknown_enum_value = false; + util::StatusOr<int> e = data.ToEnum( + enum_type, use_lower_camel_for_enums, case_insensitive_enum_parsing, + ignore_unknown_values, &is_unknown_enum_value); + if (e.ok() && !is_unknown_enum_value) { + WireFormatLite::WriteEnum(field_number, e.value(), stream); + } + return e.status(); +} + +ProtoWriter* ProtoWriter::RenderPrimitiveField( + const google::protobuf::Field& field, const google::protobuf::Type& type, + const DataPiece& data) { + util::Status status; + + // Pushing a ProtoElement and then pop it off at the end for 2 purposes: + // error location reporting and required field accounting. + // + // For proto3, since there is no required field tracking, we only need to + // push ProtoElement for error cases. + if (!element_->proto3()) { + element_.reset(new ProtoElement(element_.release(), &field, type, false)); + } + + switch (field.kind()) { + case google::protobuf::Field::TYPE_INT32: { + status = WriteInt32(field.number(), data, stream_.get()); + break; + } + case google::protobuf::Field::TYPE_SFIXED32: { + status = WriteSFixed32(field.number(), data, stream_.get()); + break; + } + case google::protobuf::Field::TYPE_SINT32: { + status = WriteSInt32(field.number(), data, stream_.get()); + break; + } + case google::protobuf::Field::TYPE_FIXED32: { + status = WriteFixed32(field.number(), data, stream_.get()); + break; + } + case google::protobuf::Field::TYPE_UINT32: { + status = WriteUInt32(field.number(), data, stream_.get()); + break; + } + case google::protobuf::Field::TYPE_INT64: { + status = WriteInt64(field.number(), data, stream_.get()); + break; + } + case google::protobuf::Field::TYPE_SFIXED64: { + status = WriteSFixed64(field.number(), data, stream_.get()); + break; + } + case google::protobuf::Field::TYPE_SINT64: { + status = WriteSInt64(field.number(), data, stream_.get()); + break; + } + case google::protobuf::Field::TYPE_FIXED64: { + status = WriteFixed64(field.number(), data, stream_.get()); + break; + } + case google::protobuf::Field::TYPE_UINT64: { + status = WriteUInt64(field.number(), data, stream_.get()); + break; + } + case google::protobuf::Field::TYPE_DOUBLE: { + status = WriteDouble(field.number(), data, stream_.get()); + break; + } + case google::protobuf::Field::TYPE_FLOAT: { + status = WriteFloat(field.number(), data, stream_.get()); + break; + } + case google::protobuf::Field::TYPE_BOOL: { + status = WriteBool(field.number(), data, stream_.get()); + break; + } + case google::protobuf::Field::TYPE_BYTES: { + status = WriteBytes(field.number(), data, stream_.get()); + break; + } + case google::protobuf::Field::TYPE_STRING: { + status = WriteString(field.number(), data, stream_.get()); + break; + } + case google::protobuf::Field::TYPE_ENUM: { + status = WriteEnum( + field.number(), data, typeinfo_->GetEnumByTypeUrl(field.type_url()), + stream_.get(), use_lower_camel_for_enums_, + case_insensitive_enum_parsing_, ignore_unknown_enum_values_); + break; + } + default: // TYPE_GROUP, TYPE_MESSAGE, TYPE_UNKNOWN. + status = util::InvalidArgumentError(data.ValueAsStringOrDefault("")); + } + + if (!status.ok()) { + // Push a ProtoElement for location reporting purposes. + if (element_->proto3()) { + element_.reset(new ProtoElement(element_.release(), &field, type, false)); + } + InvalidValue(field.type_url().empty() + ? google::protobuf::Field_Kind_Name(field.kind()) + : field.type_url(), + status.message()); + element_.reset(element()->pop()); + return this; + } + + if (!element_->proto3()) element_.reset(element()->pop()); + + return this; +} + +const google::protobuf::Field* ProtoWriter::BeginNamed(StringPiece name, + bool is_list) { + if (invalid_depth_ > 0) { + ++invalid_depth_; + return nullptr; + } + const google::protobuf::Field* field = Lookup(name); + if (field == nullptr) { + ++invalid_depth_; + // InvalidName() already called in Lookup(). + return nullptr; + } + if (is_list && !IsRepeated(*field)) { + ++invalid_depth_; + InvalidName(name, "Proto field is not repeating, cannot start list."); + return nullptr; + } + return field; +} + +const google::protobuf::Field* ProtoWriter::Lookup( + StringPiece unnormalized_name) { + ProtoElement* e = element(); + if (e == nullptr) { + InvalidName(unnormalized_name, "Root element must be a message."); + return nullptr; + } + if (unnormalized_name.empty()) { + // Objects in repeated field inherit the same field descriptor. + if (e->parent_field() == nullptr) { + InvalidName(unnormalized_name, "Proto fields must have a name."); + } else if (!IsRepeated(*e->parent_field())) { + InvalidName(unnormalized_name, "Proto fields must have a name."); + return nullptr; + } + return e->parent_field(); + } + const google::protobuf::Field* field = + typeinfo_->FindField(&e->type(), unnormalized_name); + if (field == nullptr && !ignore_unknown_fields_) { + InvalidName(unnormalized_name, "Cannot find field."); + } + return field; +} + +const google::protobuf::Type* ProtoWriter::LookupType( + const google::protobuf::Field* field) { + return ((field->kind() == google::protobuf::Field::TYPE_MESSAGE || + field->kind() == google::protobuf::Field::TYPE_GROUP) + ? typeinfo_->GetTypeByTypeUrl(field->type_url()) + : &element_->type()); +} + +void ProtoWriter::WriteRootMessage() { + GOOGLE_DCHECK(!done_); + int curr_pos = 0; + // Calls the destructor of CodedOutputStream to remove any uninitialized + // memory from the Cord before we read it. + stream_.reset(nullptr); + const void* data; + int length; + io::ArrayInputStream input_stream(buffer_.data(), buffer_.size()); + while (input_stream.Next(&data, &length)) { + if (length == 0) continue; + int num_bytes = length; + // Write up to where we need to insert the size field. + // The number of bytes we may write is the smaller of: + // - the current fragment size + // - the distance to the next position where a size field needs to be + // inserted. + if (!size_insert_.empty() && + size_insert_.front().pos - curr_pos < num_bytes) { + num_bytes = size_insert_.front().pos - curr_pos; + } + output_->Append(static_cast<const char*>(data), num_bytes); + if (num_bytes < length) { + input_stream.BackUp(length - num_bytes); + } + curr_pos += num_bytes; + // Insert the size field. + // size_insert_.front(): the next <index, size> pair to be written. + // size_insert_.front().pos: position of the size field. + // size_insert_.front().size: the size (integer) to be inserted. + if (!size_insert_.empty() && curr_pos == size_insert_.front().pos) { + // Varint32 occupies at most 10 bytes. + uint8_t insert_buffer[10]; + uint8_t* insert_buffer_pos = CodedOutputStream::WriteVarint32ToArray( + size_insert_.front().size, insert_buffer); + output_->Append(reinterpret_cast<const char*>(insert_buffer), + insert_buffer_pos - insert_buffer); + size_insert_.pop_front(); + } + } + output_->Flush(); + stream_.reset(new CodedOutputStream(&adapter_)); + done_ = true; +} + +void ProtoWriter::WriteTag(const google::protobuf::Field& field) { + WireFormatLite::WireType wire_type = WireFormatLite::WireTypeForFieldType( + static_cast<WireFormatLite::FieldType>(field.kind())); + stream_->WriteTag(WireFormatLite::MakeTag(field.number(), wire_type)); +} + + +} // namespace converter +} // namespace util +} // namespace protobuf +} // namespace google diff --git a/toolkit/components/protobuf/src/google/protobuf/util/internal/proto_writer.h b/toolkit/components/protobuf/src/google/protobuf/util/internal/proto_writer.h new file mode 100644 index 0000000000..a7cf6acf78 --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/util/internal/proto_writer.h @@ -0,0 +1,389 @@ +// 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. + +#ifndef GOOGLE_PROTOBUF_UTIL_INTERNAL_PROTO_WRITER_H__ +#define GOOGLE_PROTOBUF_UTIL_INTERNAL_PROTO_WRITER_H__ + +#include <cstdint> +#include <deque> +#include <string> +#include <unordered_set> +#include <vector> + +#include <google/protobuf/stubs/common.h> +#include <google/protobuf/type.pb.h> +#include <google/protobuf/io/coded_stream.h> +#include <google/protobuf/io/zero_copy_stream_impl.h> +#include <google/protobuf/descriptor.h> +#include <google/protobuf/stubs/bytestream.h> +#include <google/protobuf/stubs/status.h> +#include <google/protobuf/util/internal/datapiece.h> +#include <google/protobuf/util/internal/error_listener.h> +#include <google/protobuf/util/internal/structured_objectwriter.h> +#include <google/protobuf/util/internal/type_info.h> +#include <google/protobuf/util/type_resolver.h> +#include <google/protobuf/stubs/hash.h> +#include <google/protobuf/stubs/status.h> + +// Must be included last. +#include <google/protobuf/port_def.inc> + +namespace google { +namespace protobuf { +namespace util { +namespace converter { + + +class ObjectLocationTracker; + +// An ObjectWriter that can write protobuf bytes directly from writer events. +// This class does not support special types like Struct or Map. However, since +// this class supports raw protobuf, it can be used to provide support for +// special types by inheriting from it or by wrapping it. +// +// It also supports streaming. +class PROTOBUF_EXPORT ProtoWriter : public StructuredObjectWriter { + public: +// Constructor. Does not take ownership of any parameter passed in. + ProtoWriter(TypeResolver* type_resolver, const google::protobuf::Type& type, + strings::ByteSink* output, ErrorListener* listener); + ~ProtoWriter() override; + + // ObjectWriter methods. + ProtoWriter* StartObject(StringPiece name) override; + ProtoWriter* EndObject() override; + ProtoWriter* StartList(StringPiece name) override; + ProtoWriter* EndList() override; + ProtoWriter* RenderBool(StringPiece name, bool value) override { + return RenderDataPiece(name, DataPiece(value)); + } + ProtoWriter* RenderInt32(StringPiece name, int32_t value) override { + return RenderDataPiece(name, DataPiece(value)); + } + ProtoWriter* RenderUint32(StringPiece name, uint32_t value) override { + return RenderDataPiece(name, DataPiece(value)); + } + ProtoWriter* RenderInt64(StringPiece name, int64_t value) override { + return RenderDataPiece(name, DataPiece(value)); + } + ProtoWriter* RenderUint64(StringPiece name, uint64_t value) override { + return RenderDataPiece(name, DataPiece(value)); + } + ProtoWriter* RenderDouble(StringPiece name, double value) override { + return RenderDataPiece(name, DataPiece(value)); + } + ProtoWriter* RenderFloat(StringPiece name, float value) override { + return RenderDataPiece(name, DataPiece(value)); + } + ProtoWriter* RenderString(StringPiece name, + StringPiece value) override { + return RenderDataPiece(name, + DataPiece(value, use_strict_base64_decoding())); + } + + ProtoWriter* RenderBytes(StringPiece name, StringPiece value) override { + return RenderDataPiece( + name, DataPiece(value, false, use_strict_base64_decoding())); + } + + ProtoWriter* RenderNull(StringPiece name) override { + return RenderDataPiece(name, DataPiece::NullData()); + } + + + // Renders a DataPiece 'value' into a field whose wire type is determined + // from the given field 'name'. + virtual ProtoWriter* RenderDataPiece(StringPiece name, + const DataPiece& data); + + + // Returns the location tracker to use for tracking locations for errors. + const LocationTrackerInterface& location() { + return element_ != nullptr ? *element_ : *tracker_; + } + + // When true, we finished writing to output a complete message. + bool done() override { return done_; } + + // Returns the proto stream object. + io::CodedOutputStream* stream() { return stream_.get(); } + + // Getters and mutators of invalid_depth_. + void IncrementInvalidDepth() { ++invalid_depth_; } + void DecrementInvalidDepth() { --invalid_depth_; } + int invalid_depth() { return invalid_depth_; } + + ErrorListener* listener() { return listener_; } + + const TypeInfo* typeinfo() { return typeinfo_; } + + void set_ignore_unknown_fields(bool ignore_unknown_fields) { + ignore_unknown_fields_ = ignore_unknown_fields; + } + + bool ignore_unknown_fields() { return ignore_unknown_fields_; } + + void set_ignore_unknown_enum_values(bool ignore_unknown_enum_values) { + ignore_unknown_enum_values_ = ignore_unknown_enum_values; + } + + void set_use_lower_camel_for_enums(bool use_lower_camel_for_enums) { + use_lower_camel_for_enums_ = use_lower_camel_for_enums; + } + + void set_case_insensitive_enum_parsing(bool case_insensitive_enum_parsing) { + case_insensitive_enum_parsing_ = case_insensitive_enum_parsing; + } + + void set_use_json_name_in_missing_fields( + bool use_json_name_in_missing_fields) { + use_json_name_in_missing_fields_ = use_json_name_in_missing_fields; + } + + protected: + class PROTOBUF_EXPORT ProtoElement : public BaseElement, + public LocationTrackerInterface { + public: + // Constructor for the root element. No parent nor field. + ProtoElement(const TypeInfo* typeinfo, const google::protobuf::Type& type, + ProtoWriter* enclosing); + + // Constructor for a field of an element. + ProtoElement(ProtoElement* parent, const google::protobuf::Field* field, + const google::protobuf::Type& type, bool is_list); + + ~ProtoElement() override {} + + // Called just before the destructor for clean up: + // - reports any missing required fields + // - computes the space needed by the size field, and augment the + // length of all parent messages by this additional space. + // - releases and returns the parent pointer. + ProtoElement* pop(); + + // Accessors + // parent_field() may be nullptr if we are at root. + const google::protobuf::Field* parent_field() const { + return parent_field_; + } + const google::protobuf::Type& type() const { return type_; } + + // Registers field for accounting required fields. + void RegisterField(const google::protobuf::Field* field); + + // To report location on error messages. + std::string ToString() const override; + + ProtoElement* parent() const override { + return static_cast<ProtoElement*>(BaseElement::parent()); + } + + // Returns true if the index is already taken by a preceding oneof input. + bool IsOneofIndexTaken(int32_t index); + + // Marks the oneof 'index' as taken. Future inputs to this oneof will + // generate an error. + void TakeOneofIndex(int32_t index); + + bool proto3() { return proto3_; } + + private: + // Used for access to variables of the enclosing instance of + // ProtoWriter. + ProtoWriter* ow_; + + // Describes the element as a field in the parent message. + // parent_field_ is nullptr if and only if this element is the root element. + const google::protobuf::Field* parent_field_; + + // TypeInfo to lookup types. + const TypeInfo* typeinfo_; + + // Whether the type_ is proto3 or not. + bool proto3_; + + // Additional variables if this element is a message: + // (Root element is always a message). + // type_ : the type of this element. + // required_fields_ : set of required fields. + // size_index_ : index into ProtoWriter::size_insert_ + // for later insertion of serialized message length. + const google::protobuf::Type& type_; + std::unordered_set<const google::protobuf::Field*> required_fields_; + const int size_index_; + + // Tracks position in repeated fields, needed for LocationTrackerInterface. + int array_index_; + + // Set of oneof indices already seen for the type_. Used to validate + // incoming messages so no more than one oneof is set. + std::vector<bool> oneof_indices_; + + GOOGLE_DISALLOW_IMPLICIT_CONSTRUCTORS(ProtoElement); + }; + + // Container for inserting 'size' information at the 'pos' position. + struct SizeInfo { + const int pos; + int size; + }; + + ProtoWriter(const TypeInfo* typeinfo, const google::protobuf::Type& type, + strings::ByteSink* output, ErrorListener* listener); + + ProtoElement* element() override { return element_.get(); } + + // Helper methods for calling ErrorListener. See error_listener.h. + void InvalidName(StringPiece unknown_name, StringPiece message); + void InvalidValue(StringPiece type_name, StringPiece value); + void MissingField(StringPiece missing_name); + + // Common code for BeginObject() and BeginList() that does invalid_depth_ + // bookkeeping associated with name lookup. + const google::protobuf::Field* BeginNamed(StringPiece name, + bool is_list); + + // Lookup the field in the current element. Looks in the base descriptor + // and in any extension. This will report an error if the field cannot be + // found when ignore_unknown_names_ is false or if multiple matching + // extensions are found. + const google::protobuf::Field* Lookup(StringPiece name); + + // Lookup the field type in the type descriptor. Returns nullptr if the type + // is not known. + const google::protobuf::Type* LookupType( + const google::protobuf::Field* field); + + // Write serialized output to the final output ByteSink, inserting all + // the size information for nested messages that are missing from the + // intermediate Cord buffer. + void WriteRootMessage(); + + // Helper method to write proto tags based on the given field. + void WriteTag(const google::protobuf::Field& field); + + + // Returns true if the field for type_ can be set as a oneof. If field is not + // a oneof type, this function does nothing and returns true. + // If another field for this oneof is already set, this function returns + // false. It also calls the appropriate error callback. + // unnormalized_name is used for error string. + bool ValidOneof(const google::protobuf::Field& field, + StringPiece unnormalized_name); + + // Returns true if the field is repeated. + bool IsRepeated(const google::protobuf::Field& field); + + // Starts an object given the field and the enclosing type. + ProtoWriter* StartObjectField(const google::protobuf::Field& field, + const google::protobuf::Type& type); + + // Starts a list given the field and the enclosing type. + ProtoWriter* StartListField(const google::protobuf::Field& field, + const google::protobuf::Type& type); + + // Renders a primitive field given the field and the enclosing type. + ProtoWriter* RenderPrimitiveField(const google::protobuf::Field& field, + const google::protobuf::Type& type, + const DataPiece& data); + + private: + // Writes an ENUM field, including tag, to the stream. + static util::Status WriteEnum(int field_number, const DataPiece& data, + const google::protobuf::Enum* enum_type, + io::CodedOutputStream* stream, + bool use_lower_camel_for_enums, + bool case_insensitive_enum_parsing, + bool ignore_unknown_values); + + // Variables for describing the structure of the input tree: + // master_type_: descriptor for the whole protobuf message. + // typeinfo_ : the TypeInfo object to lookup types. + const google::protobuf::Type& master_type_; + const TypeInfo* typeinfo_; + // Whether we own the typeinfo_ object. + bool own_typeinfo_; + + // Indicates whether we finished writing root message completely. + bool done_; + + // If true, don't report unknown field names to the listener. + bool ignore_unknown_fields_; + + // If true, don't report unknown enum values to the listener. + bool ignore_unknown_enum_values_; + + // If true, check if enum name in camel case or without underscore matches the + // field name. + bool use_lower_camel_for_enums_; + + // If true, check if enum name in UPPER_CASE matches the field name. + bool case_insensitive_enum_parsing_; + + // If true, use the json name in missing fields errors. + bool use_json_name_in_missing_fields_; + + // Variable for internal state processing: + // element_ : the current element. + // size_insert_: sizes of nested messages. + // pos - position to insert the size field. + // size - size value to be inserted. + std::unique_ptr<ProtoElement> element_; + std::deque<SizeInfo> size_insert_; + + // Variables for output generation: + // output_ : pointer to an external ByteSink for final user-visible output. + // buffer_ : buffer holding partial message before being ready for output_. + // adapter_ : internal adapter between CodedOutputStream and buffer_. + // stream_ : wrapper for writing tags and other encodings in wire format. + strings::ByteSink* output_; + std::string buffer_; + io::StringOutputStream adapter_; + std::unique_ptr<io::CodedOutputStream> stream_; + + // Variables for error tracking and reporting: + // listener_ : a place to report any errors found. + // invalid_depth_: number of enclosing invalid nested messages. + // tracker_ : the root location tracker interface. + ErrorListener* listener_; + int invalid_depth_; + std::unique_ptr<LocationTrackerInterface> tracker_; + + GOOGLE_DISALLOW_IMPLICIT_CONSTRUCTORS(ProtoWriter); +}; + +} // namespace converter +} // namespace util +} // namespace protobuf +} // namespace google + +#include <google/protobuf/port_undef.inc> + +#endif // GOOGLE_PROTOBUF_UTIL_INTERNAL_PROTO_WRITER_H__ diff --git a/toolkit/components/protobuf/src/google/protobuf/util/internal/protostream_objectsource.cc b/toolkit/components/protobuf/src/google/protobuf/util/internal/protostream_objectsource.cc new file mode 100644 index 0000000000..cf6c99ac1f --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/util/internal/protostream_objectsource.cc @@ -0,0 +1,1114 @@ +// 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. + +#include <google/protobuf/util/internal/protostream_objectsource.h> + +#include <cstdint> +#include <unordered_map> +#include <utility> + +#include <google/protobuf/stubs/logging.h> +#include <google/protobuf/stubs/common.h> +#include <google/protobuf/io/coded_stream.h> +#include <google/protobuf/io/zero_copy_stream_impl.h> +#include <google/protobuf/descriptor.h> +#include <google/protobuf/stubs/once.h> +#include <google/protobuf/unknown_field_set.h> +#include <google/protobuf/wire_format.h> +#include <google/protobuf/wire_format_lite.h> +#include <google/protobuf/stubs/strutil.h> +#include <google/protobuf/stubs/casts.h> +#include <google/protobuf/stubs/status.h> +#include <google/protobuf/stubs/stringprintf.h> +#include <google/protobuf/stubs/time.h> +#include <google/protobuf/util/internal/constants.h> +#include <google/protobuf/util/internal/field_mask_utility.h> +#include <google/protobuf/util/internal/utility.h> +#include <google/protobuf/stubs/map_util.h> +#include <google/protobuf/stubs/status_macros.h> + + +// Must be included last. +#include <google/protobuf/port_def.inc> + + +namespace google { +namespace protobuf { +namespace util { +namespace converter { + +using ::PROTOBUF_NAMESPACE_ID::internal::WireFormat; +using ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite; + +namespace { + +static int kDefaultMaxRecursionDepth = 64; + +// Finds a field with the given number. nullptr if none found. +const google::protobuf::Field* FindFieldByNumber( + const google::protobuf::Type& type, int number); + +// Returns true if the field is packable. +bool IsPackable(const google::protobuf::Field& field); + +// Finds an enum value with the given number. nullptr if none found. +const google::protobuf::EnumValue* FindEnumValueByNumber( + const google::protobuf::Enum& tech_enum, int number); + +// Utility function to format nanos. +const std::string FormatNanos(uint32_t nanos, bool with_trailing_zeros); + +util::StatusOr<std::string> MapKeyDefaultValueAsString( + const google::protobuf::Field& field) { + switch (field.kind()) { + case google::protobuf::Field::TYPE_BOOL: + return std::string("false"); + case google::protobuf::Field::TYPE_INT32: + case google::protobuf::Field::TYPE_INT64: + case google::protobuf::Field::TYPE_UINT32: + case google::protobuf::Field::TYPE_UINT64: + case google::protobuf::Field::TYPE_SINT32: + case google::protobuf::Field::TYPE_SINT64: + case google::protobuf::Field::TYPE_SFIXED32: + case google::protobuf::Field::TYPE_SFIXED64: + case google::protobuf::Field::TYPE_FIXED32: + case google::protobuf::Field::TYPE_FIXED64: + return std::string("0"); + case google::protobuf::Field::TYPE_STRING: + return std::string(); + default: + return util::InternalError("Invalid map key type."); + } +} +} // namespace + + +ProtoStreamObjectSource::ProtoStreamObjectSource( + io::CodedInputStream* stream, TypeResolver* type_resolver, + const google::protobuf::Type& type, const RenderOptions& render_options) + : stream_(stream), + typeinfo_(TypeInfo::NewTypeInfo(type_resolver)), + own_typeinfo_(true), + type_(type), + render_options_(render_options), + recursion_depth_(0), + max_recursion_depth_(kDefaultMaxRecursionDepth) { + GOOGLE_LOG_IF(DFATAL, stream == nullptr) << "Input stream is nullptr."; +} + +ProtoStreamObjectSource::ProtoStreamObjectSource( + io::CodedInputStream* stream, const TypeInfo* typeinfo, + const google::protobuf::Type& type, const RenderOptions& render_options) + : stream_(stream), + typeinfo_(typeinfo), + own_typeinfo_(false), + type_(type), + render_options_(render_options), + recursion_depth_(0), + max_recursion_depth_(kDefaultMaxRecursionDepth) { + GOOGLE_LOG_IF(DFATAL, stream == nullptr) << "Input stream is nullptr."; +} + +ProtoStreamObjectSource::~ProtoStreamObjectSource() { + if (own_typeinfo_) { + delete typeinfo_; + } +} + +util::Status ProtoStreamObjectSource::NamedWriteTo(StringPiece name, + ObjectWriter* ow) const { + return WriteMessage(type_, name, 0, true, ow); +} + +const google::protobuf::Field* ProtoStreamObjectSource::FindAndVerifyField( + const google::protobuf::Type& type, uint32_t tag) const { + // Lookup the new field in the type by tag number. + const google::protobuf::Field* field = FindFieldByNumber(type, tag >> 3); + // Verify if the field corresponds to the wire type in tag. + // If there is any discrepancy, mark the field as not found. + if (field != nullptr) { + WireFormatLite::WireType expected_type = + WireFormatLite::WireTypeForFieldType( + static_cast<WireFormatLite::FieldType>(field->kind())); + WireFormatLite::WireType actual_type = WireFormatLite::GetTagWireType(tag); + if (actual_type != expected_type && + (!IsPackable(*field) || + actual_type != WireFormatLite::WIRETYPE_LENGTH_DELIMITED)) { + field = nullptr; + } + } + return field; +} + +util::Status ProtoStreamObjectSource::WriteMessage( + const google::protobuf::Type& type, StringPiece name, + const uint32_t end_tag, bool include_start_and_end, + ObjectWriter* ow) const { + + const TypeRenderer* type_renderer = FindTypeRenderer(type.name()); + if (type_renderer != nullptr) { + return (*type_renderer)(this, type, name, ow); + } + + const google::protobuf::Field* field = nullptr; + std::string field_name; + // last_tag set to dummy value that is different from tag. + uint32_t tag = stream_->ReadTag(), last_tag = tag + 1; + UnknownFieldSet unknown_fields; + + + if (include_start_and_end) { + ow->StartObject(name); + } + while (tag != end_tag && tag != 0) { + if (tag != last_tag) { // Update field only if tag is changed. + last_tag = tag; + field = FindAndVerifyField(type, tag); + if (field != nullptr) { + if (render_options_.preserve_proto_field_names) { + field_name = field->name(); + } else { + field_name = field->json_name(); + } + } + } + if (field == nullptr) { + // If we didn't find a field, skip this unknown tag. + // TODO(wpoon): Check return boolean value. + WireFormat::SkipField( + stream_, tag, + nullptr); + tag = stream_->ReadTag(); + continue; + } + + if (field->cardinality() == google::protobuf::Field::CARDINALITY_REPEATED) { + if (IsMap(*field)) { + ow->StartObject(field_name); + ASSIGN_OR_RETURN(tag, RenderMap(field, field_name, tag, ow)); + ow->EndObject(); + } else { + ASSIGN_OR_RETURN(tag, RenderList(field, field_name, tag, ow)); + } + } else { + // Render the field. + RETURN_IF_ERROR(RenderField(field, field_name, ow)); + tag = stream_->ReadTag(); + } + } + + + if (include_start_and_end) { + ow->EndObject(); + } + return util::Status(); +} + +util::StatusOr<uint32_t> ProtoStreamObjectSource::RenderList( + const google::protobuf::Field* field, StringPiece name, + uint32_t list_tag, ObjectWriter* ow) const { + uint32_t tag_to_return = 0; + ow->StartList(name); + if (IsPackable(*field) && + list_tag == + WireFormatLite::MakeTag(field->number(), + WireFormatLite::WIRETYPE_LENGTH_DELIMITED)) { + RETURN_IF_ERROR(RenderPacked(field, ow)); + // Since packed fields have a single tag, read another tag from stream to + // return. + tag_to_return = stream_->ReadTag(); + } else { + do { + RETURN_IF_ERROR(RenderField(field, "", ow)); + } while ((tag_to_return = stream_->ReadTag()) == list_tag); + } + ow->EndList(); + return tag_to_return; +} + +util::StatusOr<uint32_t> ProtoStreamObjectSource::RenderMap( + const google::protobuf::Field* field, StringPiece /* name */, + uint32_t list_tag, ObjectWriter* ow) const { + const google::protobuf::Type* field_type = + typeinfo_->GetTypeByTypeUrl(field->type_url()); + uint32_t tag_to_return = 0; + do { + // Render map entry message type. + uint32_t buffer32; + stream_->ReadVarint32(&buffer32); // message length + int old_limit = stream_->PushLimit(buffer32); + std::string map_key; + for (uint32_t tag = stream_->ReadTag(); tag != 0; + tag = stream_->ReadTag()) { + const google::protobuf::Field* map_entry_field = + FindAndVerifyField(*field_type, tag); + if (map_entry_field == nullptr) { + WireFormat::SkipField(stream_, tag, nullptr); + continue; + } + // Map field numbers are key = 1 and value = 2 + if (map_entry_field->number() == 1) { + map_key = ReadFieldValueAsString(*map_entry_field); + } else if (map_entry_field->number() == 2) { + if (map_key.empty()) { + // An absent map key is treated as the default. + const google::protobuf::Field* key_field = + FindFieldByNumber(*field_type, 1); + if (key_field == nullptr) { + // The Type info for this map entry is incorrect. It should always + // have a field named "key" and with field number 1. + return util::InternalError("Invalid map entry."); + } + ASSIGN_OR_RETURN(map_key, MapKeyDefaultValueAsString(*key_field)); + } + RETURN_IF_ERROR(RenderField(map_entry_field, map_key, ow)); + } else { + // The Type info for this map entry is incorrect. It should contain + // exactly two fields with field number 1 and 2. + return util::InternalError("Invalid map entry."); + } + } + stream_->PopLimit(old_limit); + } while ((tag_to_return = stream_->ReadTag()) == list_tag); + return tag_to_return; +} + +util::Status ProtoStreamObjectSource::RenderPacked( + const google::protobuf::Field* field, ObjectWriter* ow) const { + uint32_t length; + stream_->ReadVarint32(&length); + int old_limit = stream_->PushLimit(length); + while (stream_->BytesUntilLimit() > 0) { + RETURN_IF_ERROR(RenderField(field, StringPiece(), ow)); + } + stream_->PopLimit(old_limit); + return util::Status(); +} + +util::Status ProtoStreamObjectSource::RenderTimestamp( + const ProtoStreamObjectSource* os, const google::protobuf::Type& type, + StringPiece field_name, ObjectWriter* ow) { + std::pair<int64_t, int32_t> p = os->ReadSecondsAndNanos(type); + int64_t seconds = p.first; + int32_t nanos = p.second; + if (seconds > kTimestampMaxSeconds || seconds < kTimestampMinSeconds) { + return util::InternalError(StrCat( + "Timestamp seconds exceeds limit for field: ", field_name)); + } + + if (nanos < 0 || nanos >= kNanosPerSecond) { + return util::InternalError( + StrCat("Timestamp nanos exceeds limit for field: ", field_name)); + } + + ow->RenderString(field_name, + ::google::protobuf::internal::FormatTime(seconds, nanos)); + + return util::Status(); +} + +util::Status ProtoStreamObjectSource::RenderDuration( + const ProtoStreamObjectSource* os, const google::protobuf::Type& type, + StringPiece field_name, ObjectWriter* ow) { + std::pair<int64_t, int32_t> p = os->ReadSecondsAndNanos(type); + int64_t seconds = p.first; + int32_t nanos = p.second; + if (seconds > kDurationMaxSeconds || seconds < kDurationMinSeconds) { + return util::InternalError( + StrCat("Duration seconds exceeds limit for field: ", field_name)); + } + + if (nanos <= -kNanosPerSecond || nanos >= kNanosPerSecond) { + return util::InternalError( + StrCat("Duration nanos exceeds limit for field: ", field_name)); + } + + std::string sign = ""; + if (seconds < 0) { + if (nanos > 0) { + return util::InternalError( + StrCat("Duration nanos is non-negative, but seconds is " + "negative for field: ", + field_name)); + } + sign = "-"; + seconds = -seconds; + nanos = -nanos; + } else if (seconds == 0 && nanos < 0) { + sign = "-"; + nanos = -nanos; + } + std::string formatted_duration = StringPrintf( + "%s%lld%ss", sign.c_str(), static_cast<long long>(seconds), // NOLINT + FormatNanos( + nanos, + false + ) + .c_str()); + ow->RenderString(field_name, formatted_duration); + return util::Status(); +} + +util::Status ProtoStreamObjectSource::RenderDouble( + const ProtoStreamObjectSource* os, const google::protobuf::Type& /*type*/, + StringPiece field_name, ObjectWriter* ow) { + uint32_t tag = os->stream_->ReadTag(); + uint64_t buffer64 = 0; // default value of Double wrapper value + if (tag != 0) { + os->stream_->ReadLittleEndian64(&buffer64); + os->stream_->ReadTag(); + } + ow->RenderDouble(field_name, bit_cast<double>(buffer64)); + return util::Status(); +} + +util::Status ProtoStreamObjectSource::RenderFloat( + const ProtoStreamObjectSource* os, const google::protobuf::Type& /*type*/, + StringPiece field_name, ObjectWriter* ow) { + uint32_t tag = os->stream_->ReadTag(); + uint32_t buffer32 = 0; // default value of Float wrapper value + if (tag != 0) { + os->stream_->ReadLittleEndian32(&buffer32); + os->stream_->ReadTag(); + } + ow->RenderFloat(field_name, bit_cast<float>(buffer32)); + return util::Status(); +} + +util::Status ProtoStreamObjectSource::RenderInt64( + const ProtoStreamObjectSource* os, const google::protobuf::Type& /*type*/, + StringPiece field_name, ObjectWriter* ow) { + uint32_t tag = os->stream_->ReadTag(); + uint64_t buffer64 = 0; // default value of Int64 wrapper value + if (tag != 0) { + os->stream_->ReadVarint64(&buffer64); + os->stream_->ReadTag(); + } + ow->RenderInt64(field_name, bit_cast<int64_t>(buffer64)); + return util::Status(); +} + +util::Status ProtoStreamObjectSource::RenderUInt64( + const ProtoStreamObjectSource* os, const google::protobuf::Type& /*type*/, + StringPiece field_name, ObjectWriter* ow) { + uint32_t tag = os->stream_->ReadTag(); + uint64_t buffer64 = 0; // default value of UInt64 wrapper value + if (tag != 0) { + os->stream_->ReadVarint64(&buffer64); + os->stream_->ReadTag(); + } + ow->RenderUint64(field_name, bit_cast<uint64_t>(buffer64)); + return util::Status(); +} + +util::Status ProtoStreamObjectSource::RenderInt32( + const ProtoStreamObjectSource* os, const google::protobuf::Type& /*type*/, + StringPiece field_name, ObjectWriter* ow) { + uint32_t tag = os->stream_->ReadTag(); + uint32_t buffer32 = 0; // default value of Int32 wrapper value + if (tag != 0) { + os->stream_->ReadVarint32(&buffer32); + os->stream_->ReadTag(); + } + ow->RenderInt32(field_name, bit_cast<int32_t>(buffer32)); + return util::Status(); +} + +util::Status ProtoStreamObjectSource::RenderUInt32( + const ProtoStreamObjectSource* os, const google::protobuf::Type& /*type*/, + StringPiece field_name, ObjectWriter* ow) { + uint32_t tag = os->stream_->ReadTag(); + uint32_t buffer32 = 0; // default value of UInt32 wrapper value + if (tag != 0) { + os->stream_->ReadVarint32(&buffer32); + os->stream_->ReadTag(); + } + ow->RenderUint32(field_name, bit_cast<uint32_t>(buffer32)); + return util::Status(); +} + +util::Status ProtoStreamObjectSource::RenderBool( + const ProtoStreamObjectSource* os, const google::protobuf::Type& /*type*/, + StringPiece field_name, ObjectWriter* ow) { + uint32_t tag = os->stream_->ReadTag(); + uint64_t buffer64 = 0; // results in 'false' value as default, which is the + // default value of Bool wrapper + if (tag != 0) { + os->stream_->ReadVarint64(&buffer64); + os->stream_->ReadTag(); + } + ow->RenderBool(field_name, buffer64 != 0); + return util::Status(); +} + +util::Status ProtoStreamObjectSource::RenderString( + const ProtoStreamObjectSource* os, const google::protobuf::Type& /*type*/, + StringPiece field_name, ObjectWriter* ow) { + uint32_t tag = os->stream_->ReadTag(); + uint32_t buffer32; + std::string str; // default value of empty for String wrapper + if (tag != 0) { + os->stream_->ReadVarint32(&buffer32); // string size. + os->stream_->ReadString(&str, buffer32); + os->stream_->ReadTag(); + } + ow->RenderString(field_name, str); + return util::Status(); +} + +util::Status ProtoStreamObjectSource::RenderBytes( + const ProtoStreamObjectSource* os, const google::protobuf::Type& /*type*/, + StringPiece field_name, ObjectWriter* ow) { + uint32_t tag = os->stream_->ReadTag(); + uint32_t buffer32; + std::string str; + if (tag != 0) { + os->stream_->ReadVarint32(&buffer32); + os->stream_->ReadString(&str, buffer32); + os->stream_->ReadTag(); + } + ow->RenderBytes(field_name, str); + return util::Status(); +} + +util::Status ProtoStreamObjectSource::RenderStruct( + const ProtoStreamObjectSource* os, const google::protobuf::Type& type, + StringPiece field_name, ObjectWriter* ow) { + const google::protobuf::Field* field = nullptr; + uint32_t tag = os->stream_->ReadTag(); + ow->StartObject(field_name); + while (tag != 0) { + field = os->FindAndVerifyField(type, tag); + if (field == nullptr) { + WireFormat::SkipField(os->stream_, tag, nullptr); + tag = os->stream_->ReadTag(); + continue; + } + // google.protobuf.Struct has only one field that is a map. Hence we use + // RenderMap to render that field. + if (os->IsMap(*field)) { + ASSIGN_OR_RETURN(tag, os->RenderMap(field, field_name, tag, ow)); + } + } + ow->EndObject(); + return util::Status(); +} + +util::Status ProtoStreamObjectSource::RenderStructValue( + const ProtoStreamObjectSource* os, const google::protobuf::Type& type, + StringPiece field_name, ObjectWriter* ow) { + const google::protobuf::Field* field = nullptr; + for (uint32_t tag = os->stream_->ReadTag(); tag != 0; + tag = os->stream_->ReadTag()) { + field = os->FindAndVerifyField(type, tag); + if (field == nullptr) { + WireFormat::SkipField(os->stream_, tag, nullptr); + continue; + } + RETURN_IF_ERROR(os->RenderField(field, field_name, ow)); + } + return util::Status(); +} + +// TODO(skarvaje): Avoid code duplication of for loops and SkipField logic. +util::Status ProtoStreamObjectSource::RenderStructListValue( + const ProtoStreamObjectSource* os, const google::protobuf::Type& type, + StringPiece field_name, ObjectWriter* ow) { + uint32_t tag = os->stream_->ReadTag(); + + // Render empty list when we find empty ListValue message. + if (tag == 0) { + ow->StartList(field_name); + ow->EndList(); + return util::Status(); + } + + while (tag != 0) { + const google::protobuf::Field* field = os->FindAndVerifyField(type, tag); + if (field == nullptr) { + WireFormat::SkipField(os->stream_, tag, nullptr); + tag = os->stream_->ReadTag(); + continue; + } + ASSIGN_OR_RETURN(tag, os->RenderList(field, field_name, tag, ow)); + } + return util::Status(); +} + +util::Status ProtoStreamObjectSource::RenderAny( + const ProtoStreamObjectSource* os, const google::protobuf::Type& type, + StringPiece field_name, ObjectWriter* ow) { + // An Any is of the form { string type_url = 1; bytes value = 2; } + uint32_t tag; + std::string type_url; + std::string value; + + // First read out the type_url and value from the proto stream + for (tag = os->stream_->ReadTag(); tag != 0; tag = os->stream_->ReadTag()) { + const google::protobuf::Field* field = os->FindAndVerifyField(type, tag); + if (field == nullptr) { + WireFormat::SkipField(os->stream_, tag, nullptr); + continue; + } + // 'type_url' has field number of 1 and 'value' has field number 2 + // //google/protobuf/any.proto + if (field->number() == 1) { + // read type_url + uint32_t type_url_size; + os->stream_->ReadVarint32(&type_url_size); + os->stream_->ReadString(&type_url, type_url_size); + } else if (field->number() == 2) { + // read value + uint32_t value_size; + os->stream_->ReadVarint32(&value_size); + os->stream_->ReadString(&value, value_size); + } + } + + // If there is no value, we don't lookup the type, we just output it (if + // present). If both type and value are empty we output an empty object. + if (value.empty()) { + ow->StartObject(field_name); + if (!type_url.empty()) { + ow->RenderString("@type", type_url); + } + ow->EndObject(); + return util::Status(); + } + + // If there is a value but no type, we cannot render it, so report an error. + if (type_url.empty()) { + // TODO(sven): Add an external message once those are ready. + return util::InternalError("Invalid Any, the type_url is missing."); + } + + util::StatusOr<const google::protobuf::Type*> resolved_type = + os->typeinfo_->ResolveTypeUrl(type_url); + + if (!resolved_type.ok()) { + // Convert into an internal error, since this means the backend gave us + // an invalid response (missing or invalid type information). + return util::InternalError(resolved_type.status().message()); + } + // nested_type cannot be null at this time. + const google::protobuf::Type* nested_type = resolved_type.value(); + + io::ArrayInputStream zero_copy_stream(value.data(), value.size()); + io::CodedInputStream in_stream(&zero_copy_stream); + // We know the type so we can render it. Recursively parse the nested stream + // using a nested ProtoStreamObjectSource using our nested type information. + ProtoStreamObjectSource nested_os(&in_stream, os->typeinfo_, *nested_type, + os->render_options_); + + // We manually call start and end object here so we can inject the @type. + ow->StartObject(field_name); + ow->RenderString("@type", type_url); + util::Status result = + nested_os.WriteMessage(nested_os.type_, "value", 0, false, ow); + ow->EndObject(); + return result; +} + +util::Status ProtoStreamObjectSource::RenderFieldMask( + const ProtoStreamObjectSource* os, const google::protobuf::Type& type, + StringPiece field_name, ObjectWriter* ow) { + std::string combined; + uint32_t buffer32; + uint32_t paths_field_tag = 0; + for (uint32_t tag = os->stream_->ReadTag(); tag != 0; + tag = os->stream_->ReadTag()) { + if (paths_field_tag == 0) { + const google::protobuf::Field* field = os->FindAndVerifyField(type, tag); + if (field != nullptr && field->number() == 1 && + field->name() == "paths") { + paths_field_tag = tag; + } + } + if (paths_field_tag != tag) { + return util::InternalError("Invalid FieldMask, unexpected field."); + } + std::string str; + os->stream_->ReadVarint32(&buffer32); // string size. + os->stream_->ReadString(&str, buffer32); + if (!combined.empty()) { + combined.append(","); + } + combined.append(ConvertFieldMaskPath(str, &ToCamelCase)); + } + ow->RenderString(field_name, combined); + return util::Status(); +} + + +std::unordered_map<std::string, ProtoStreamObjectSource::TypeRenderer>* + ProtoStreamObjectSource::renderers_ = nullptr; +PROTOBUF_NAMESPACE_ID::internal::once_flag source_renderers_init_; + + +void ProtoStreamObjectSource::InitRendererMap() { + renderers_ = new std::unordered_map<std::string, + ProtoStreamObjectSource::TypeRenderer>(); + (*renderers_)["google.protobuf.Timestamp"] = + &ProtoStreamObjectSource::RenderTimestamp; + (*renderers_)["google.protobuf.Duration"] = + &ProtoStreamObjectSource::RenderDuration; + (*renderers_)["google.protobuf.DoubleValue"] = + &ProtoStreamObjectSource::RenderDouble; + (*renderers_)["google.protobuf.FloatValue"] = + &ProtoStreamObjectSource::RenderFloat; + (*renderers_)["google.protobuf.Int64Value"] = + &ProtoStreamObjectSource::RenderInt64; + (*renderers_)["google.protobuf.UInt64Value"] = + &ProtoStreamObjectSource::RenderUInt64; + (*renderers_)["google.protobuf.Int32Value"] = + &ProtoStreamObjectSource::RenderInt32; + (*renderers_)["google.protobuf.UInt32Value"] = + &ProtoStreamObjectSource::RenderUInt32; + (*renderers_)["google.protobuf.BoolValue"] = + &ProtoStreamObjectSource::RenderBool; + (*renderers_)["google.protobuf.StringValue"] = + &ProtoStreamObjectSource::RenderString; + (*renderers_)["google.protobuf.BytesValue"] = + &ProtoStreamObjectSource::RenderBytes; + (*renderers_)["google.protobuf.Any"] = &ProtoStreamObjectSource::RenderAny; + (*renderers_)["google.protobuf.Struct"] = + &ProtoStreamObjectSource::RenderStruct; + (*renderers_)["google.protobuf.Value"] = + &ProtoStreamObjectSource::RenderStructValue; + (*renderers_)["google.protobuf.ListValue"] = + &ProtoStreamObjectSource::RenderStructListValue; + (*renderers_)["google.protobuf.FieldMask"] = + &ProtoStreamObjectSource::RenderFieldMask; + ::google::protobuf::internal::OnShutdown(&DeleteRendererMap); +} + +void ProtoStreamObjectSource::DeleteRendererMap() { + delete ProtoStreamObjectSource::renderers_; + renderers_ = nullptr; +} + +// static +ProtoStreamObjectSource::TypeRenderer* +ProtoStreamObjectSource::FindTypeRenderer(const std::string& type_url) { + PROTOBUF_NAMESPACE_ID::internal::call_once(source_renderers_init_, + InitRendererMap); + return FindOrNull(*renderers_, type_url); +} + +util::Status ProtoStreamObjectSource::RenderField( + const google::protobuf::Field* field, StringPiece field_name, + ObjectWriter* ow) const { + // Short-circuit message types as it tends to call WriteMessage recursively + // and ends up using a lot of stack space. Keep the stack usage of this + // message small in order to preserve stack space and not crash. + if (field->kind() == google::protobuf::Field::TYPE_MESSAGE) { + uint32_t buffer32; + stream_->ReadVarint32(&buffer32); // message length + int old_limit = stream_->PushLimit(buffer32); + // Get the nested message type for this field. + const google::protobuf::Type* type = + typeinfo_->GetTypeByTypeUrl(field->type_url()); + if (type == nullptr) { + return util::InternalError( + StrCat("Invalid configuration. Could not find the type: ", + field->type_url())); + } + + // Short-circuit any special type rendering to save call-stack space. + const TypeRenderer* type_renderer = FindTypeRenderer(type->name()); + + RETURN_IF_ERROR(IncrementRecursionDepth(type->name(), field_name)); + if (type_renderer != nullptr) { + RETURN_IF_ERROR((*type_renderer)(this, *type, field_name, ow)); + } else { + RETURN_IF_ERROR(WriteMessage(*type, field_name, 0, true, ow)); + } + --recursion_depth_; + + if (!stream_->ConsumedEntireMessage()) { + return util::InvalidArgumentError( + "Nested protocol message not parsed in its entirety."); + } + stream_->PopLimit(old_limit); + } else { + // Render all other non-message types. + return RenderNonMessageField(field, field_name, ow); + } + return util::Status(); +} + +util::Status ProtoStreamObjectSource::RenderNonMessageField( + const google::protobuf::Field* field, StringPiece field_name, + ObjectWriter* ow) const { + // Temporary buffers of different types. + uint32_t buffer32 = 0; + uint64_t buffer64 = 0; + std::string strbuffer; + switch (field->kind()) { + case google::protobuf::Field::TYPE_BOOL: { + stream_->ReadVarint64(&buffer64); + ow->RenderBool(field_name, buffer64 != 0); + break; + } + case google::protobuf::Field::TYPE_INT32: { + stream_->ReadVarint32(&buffer32); + ow->RenderInt32(field_name, bit_cast<int32_t>(buffer32)); + break; + } + case google::protobuf::Field::TYPE_INT64: { + stream_->ReadVarint64(&buffer64); + ow->RenderInt64(field_name, bit_cast<int64_t>(buffer64)); + break; + } + case google::protobuf::Field::TYPE_UINT32: { + stream_->ReadVarint32(&buffer32); + ow->RenderUint32(field_name, bit_cast<uint32_t>(buffer32)); + break; + } + case google::protobuf::Field::TYPE_UINT64: { + stream_->ReadVarint64(&buffer64); + ow->RenderUint64(field_name, bit_cast<uint64_t>(buffer64)); + break; + } + case google::protobuf::Field::TYPE_SINT32: { + stream_->ReadVarint32(&buffer32); + ow->RenderInt32(field_name, WireFormatLite::ZigZagDecode32(buffer32)); + break; + } + case google::protobuf::Field::TYPE_SINT64: { + stream_->ReadVarint64(&buffer64); + ow->RenderInt64(field_name, WireFormatLite::ZigZagDecode64(buffer64)); + break; + } + case google::protobuf::Field::TYPE_SFIXED32: { + stream_->ReadLittleEndian32(&buffer32); + ow->RenderInt32(field_name, bit_cast<int32_t>(buffer32)); + break; + } + case google::protobuf::Field::TYPE_SFIXED64: { + stream_->ReadLittleEndian64(&buffer64); + ow->RenderInt64(field_name, bit_cast<int64_t>(buffer64)); + break; + } + case google::protobuf::Field::TYPE_FIXED32: { + stream_->ReadLittleEndian32(&buffer32); + ow->RenderUint32(field_name, bit_cast<uint32_t>(buffer32)); + break; + } + case google::protobuf::Field::TYPE_FIXED64: { + stream_->ReadLittleEndian64(&buffer64); + ow->RenderUint64(field_name, bit_cast<uint64_t>(buffer64)); + break; + } + case google::protobuf::Field::TYPE_FLOAT: { + stream_->ReadLittleEndian32(&buffer32); + ow->RenderFloat(field_name, bit_cast<float>(buffer32)); + break; + } + case google::protobuf::Field::TYPE_DOUBLE: { + stream_->ReadLittleEndian64(&buffer64); + ow->RenderDouble(field_name, bit_cast<double>(buffer64)); + break; + } + case google::protobuf::Field::TYPE_ENUM: { + stream_->ReadVarint32(&buffer32); + + // If the field represents an explicit NULL value, render null. + if (field->type_url() == kStructNullValueTypeUrl) { + ow->RenderNull(field_name); + break; + } + + // Get the nested enum type for this field. + // TODO(skarvaje): Avoid string manipulation. Find ways to speed this + // up. + const google::protobuf::Enum* en = + typeinfo_->GetEnumByTypeUrl(field->type_url()); + // Lookup the name of the enum, and render that. Unknown enum values + // are printed as integers. + if (en != nullptr) { + const google::protobuf::EnumValue* enum_value = + FindEnumValueByNumber(*en, buffer32); + if (enum_value != nullptr) { + if (render_options_.use_ints_for_enums) { + ow->RenderInt32(field_name, buffer32); + } else if (render_options_.use_lower_camel_for_enums) { + ow->RenderString(field_name, + EnumValueNameToLowerCamelCase(enum_value->name())); + } else { + ow->RenderString(field_name, enum_value->name()); + } + } else { + ow->RenderInt32(field_name, buffer32); + } + } else { + ow->RenderInt32(field_name, buffer32); + } + break; + } + case google::protobuf::Field::TYPE_STRING: { + stream_->ReadVarint32(&buffer32); // string size. + stream_->ReadString(&strbuffer, buffer32); + ow->RenderString(field_name, strbuffer); + break; + } + case google::protobuf::Field::TYPE_BYTES: { + stream_->ReadVarint32(&buffer32); // bytes size. + stream_->ReadString(&strbuffer, buffer32); + ow->RenderBytes(field_name, strbuffer); + break; + } + default: + break; + } + return util::Status(); +} + +// TODO(skarvaje): Fix this to avoid code duplication. +const std::string ProtoStreamObjectSource::ReadFieldValueAsString( + const google::protobuf::Field& field) const { + std::string result; + switch (field.kind()) { + case google::protobuf::Field::TYPE_BOOL: { + uint64_t buffer64; + stream_->ReadVarint64(&buffer64); + result = buffer64 != 0 ? "true" : "false"; + break; + } + case google::protobuf::Field::TYPE_INT32: { + uint32_t buffer32; + stream_->ReadVarint32(&buffer32); + result = StrCat(bit_cast<int32_t>(buffer32)); + break; + } + case google::protobuf::Field::TYPE_INT64: { + uint64_t buffer64; + stream_->ReadVarint64(&buffer64); + result = StrCat(bit_cast<int64_t>(buffer64)); + break; + } + case google::protobuf::Field::TYPE_UINT32: { + uint32_t buffer32; + stream_->ReadVarint32(&buffer32); + result = StrCat(bit_cast<uint32_t>(buffer32)); + break; + } + case google::protobuf::Field::TYPE_UINT64: { + uint64_t buffer64; + stream_->ReadVarint64(&buffer64); + result = StrCat(bit_cast<uint64_t>(buffer64)); + break; + } + case google::protobuf::Field::TYPE_SINT32: { + uint32_t buffer32; + stream_->ReadVarint32(&buffer32); + result = StrCat(WireFormatLite::ZigZagDecode32(buffer32)); + break; + } + case google::protobuf::Field::TYPE_SINT64: { + uint64_t buffer64; + stream_->ReadVarint64(&buffer64); + result = StrCat(WireFormatLite::ZigZagDecode64(buffer64)); + break; + } + case google::protobuf::Field::TYPE_SFIXED32: { + uint32_t buffer32; + stream_->ReadLittleEndian32(&buffer32); + result = StrCat(bit_cast<int32_t>(buffer32)); + break; + } + case google::protobuf::Field::TYPE_SFIXED64: { + uint64_t buffer64; + stream_->ReadLittleEndian64(&buffer64); + result = StrCat(bit_cast<int64_t>(buffer64)); + break; + } + case google::protobuf::Field::TYPE_FIXED32: { + uint32_t buffer32; + stream_->ReadLittleEndian32(&buffer32); + result = StrCat(bit_cast<uint32_t>(buffer32)); + break; + } + case google::protobuf::Field::TYPE_FIXED64: { + uint64_t buffer64; + stream_->ReadLittleEndian64(&buffer64); + result = StrCat(bit_cast<uint64_t>(buffer64)); + break; + } + case google::protobuf::Field::TYPE_FLOAT: { + uint32_t buffer32; + stream_->ReadLittleEndian32(&buffer32); + result = SimpleFtoa(bit_cast<float>(buffer32)); + break; + } + case google::protobuf::Field::TYPE_DOUBLE: { + uint64_t buffer64; + stream_->ReadLittleEndian64(&buffer64); + result = SimpleDtoa(bit_cast<double>(buffer64)); + break; + } + case google::protobuf::Field::TYPE_ENUM: { + uint32_t buffer32; + stream_->ReadVarint32(&buffer32); + // Get the nested enum type for this field. + // TODO(skarvaje): Avoid string manipulation. Find ways to speed this + // up. + const google::protobuf::Enum* en = + typeinfo_->GetEnumByTypeUrl(field.type_url()); + // Lookup the name of the enum, and render that. Skips unknown enums. + if (en != nullptr) { + const google::protobuf::EnumValue* enum_value = + FindEnumValueByNumber(*en, buffer32); + if (enum_value != nullptr) { + result = enum_value->name(); + } + } + break; + } + case google::protobuf::Field::TYPE_STRING: { + uint32_t buffer32; + stream_->ReadVarint32(&buffer32); // string size. + stream_->ReadString(&result, buffer32); + break; + } + case google::protobuf::Field::TYPE_BYTES: { + uint32_t buffer32; + stream_->ReadVarint32(&buffer32); // bytes size. + stream_->ReadString(&result, buffer32); + break; + } + default: + break; + } + return result; +} + +// Field is a map if it is a repeated message and it has an option "map_type". +// TODO(skarvaje): Consider pre-computing the IsMap() into Field directly. +bool ProtoStreamObjectSource::IsMap( + const google::protobuf::Field& field) const { + const google::protobuf::Type* field_type = + typeinfo_->GetTypeByTypeUrl(field.type_url()); + return field.kind() == google::protobuf::Field::TYPE_MESSAGE && + util::converter::IsMap(field, *field_type); +} + +std::pair<int64_t, int32_t> ProtoStreamObjectSource::ReadSecondsAndNanos( + const google::protobuf::Type& type) const { + uint64_t seconds = 0; + uint32_t nanos = 0; + uint32_t tag = 0; + int64_t signed_seconds = 0; + int32_t signed_nanos = 0; + + for (tag = stream_->ReadTag(); tag != 0; tag = stream_->ReadTag()) { + const google::protobuf::Field* field = FindAndVerifyField(type, tag); + if (field == nullptr) { + WireFormat::SkipField(stream_, tag, nullptr); + continue; + } + // 'seconds' has field number of 1 and 'nanos' has field number 2 + // //google/protobuf/timestamp.proto & duration.proto + if (field->number() == 1) { + // read seconds + stream_->ReadVarint64(&seconds); + signed_seconds = bit_cast<int64_t>(seconds); + } else if (field->number() == 2) { + // read nanos + stream_->ReadVarint32(&nanos); + signed_nanos = bit_cast<int32_t>(nanos); + } + } + return std::pair<int64_t, int32_t>(signed_seconds, signed_nanos); +} + +util::Status ProtoStreamObjectSource::IncrementRecursionDepth( + StringPiece type_name, StringPiece field_name) const { + if (++recursion_depth_ > max_recursion_depth_) { + return util::InvalidArgumentError( + StrCat("Message too deep. Max recursion depth reached for type '", + type_name, "', field '", field_name, "'")); + } + return util::Status(); +} + +namespace { +// TODO(skarvaje): Speed this up by not doing a linear scan. +const google::protobuf::Field* FindFieldByNumber( + const google::protobuf::Type& type, int number) { + for (int i = 0; i < type.fields_size(); ++i) { + if (type.fields(i).number() == number) { + return &type.fields(i); + } + } + return nullptr; +} + +// TODO(skarvaje): Replace FieldDescriptor by implementing IsTypePackable() +// using tech Field. +bool IsPackable(const google::protobuf::Field& field) { + return field.cardinality() == google::protobuf::Field::CARDINALITY_REPEATED && + FieldDescriptor::IsTypePackable( + static_cast<FieldDescriptor::Type>(field.kind())); +} + +// TODO(skarvaje): Speed this up by not doing a linear scan. +const google::protobuf::EnumValue* FindEnumValueByNumber( + const google::protobuf::Enum& tech_enum, int number) { + for (int i = 0; i < tech_enum.enumvalue_size(); ++i) { + const google::protobuf::EnumValue& ev = tech_enum.enumvalue(i); + if (ev.number() == number) { + return &ev; + } + } + return nullptr; +} + +// TODO(skarvaje): Look into optimizing this by not doing computation on +// double. +const std::string FormatNanos(uint32_t nanos, bool with_trailing_zeros) { + if (nanos == 0) { + return with_trailing_zeros ? ".000" : ""; + } + + const int precision = (nanos % 1000 != 0) ? 9 + : (nanos % 1000000 != 0) ? 6 + : 3; + std::string formatted = StringPrintf( + "%.*f", precision, static_cast<double>(nanos) / kNanosPerSecond); + // remove the leading 0 before decimal. + return formatted.substr(1); +} +} // namespace + +} // namespace converter +} // namespace util +} // namespace protobuf +} // namespace google diff --git a/toolkit/components/protobuf/src/google/protobuf/util/internal/protostream_objectsource.h b/toolkit/components/protobuf/src/google/protobuf/util/internal/protostream_objectsource.h new file mode 100644 index 0000000000..8ed2ca9bb4 --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/util/internal/protostream_objectsource.h @@ -0,0 +1,329 @@ +// 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. + +#ifndef GOOGLE_PROTOBUF_UTIL_INTERNAL_PROTOSTREAM_OBJECTSOURCE_H__ +#define GOOGLE_PROTOBUF_UTIL_INTERNAL_PROTOSTREAM_OBJECTSOURCE_H__ + +#include <cstdint> +#include <functional> +#include <string> +#include <unordered_map> + +#include <google/protobuf/stubs/status.h> + +#include <google/protobuf/stubs/common.h> +#include <google/protobuf/type.pb.h> +#include <google/protobuf/stubs/statusor.h> +#include <google/protobuf/stubs/strutil.h> +#include <google/protobuf/util/internal/object_source.h> +#include <google/protobuf/util/internal/object_writer.h> +#include <google/protobuf/util/internal/type_info.h> +#include <google/protobuf/util/type_resolver.h> +#include <google/protobuf/stubs/hash.h> +#include <google/protobuf/stubs/status.h> + + +// Must be included last. +#include <google/protobuf/port_def.inc> + +namespace google { +namespace protobuf { +namespace util { +namespace converter { + +class TypeInfo; + +// An ObjectSource that can parse a stream of bytes as a protocol buffer. +// Its WriteTo() method can be given an ObjectWriter. +// This implementation uses a google.protobuf.Type for tag and name lookup. +// The field names are converted into lower camel-case when writing to the +// ObjectWriter. +// +// Sample usage: (suppose input is: string proto) +// ArrayInputStream arr_stream(proto.data(), proto.size()); +// CodedInputStream in_stream(&arr_stream); +// ProtoStreamObjectSource os(&in_stream, /*ServiceTypeInfo*/ typeinfo, +// <your message google::protobuf::Type>); +// +// Status status = os.WriteTo(<some ObjectWriter>); +class PROTOBUF_EXPORT ProtoStreamObjectSource : public ObjectSource { + public: + + struct RenderOptions { + RenderOptions() = default; + RenderOptions(const RenderOptions&) = default; + + // Sets whether or not to use lowerCamelCase casing for enum values. If set + // to false, enum values are output without any case conversions. + // + // For example, if we have an enum: + // enum Type { + // ACTION_AND_ADVENTURE = 1; + // } + // Type type = 20; + // + // And this option is set to true. Then the rendered "type" field will have + // the string "actionAndAdventure". + // { + // ... + // "type": "actionAndAdventure", + // ... + // } + // + // If set to false, the rendered "type" field will have the string + // "ACTION_AND_ADVENTURE". + // { + // ... + // "type": "ACTION_AND_ADVENTURE", + // ... + // } + bool use_lower_camel_for_enums = false; + + // Sets whether to always output enums as ints, by default this is off, and + // enums are rendered as strings. + bool use_ints_for_enums = false; + + // Whether to preserve proto field names + bool preserve_proto_field_names = false; + + }; + + ProtoStreamObjectSource(io::CodedInputStream* stream, + TypeResolver* type_resolver, + const google::protobuf::Type& type) + : ProtoStreamObjectSource(stream, type_resolver, type, RenderOptions()) {} + ProtoStreamObjectSource(io::CodedInputStream* stream, + TypeResolver* type_resolver, + const google::protobuf::Type& type, + const RenderOptions& render_options); + + ~ProtoStreamObjectSource() override; + + util::Status NamedWriteTo(StringPiece name, + ObjectWriter* ow) const override; + + // Sets the max recursion depth of proto message to be deserialized. Proto + // messages over this depth will fail to be deserialized. + // Default value is 64. + void set_max_recursion_depth(int max_depth) { + max_recursion_depth_ = max_depth; + } + + protected: + // Writes a proto2 Message to the ObjectWriter. When the given end_tag is + // found this method will complete, allowing it to be used for parsing both + // nested messages (end with 0) and nested groups (end with group end tag). + // The include_start_and_end parameter allows this method to be called when + // already inside of an object, and skip calling StartObject and EndObject. + virtual util::Status WriteMessage(const google::protobuf::Type& type, + StringPiece name, + const uint32_t end_tag, + bool include_start_and_end, + ObjectWriter* ow) const; + + // Renders a repeating field (packed or unpacked). Returns the next tag after + // reading all sequential repeating elements. The caller should use this tag + // before reading more tags from the stream. + virtual util::StatusOr<uint32_t> RenderList( + const google::protobuf::Field* field, StringPiece name, + uint32_t list_tag, ObjectWriter* ow) const; + + // Looks up a field and verify its consistency with wire type in tag. + const google::protobuf::Field* FindAndVerifyField( + const google::protobuf::Type& type, uint32_t tag) const; + + // Renders a field value to the ObjectWriter. + virtual util::Status RenderField(const google::protobuf::Field* field, + StringPiece field_name, + ObjectWriter* ow) const; + + // Reads field value according to Field spec in 'field' and returns the read + // value as string. This only works for primitive datatypes (no message + // types). + const std::string ReadFieldValueAsString( + const google::protobuf::Field& field) const; + + + // Returns the input stream. + io::CodedInputStream* stream() const { return stream_; } + + private: + ProtoStreamObjectSource(io::CodedInputStream* stream, + const TypeInfo* typeinfo, + const google::protobuf::Type& type, + const RenderOptions& render_options); + // Function that renders a well known type with a modified behavior. + typedef util::Status (*TypeRenderer)(const ProtoStreamObjectSource*, + const google::protobuf::Type&, + StringPiece, ObjectWriter*); + + // TODO(skarvaje): Mark these methods as non-const as they modify internal + // state (stream_). + // + // Renders a NWP map. + // Returns the next tag after reading all map entries. The caller should use + // this tag before reading more tags from the stream. + util::StatusOr<uint32_t> RenderMap(const google::protobuf::Field* field, + StringPiece name, uint32_t list_tag, + ObjectWriter* ow) const; + + // Renders a packed repeating field. A packed field is stored as: + // {tag length item1 item2 item3} instead of the less efficient + // {tag item1 tag item2 tag item3}. + util::Status RenderPacked(const google::protobuf::Field* field, + ObjectWriter* ow) const; + + // Renders a google.protobuf.Timestamp value to ObjectWriter + static util::Status RenderTimestamp(const ProtoStreamObjectSource* os, + const google::protobuf::Type& type, + StringPiece name, ObjectWriter* ow); + + // Renders a google.protobuf.Duration value to ObjectWriter + static util::Status RenderDuration(const ProtoStreamObjectSource* os, + const google::protobuf::Type& type, + StringPiece name, ObjectWriter* ow); + + // Following RenderTYPE functions render well known types in + // google/protobuf/wrappers.proto corresponding to TYPE. + static util::Status RenderDouble(const ProtoStreamObjectSource* os, + const google::protobuf::Type& type, + StringPiece name, ObjectWriter* ow); + static util::Status RenderFloat(const ProtoStreamObjectSource* os, + const google::protobuf::Type& type, + StringPiece name, ObjectWriter* ow); + static util::Status RenderInt64(const ProtoStreamObjectSource* os, + const google::protobuf::Type& type, + StringPiece name, ObjectWriter* ow); + static util::Status RenderUInt64(const ProtoStreamObjectSource* os, + const google::protobuf::Type& type, + StringPiece name, ObjectWriter* ow); + static util::Status RenderInt32(const ProtoStreamObjectSource* os, + const google::protobuf::Type& type, + StringPiece name, ObjectWriter* ow); + static util::Status RenderUInt32(const ProtoStreamObjectSource* os, + const google::protobuf::Type& type, + StringPiece name, ObjectWriter* ow); + static util::Status RenderBool(const ProtoStreamObjectSource* os, + const google::protobuf::Type& type, + StringPiece name, ObjectWriter* ow); + static util::Status RenderString(const ProtoStreamObjectSource* os, + const google::protobuf::Type& type, + StringPiece name, ObjectWriter* ow); + static util::Status RenderBytes(const ProtoStreamObjectSource* os, + const google::protobuf::Type& type, + StringPiece name, ObjectWriter* ow); + + // Renders a google.protobuf.Struct to ObjectWriter. + static util::Status RenderStruct(const ProtoStreamObjectSource* os, + const google::protobuf::Type& type, + StringPiece name, ObjectWriter* ow); + + // Helper to render google.protobuf.Struct's Value fields to ObjectWriter. + static util::Status RenderStructValue(const ProtoStreamObjectSource* os, + const google::protobuf::Type& type, + StringPiece name, + ObjectWriter* ow); + + // Helper to render google.protobuf.Struct's ListValue fields to ObjectWriter. + static util::Status RenderStructListValue(const ProtoStreamObjectSource* os, + const google::protobuf::Type& type, + StringPiece name, + ObjectWriter* ow); + + // Render the "Any" type. + static util::Status RenderAny(const ProtoStreamObjectSource* os, + const google::protobuf::Type& type, + StringPiece name, ObjectWriter* ow); + + // Render the "FieldMask" type. + static util::Status RenderFieldMask(const ProtoStreamObjectSource* os, + const google::protobuf::Type& type, + StringPiece name, ObjectWriter* ow); + + static std::unordered_map<std::string, TypeRenderer>* renderers_; + static void InitRendererMap(); + static void DeleteRendererMap(); + static TypeRenderer* FindTypeRenderer(const std::string& type_url); + + // Same as above but renders all non-message field types. Callers don't call + // this function directly. They just use RenderField. + util::Status RenderNonMessageField(const google::protobuf::Field* field, + StringPiece field_name, + ObjectWriter* ow) const; + + + // Utility function to detect proto maps. The 'field' MUST be repeated. + bool IsMap(const google::protobuf::Field& field) const; + + // Utility to read int64 and int32 values from a message type in stream_. + // Used for reading google.protobuf.Timestamp and Duration messages. + std::pair<int64_t, int32_t> ReadSecondsAndNanos( + const google::protobuf::Type& type) const; + + // Helper function to check recursion depth and increment it. It will return + // OkStatus() if the current depth is allowed. Otherwise an error is returned. + // type_name and field_name are used for error reporting. + util::Status IncrementRecursionDepth(StringPiece type_name, + StringPiece field_name) const; + + // Input stream to read from. Ownership rests with the caller. + mutable io::CodedInputStream* stream_; + + // Type information for all the types used in the descriptor. Used to find + // google::protobuf::Type of nested messages/enums. + const TypeInfo* typeinfo_; + + // Whether this class owns the typeinfo_ object. If true the typeinfo_ object + // should be deleted in the destructor. + bool own_typeinfo_; + + // google::protobuf::Type of the message source. + const google::protobuf::Type& type_; + + + const RenderOptions render_options_; + + // Tracks current recursion depth. + mutable int recursion_depth_; + + // Maximum allowed recursion depth. + int max_recursion_depth_; + + GOOGLE_DISALLOW_IMPLICIT_CONSTRUCTORS(ProtoStreamObjectSource); +}; + +} // namespace converter +} // namespace util +} // namespace protobuf +} // namespace google + +#include <google/protobuf/port_undef.inc> + +#endif // GOOGLE_PROTOBUF_UTIL_INTERNAL_PROTOSTREAM_OBJECTSOURCE_H__ diff --git a/toolkit/components/protobuf/src/google/protobuf/util/internal/protostream_objectwriter.cc b/toolkit/components/protobuf/src/google/protobuf/util/internal/protostream_objectwriter.cc new file mode 100644 index 0000000000..ecb219e06e --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/util/internal/protostream_objectwriter.cc @@ -0,0 +1,1401 @@ +// 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. + +#include <google/protobuf/util/internal/protostream_objectwriter.h> + +#include <cstdint> +#include <functional> +#include <stack> +#include <unordered_map> +#include <unordered_set> + +#include <google/protobuf/stubs/once.h> +#include <google/protobuf/wire_format_lite.h> +#include <google/protobuf/stubs/strutil.h> +#include <google/protobuf/stubs/status.h> +#include <google/protobuf/stubs/statusor.h> +#include <google/protobuf/stubs/time.h> +#include <google/protobuf/util/internal/constants.h> +#include <google/protobuf/util/internal/field_mask_utility.h> +#include <google/protobuf/util/internal/object_location_tracker.h> +#include <google/protobuf/util/internal/utility.h> +#include <google/protobuf/stubs/map_util.h> + + +// Must be included last. +#include <google/protobuf/port_def.inc> + +namespace google { +namespace protobuf { +namespace util { +namespace converter { + +using util::Status; +using ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite; +using std::placeholders::_1; + + +ProtoStreamObjectWriter::ProtoStreamObjectWriter( + TypeResolver* type_resolver, const google::protobuf::Type& type, + strings::ByteSink* output, ErrorListener* listener, + const ProtoStreamObjectWriter::Options& options) + : ProtoWriter(type_resolver, type, output, listener), + master_type_(type), + current_(nullptr), + options_(options) { + set_ignore_unknown_fields(options_.ignore_unknown_fields); + set_ignore_unknown_enum_values(options_.ignore_unknown_enum_values); + set_use_lower_camel_for_enums(options_.use_lower_camel_for_enums); + set_case_insensitive_enum_parsing(options_.case_insensitive_enum_parsing); + set_use_json_name_in_missing_fields(options.use_json_name_in_missing_fields); +} + +ProtoStreamObjectWriter::ProtoStreamObjectWriter( + const TypeInfo* typeinfo, const google::protobuf::Type& type, + strings::ByteSink* output, ErrorListener* listener, + const ProtoStreamObjectWriter::Options& options) + : ProtoWriter(typeinfo, type, output, listener), + master_type_(type), + current_(nullptr), + options_(options) { + set_ignore_unknown_fields(options_.ignore_unknown_fields); + set_use_lower_camel_for_enums(options.use_lower_camel_for_enums); + set_case_insensitive_enum_parsing(options_.case_insensitive_enum_parsing); + set_use_json_name_in_missing_fields(options.use_json_name_in_missing_fields); +} + +ProtoStreamObjectWriter::ProtoStreamObjectWriter( + const TypeInfo* typeinfo, const google::protobuf::Type& type, + strings::ByteSink* output, ErrorListener* listener) + : ProtoWriter(typeinfo, type, output, listener), + master_type_(type), + current_(nullptr), + options_(ProtoStreamObjectWriter::Options::Defaults()) {} + +ProtoStreamObjectWriter::~ProtoStreamObjectWriter() { + if (current_ == nullptr) return; + // Cleanup explicitly in order to avoid destructor stack overflow when input + // is deeply nested. + // Cast to BaseElement to avoid doing additional checks (like missing fields) + // during pop(). + std::unique_ptr<BaseElement> element( + static_cast<BaseElement*>(current_.get())->pop<BaseElement>()); + while (element != nullptr) { + element.reset(element->pop<BaseElement>()); + } +} + +namespace { +// Utility method to split a string representation of Timestamp or Duration and +// return the parts. +void SplitSecondsAndNanos(StringPiece input, StringPiece* seconds, + StringPiece* nanos) { + size_t idx = input.rfind('.'); + if (idx != std::string::npos) { + *seconds = input.substr(0, idx); + *nanos = input.substr(idx + 1); + } else { + *seconds = input; + *nanos = StringPiece(); + } +} + +Status GetNanosFromStringPiece(StringPiece s_nanos, + const char* parse_failure_message, + const char* exceeded_limit_message, + int32_t* nanos) { + *nanos = 0; + + // Count the number of leading 0s and consume them. + int num_leading_zeros = 0; + while (s_nanos.Consume("0")) { + num_leading_zeros++; + } + int32_t i_nanos = 0; + // 's_nanos' contains fractional seconds -- i.e. 'nanos' is equal to + // "0." + s_nanos.ToString() seconds. An int32_t is used for the + // conversion to 'nanos', rather than a double, so that there is no + // loss of precision. + if (!s_nanos.empty() && !safe_strto32(s_nanos, &i_nanos)) { + return util::InvalidArgumentError(parse_failure_message); + } + if (i_nanos > kNanosPerSecond || i_nanos < 0) { + return util::InvalidArgumentError(exceeded_limit_message); + } + // s_nanos should only have digits. No whitespace. + if (s_nanos.find_first_not_of("0123456789") != StringPiece::npos) { + return util::InvalidArgumentError(parse_failure_message); + } + + if (i_nanos > 0) { + // 'scale' is the number of digits to the right of the decimal + // point in "0." + s_nanos.ToString() + int32_t scale = num_leading_zeros + s_nanos.size(); + // 'conversion' converts i_nanos into nanoseconds. + // conversion = kNanosPerSecond / static_cast<int32_t>(std::pow(10, scale)) + // For efficiency, we precompute the conversion factor. + int32_t conversion = 0; + switch (scale) { + case 1: + conversion = 100000000; + break; + case 2: + conversion = 10000000; + break; + case 3: + conversion = 1000000; + break; + case 4: + conversion = 100000; + break; + case 5: + conversion = 10000; + break; + case 6: + conversion = 1000; + break; + case 7: + conversion = 100; + break; + case 8: + conversion = 10; + break; + case 9: + conversion = 1; + break; + default: + return util::InvalidArgumentError(exceeded_limit_message); + } + *nanos = i_nanos * conversion; + } + + return Status(); +} + +} // namespace + +ProtoStreamObjectWriter::AnyWriter::AnyWriter(ProtoStreamObjectWriter* parent) + : parent_(parent), + ow_(), + invalid_(false), + data_(), + output_(&data_), + depth_(0), + is_well_known_type_(false), + well_known_type_render_(nullptr) {} + +ProtoStreamObjectWriter::AnyWriter::~AnyWriter() {} + +void ProtoStreamObjectWriter::AnyWriter::StartObject(StringPiece name) { + ++depth_; + // If an object writer is absent, that means we have not called StartAny() + // before reaching here, which happens when we have data before the "@type" + // field. + if (ow_ == nullptr) { + // Save data before the "@type" field for later replay. + uninterpreted_events_.push_back(Event(Event::START_OBJECT, name)); + } else if (is_well_known_type_ && depth_ == 1) { + // For well-known types, the only other field besides "@type" should be a + // "value" field. + if (name != "value" && !invalid_) { + parent_->InvalidValue("Any", + "Expect a \"value\" field for well-known types."); + invalid_ = true; + } + ow_->StartObject(""); + } else { + // Forward the call to the child writer if: + // 1. the type is not a well-known type. + // 2. or, we are in a nested Any, Struct, or Value object. + ow_->StartObject(name); + } +} + +bool ProtoStreamObjectWriter::AnyWriter::EndObject() { + --depth_; + if (ow_ == nullptr) { + if (depth_ >= 0) { + // Save data before the "@type" field for later replay. + uninterpreted_events_.push_back(Event(Event::END_OBJECT)); + } + } else if (depth_ >= 0 || !is_well_known_type_) { + // As long as depth_ >= 0, we know we haven't reached the end of Any. + // Propagate these EndObject() calls to the contained ow_. For regular + // message types, we propagate the end of Any as well. + ow_->EndObject(); + } + // A negative depth_ implies that we have reached the end of Any + // object. Now we write out its contents. + if (depth_ < 0) { + WriteAny(); + return false; + } + return true; +} + +void ProtoStreamObjectWriter::AnyWriter::StartList(StringPiece name) { + ++depth_; + if (ow_ == nullptr) { + // Save data before the "@type" field for later replay. + uninterpreted_events_.push_back(Event(Event::START_LIST, name)); + } else if (is_well_known_type_ && depth_ == 1) { + if (name != "value" && !invalid_) { + parent_->InvalidValue("Any", + "Expect a \"value\" field for well-known types."); + invalid_ = true; + } + ow_->StartList(""); + } else { + ow_->StartList(name); + } +} + +void ProtoStreamObjectWriter::AnyWriter::EndList() { + --depth_; + if (depth_ < 0) { + GOOGLE_LOG(DFATAL) << "Mismatched EndList found, should not be possible"; + depth_ = 0; + } + if (ow_ == nullptr) { + // Save data before the "@type" field for later replay. + uninterpreted_events_.push_back(Event(Event::END_LIST)); + } else { + ow_->EndList(); + } +} + +void ProtoStreamObjectWriter::AnyWriter::RenderDataPiece( + StringPiece name, const DataPiece& value) { + // Start an Any only at depth_ 0. Other RenderDataPiece calls with "@type" + // should go to the contained ow_ as they indicate nested Anys. + if (depth_ == 0 && ow_ == nullptr && name == "@type") { + StartAny(value); + } else if (ow_ == nullptr) { + // Save data before the "@type" field. + uninterpreted_events_.push_back(Event(name, value)); + } else if (depth_ == 0 && is_well_known_type_) { + if (name != "value" && !invalid_) { + parent_->InvalidValue("Any", + "Expect a \"value\" field for well-known types."); + invalid_ = true; + } + if (well_known_type_render_ == nullptr) { + // Only Any and Struct don't have a special type render but both of + // them expect a JSON object (i.e., a StartObject() call). + if (value.type() != DataPiece::TYPE_NULL && !invalid_) { + parent_->InvalidValue("Any", "Expect a JSON object."); + invalid_ = true; + } + } else { + ow_->ProtoWriter::StartObject(""); + Status status = (*well_known_type_render_)(ow_.get(), value); + if (!status.ok()) ow_->InvalidValue("Any", status.message()); + ow_->ProtoWriter::EndObject(); + } + } else { + ow_->RenderDataPiece(name, value); + } +} + +void ProtoStreamObjectWriter::AnyWriter::StartAny(const DataPiece& value) { + // Figure out the type url. This is a copy-paste from WriteString but we also + // need the value, so we can't just call through to that. + if (value.type() == DataPiece::TYPE_STRING) { + type_url_ = std::string(value.str()); + } else { + util::StatusOr<std::string> s = value.ToString(); + if (!s.ok()) { + parent_->InvalidValue("String", s.status().message()); + invalid_ = true; + return; + } + type_url_ = s.value(); + } + // Resolve the type url, and report an error if we failed to resolve it. + util::StatusOr<const google::protobuf::Type*> resolved_type = + parent_->typeinfo()->ResolveTypeUrl(type_url_); + if (!resolved_type.ok()) { + parent_->InvalidValue("Any", resolved_type.status().message()); + invalid_ = true; + return; + } + // At this point, type is never null. + const google::protobuf::Type* type = resolved_type.value(); + + well_known_type_render_ = FindTypeRenderer(type_url_); + if (well_known_type_render_ != nullptr || + // Explicitly list Any and Struct here because they don't have a + // custom renderer. + type->name() == kAnyType || type->name() == kStructType) { + is_well_known_type_ = true; + } + + // Create our object writer and initialize it with the first StartObject + // call. + ow_.reset(new ProtoStreamObjectWriter(parent_->typeinfo(), *type, &output_, + parent_->listener(), + parent_->options_)); + + // Don't call StartObject() for well-known types yet. Depending on the + // type of actual data, we may not need to call StartObject(). For + // example: + // { + // "@type": "type.googleapis.com/google.protobuf.Value", + // "value": [1, 2, 3], + // } + // With the above JSON representation, we will only call StartList() on the + // contained ow_. + if (!is_well_known_type_) { + ow_->StartObject(""); + } + + // Now we know the proto type and can interpret all data fields we gathered + // before the "@type" field. + for (int i = 0; i < uninterpreted_events_.size(); ++i) { + uninterpreted_events_[i].Replay(this); + } +} + +void ProtoStreamObjectWriter::AnyWriter::WriteAny() { + if (ow_ == nullptr) { + if (uninterpreted_events_.empty()) { + // We never got any content, so just return immediately, which is + // equivalent to writing an empty Any. + return; + } else { + // There are uninterpreted data, but we never got a "@type" field. + if (!invalid_) { + parent_->InvalidValue("Any", + StrCat("Missing @type for any field in ", + parent_->master_type_.name())); + invalid_ = true; + } + return; + } + } + // Render the type_url and value fields directly to the stream. + // type_url has tag 1 and value has tag 2. + WireFormatLite::WriteString(1, type_url_, parent_->stream()); + if (!data_.empty()) { + WireFormatLite::WriteBytes(2, data_, parent_->stream()); + } +} + +void ProtoStreamObjectWriter::AnyWriter::Event::Replay( + AnyWriter* writer) const { + switch (type_) { + case START_OBJECT: + writer->StartObject(name_); + break; + case END_OBJECT: + writer->EndObject(); + break; + case START_LIST: + writer->StartList(name_); + break; + case END_LIST: + writer->EndList(); + break; + case RENDER_DATA_PIECE: + writer->RenderDataPiece(name_, value_); + break; + } +} + +void ProtoStreamObjectWriter::AnyWriter::Event::DeepCopy() { + // DataPiece only contains a string reference. To make sure the referenced + // string value stays valid, we make a copy of the string value and update + // DataPiece to reference our own copy. + if (value_.type() == DataPiece::TYPE_STRING) { + StrAppend(&value_storage_, value_.str()); + value_ = DataPiece(value_storage_, value_.use_strict_base64_decoding()); + } else if (value_.type() == DataPiece::TYPE_BYTES) { + value_storage_ = value_.ToBytes().value(); + value_ = + DataPiece(value_storage_, true, value_.use_strict_base64_decoding()); + } +} + +ProtoStreamObjectWriter::Item::Item(ProtoStreamObjectWriter* enclosing, + ItemType item_type, bool is_placeholder, + bool is_list) + : BaseElement(nullptr), + ow_(enclosing), + any_(), + item_type_(item_type), + is_placeholder_(is_placeholder), + is_list_(is_list) { + if (item_type_ == ANY) { + any_.reset(new AnyWriter(ow_)); + } + if (item_type == MAP) { + map_keys_.reset(new std::unordered_set<std::string>); + } +} + +ProtoStreamObjectWriter::Item::Item(ProtoStreamObjectWriter::Item* parent, + ItemType item_type, bool is_placeholder, + bool is_list) + : BaseElement(parent), + ow_(this->parent()->ow_), + any_(), + item_type_(item_type), + is_placeholder_(is_placeholder), + is_list_(is_list) { + if (item_type == ANY) { + any_.reset(new AnyWriter(ow_)); + } + if (item_type == MAP) { + map_keys_.reset(new std::unordered_set<std::string>); + } +} + +bool ProtoStreamObjectWriter::Item::InsertMapKeyIfNotPresent( + StringPiece map_key) { + return InsertIfNotPresent(map_keys_.get(), std::string(map_key)); +} + + +ProtoStreamObjectWriter* ProtoStreamObjectWriter::StartObject( + StringPiece name) { + if (invalid_depth() > 0) { + IncrementInvalidDepth(); + return this; + } + + // Starting the root message. Create the root Item and return. + // ANY message type does not need special handling, just set the ItemType + // to ANY. + if (current_ == nullptr) { + ProtoWriter::StartObject(name); + current_.reset(new Item( + this, master_type_.name() == kAnyType ? Item::ANY : Item::MESSAGE, + false, false)); + + // If master type is a special type that needs extra values to be written to + // stream, we write those values. + if (master_type_.name() == kStructType) { + // Struct has a map<string, Value> field called "fields". + // https://github.com/protocolbuffers/protobuf/blob/main/src/google/protobuf/struct.proto + // "fields": [ + Push("fields", Item::MAP, true, true); + return this; + } + + if (master_type_.name() == kStructValueType) { + // We got a StartObject call with google.protobuf.Value field. The only + // object within that type is a struct type. So start a struct. + // + // The struct field in Value type is named "struct_value" + // https://github.com/protocolbuffers/protobuf/blob/main/src/google/protobuf/struct.proto + // Also start the map field "fields" within the struct. + // "struct_value": { + // "fields": [ + Push("struct_value", Item::MESSAGE, true, false); + Push("fields", Item::MAP, true, true); + return this; + } + + if (master_type_.name() == kStructListValueType) { + InvalidValue(kStructListValueType, + "Cannot start root message with ListValue."); + } + + return this; + } + + // Send all ANY events to AnyWriter. + if (current_->IsAny()) { + current_->any()->StartObject(name); + return this; + } + + // If we are within a map, we render name as keys and send StartObject to the + // value field. + if (current_->IsMap()) { + if (!ValidMapKey(name)) { + IncrementInvalidDepth(); + return this; + } + + // Map is a repeated field of message type with a "key" and a "value" field. + // https://developers.google.com/protocol-buffers/docs/proto3?hl=en#maps + // message MapFieldEntry { + // key_type key = 1; + // value_type value = 2; + // } + // + // repeated MapFieldEntry map_field = N; + // + // That means, we render the following element within a list (hence no + // name): + // { "key": "<name>", "value": { + Push("", Item::MESSAGE, false, false); + ProtoWriter::RenderDataPiece("key", + DataPiece(name, use_strict_base64_decoding())); + Push("value", IsAny(*Lookup("value")) ? Item::ANY : Item::MESSAGE, true, + false); + + // Make sure we are valid so far after starting map fields. + if (invalid_depth() > 0) return this; + + // If top of stack is g.p.Struct type, start the struct the map field within + // it. + if (element() != nullptr && IsStruct(*element()->parent_field())) { + // Render "fields": [ + Push("fields", Item::MAP, true, true); + return this; + } + + // If top of stack is g.p.Value type, start the Struct within it. + if (element() != nullptr && IsStructValue(*element()->parent_field())) { + // Render + // "struct_value": { + // "fields": [ + Push("struct_value", Item::MESSAGE, true, false); + Push("fields", Item::MAP, true, true); + } + return this; + } + + const google::protobuf::Field* field = BeginNamed(name, false); + + if (field == nullptr) return this; + + // Legacy JSON map is a list of key value pairs. Starts a map entry object. + if (options_.use_legacy_json_map_format && name.empty()) { + Push(name, IsAny(*field) ? Item::ANY : Item::MESSAGE, false, false); + return this; + } + + if (IsMap(*field)) { + // Begin a map. A map is triggered by a StartObject() call if the current + // field has a map type. + // A map type is always repeated, hence set is_list to true. + // Render + // "<name>": [ + Push(name, Item::MAP, false, true); + return this; + } + + if (options_.disable_implicit_message_list) { + // If the incoming object is repeated, the top-level object on stack should + // be list. Report an error otherwise. + if (IsRepeated(*field) && !current_->is_list()) { + IncrementInvalidDepth(); + + if (!options_.suppress_implicit_message_list_error) { + InvalidValue( + field->name(), + "Starting an object in a repeated field but the parent object " + "is not a list"); + } + return this; + } + } + + if (IsStruct(*field)) { + // Start a struct object. + // Render + // "<name>": { + // "fields": { + Push(name, Item::MESSAGE, false, false); + Push("fields", Item::MAP, true, true); + return this; + } + + if (IsStructValue(*field)) { + // We got a StartObject call with google.protobuf.Value field. The only + // object within that type is a struct type. So start a struct. + // Render + // "<name>": { + // "struct_value": { + // "fields": { + Push(name, Item::MESSAGE, false, false); + Push("struct_value", Item::MESSAGE, true, false); + Push("fields", Item::MAP, true, true); + return this; + } + + if (field->kind() != google::protobuf::Field::TYPE_GROUP && + field->kind() != google::protobuf::Field::TYPE_MESSAGE) { + IncrementInvalidDepth(); + if (!options_.suppress_object_to_scalar_error) { + InvalidValue(field->name(), "Starting an object on a scalar field"); + } + + return this; + } + + // A regular message type. Pass it directly to ProtoWriter. + // Render + // "<name>": { + Push(name, IsAny(*field) ? Item::ANY : Item::MESSAGE, false, false); + return this; +} + +ProtoStreamObjectWriter* ProtoStreamObjectWriter::EndObject() { + if (invalid_depth() > 0) { + DecrementInvalidDepth(); + return this; + } + + if (current_ == nullptr) return this; + + if (current_->IsAny()) { + if (current_->any()->EndObject()) return this; + } + + Pop(); + + return this; +} + + +ProtoStreamObjectWriter* ProtoStreamObjectWriter::StartList( + StringPiece name) { + if (invalid_depth() > 0) { + IncrementInvalidDepth(); + return this; + } + + // Since we cannot have a top-level repeated item in protobuf, the only way + // this is valid is if we start a special type google.protobuf.ListValue or + // google.protobuf.Value. + if (current_ == nullptr) { + if (!name.empty()) { + InvalidName(name, "Root element should not be named."); + IncrementInvalidDepth(); + return this; + } + + // If master type is a special type that needs extra values to be written to + // stream, we write those values. + if (master_type_.name() == kStructValueType) { + // We got a StartList with google.protobuf.Value master type. This means + // we have to start the "list_value" within google.protobuf.Value. + // + // See + // https://github.com/protocolbuffers/protobuf/blob/main/src/google/protobuf/struct.proto + // + // Render + // "<name>": { + // "list_value": { + // "values": [ // Start this list. + ProtoWriter::StartObject(name); + current_.reset(new Item(this, Item::MESSAGE, false, false)); + Push("list_value", Item::MESSAGE, true, false); + Push("values", Item::MESSAGE, true, true); + return this; + } + + if (master_type_.name() == kStructListValueType) { + // We got a StartList with google.protobuf.ListValue master type. This + // means we have to start the "values" within google.protobuf.ListValue. + // + // Render + // "<name>": { + // "values": [ // Start this list. + ProtoWriter::StartObject(name); + current_.reset(new Item(this, Item::MESSAGE, false, false)); + Push("values", Item::MESSAGE, true, true); + return this; + } + + // Send the event to ProtoWriter so proper errors can be reported. + // + // Render a regular list: + // "<name>": [ + ProtoWriter::StartList(name); + current_.reset(new Item(this, Item::MESSAGE, false, true)); + return this; + } + + if (current_->IsAny()) { + current_->any()->StartList(name); + return this; + } + + // If the top of stack is a map, we are starting a list value within a map. + // Since map does not allow repeated values, this can only happen when the map + // value is of a special type that renders a list in JSON. These can be one + // of 3 cases: + // i. We are rendering a list value within google.protobuf.Struct + // ii. We are rendering a list value within google.protobuf.Value + // iii. We are rendering a list value with type google.protobuf.ListValue. + if (current_->IsMap()) { + if (!ValidMapKey(name)) { + IncrementInvalidDepth(); + return this; + } + + // Start the repeated map entry object. + // Render + // { "key": "<name>", "value": { + Push("", Item::MESSAGE, false, false); + ProtoWriter::RenderDataPiece("key", + DataPiece(name, use_strict_base64_decoding())); + Push("value", Item::MESSAGE, true, false); + + // Make sure we are valid after pushing all above items. + if (invalid_depth() > 0) return this; + + // case i and ii above. Start "list_value" field within g.p.Value + if (element() != nullptr && element()->parent_field() != nullptr) { + // Render + // "list_value": { + // "values": [ // Start this list + if (IsStructValue(*element()->parent_field())) { + Push("list_value", Item::MESSAGE, true, false); + Push("values", Item::MESSAGE, true, true); + return this; + } + + // Render + // "values": [ + if (IsStructListValue(*element()->parent_field())) { + // case iii above. Bind directly to g.p.ListValue + Push("values", Item::MESSAGE, true, true); + return this; + } + } + + // Report an error. + InvalidValue("Map", StrCat("Cannot have repeated items ('", name, + "') within a map.")); + return this; + } + + // When name is empty and stack is not empty, we are rendering an item within + // a list. + if (name.empty()) { + if (element() != nullptr && element()->parent_field() != nullptr) { + if (IsStructValue(*element()->parent_field())) { + // Since it is g.p.Value, we bind directly to the list_value. + // Render + // { // g.p.Value item within the list + // "list_value": { + // "values": [ + Push("", Item::MESSAGE, false, false); + Push("list_value", Item::MESSAGE, true, false); + Push("values", Item::MESSAGE, true, true); + return this; + } + + if (IsStructListValue(*element()->parent_field())) { + // Since it is g.p.ListValue, we bind to it directly. + // Render + // { // g.p.ListValue item within the list + // "values": [ + Push("", Item::MESSAGE, false, false); + Push("values", Item::MESSAGE, true, true); + return this; + } + } + + // Pass the event to underlying ProtoWriter. + Push(name, Item::MESSAGE, false, true); + return this; + } + + // name is not empty + const google::protobuf::Field* field = Lookup(name); + + if (field == nullptr) { + IncrementInvalidDepth(); + return this; + } + + if (IsStructValue(*field)) { + // If g.p.Value is repeated, start that list. Otherwise, start the + // "list_value" within it. + if (IsRepeated(*field)) { + // Render it just like a regular repeated field. + // "<name>": [ + Push(name, Item::MESSAGE, false, true); + return this; + } + + // Start the "list_value" field. + // Render + // "<name>": { + // "list_value": { + // "values": [ + Push(name, Item::MESSAGE, false, false); + Push("list_value", Item::MESSAGE, true, false); + Push("values", Item::MESSAGE, true, true); + return this; + } + + if (IsStructListValue(*field)) { + // If g.p.ListValue is repeated, start that list. Otherwise, start the + // "values" within it. + if (IsRepeated(*field)) { + // Render it just like a regular repeated field. + // "<name>": [ + Push(name, Item::MESSAGE, false, true); + return this; + } + + // Start the "values" field within g.p.ListValue. + // Render + // "<name>": { + // "values": [ + Push(name, Item::MESSAGE, false, false); + Push("values", Item::MESSAGE, true, true); + return this; + } + + // If we are here, the field should be repeated. Report an error otherwise. + if (!IsRepeated(*field)) { + IncrementInvalidDepth(); + InvalidName(name, "Proto field is not repeating, cannot start list."); + return this; + } + + if (IsMap(*field)) { + if (options_.use_legacy_json_map_format) { + Push(name, Item::MESSAGE, false, true); + return this; + } + InvalidValue("Map", StrCat("Cannot bind a list to map for field '", + name, "'.")); + IncrementInvalidDepth(); + return this; + } + + // Pass the event to ProtoWriter. + // Render + // "<name>": [ + Push(name, Item::MESSAGE, false, true); + return this; +} + +ProtoStreamObjectWriter* ProtoStreamObjectWriter::EndList() { + if (invalid_depth() > 0) { + DecrementInvalidDepth(); + return this; + } + + if (current_ == nullptr) return this; + + if (current_->IsAny()) { + current_->any()->EndList(); + return this; + } + + Pop(); + return this; +} + +Status ProtoStreamObjectWriter::RenderStructValue(ProtoStreamObjectWriter* ow, + const DataPiece& data) { + std::string struct_field_name; + switch (data.type()) { + case DataPiece::TYPE_INT32: { + if (ow->options_.struct_integers_as_strings) { + util::StatusOr<int32_t> int_value = data.ToInt32(); + if (int_value.ok()) { + ow->ProtoWriter::RenderDataPiece( + "string_value", + DataPiece(SimpleDtoa(int_value.value()), true)); + return Status(); + } + } + struct_field_name = "number_value"; + break; + } + case DataPiece::TYPE_UINT32: { + if (ow->options_.struct_integers_as_strings) { + util::StatusOr<uint32_t> int_value = data.ToUint32(); + if (int_value.ok()) { + ow->ProtoWriter::RenderDataPiece( + "string_value", + DataPiece(SimpleDtoa(int_value.value()), true)); + return Status(); + } + } + struct_field_name = "number_value"; + break; + } + case DataPiece::TYPE_INT64: { + // If the option to treat integers as strings is set, then render them as + // strings. Otherwise, fallback to rendering them as double. + if (ow->options_.struct_integers_as_strings) { + util::StatusOr<int64_t> int_value = data.ToInt64(); + if (int_value.ok()) { + ow->ProtoWriter::RenderDataPiece( + "string_value", DataPiece(StrCat(int_value.value()), true)); + return Status(); + } + } + struct_field_name = "number_value"; + break; + } + case DataPiece::TYPE_UINT64: { + // If the option to treat integers as strings is set, then render them as + // strings. Otherwise, fallback to rendering them as double. + if (ow->options_.struct_integers_as_strings) { + util::StatusOr<uint64_t> int_value = data.ToUint64(); + if (int_value.ok()) { + ow->ProtoWriter::RenderDataPiece( + "string_value", DataPiece(StrCat(int_value.value()), true)); + return Status(); + } + } + struct_field_name = "number_value"; + break; + } + case DataPiece::TYPE_FLOAT: { + if (ow->options_.struct_integers_as_strings) { + util::StatusOr<float> float_value = data.ToFloat(); + if (float_value.ok()) { + ow->ProtoWriter::RenderDataPiece( + "string_value", + DataPiece(SimpleDtoa(float_value.value()), true)); + return Status(); + } + } + struct_field_name = "number_value"; + break; + } + case DataPiece::TYPE_DOUBLE: { + if (ow->options_.struct_integers_as_strings) { + util::StatusOr<double> double_value = data.ToDouble(); + if (double_value.ok()) { + ow->ProtoWriter::RenderDataPiece( + "string_value", + DataPiece(SimpleDtoa(double_value.value()), true)); + return Status(); + } + } + struct_field_name = "number_value"; + break; + } + case DataPiece::TYPE_STRING: { + struct_field_name = "string_value"; + break; + } + case DataPiece::TYPE_BOOL: { + struct_field_name = "bool_value"; + break; + } + case DataPiece::TYPE_NULL: { + struct_field_name = "null_value"; + break; + } + default: { + return util::InvalidArgumentError( + "Invalid struct data type. Only number, string, boolean or null " + "values are supported."); + } + } + ow->ProtoWriter::RenderDataPiece(struct_field_name, data); + return Status(); +} + +Status ProtoStreamObjectWriter::RenderTimestamp(ProtoStreamObjectWriter* ow, + const DataPiece& data) { + if (data.type() == DataPiece::TYPE_NULL) return Status(); + if (data.type() != DataPiece::TYPE_STRING) { + return util::InvalidArgumentError( + StrCat("Invalid data type for timestamp, value is ", + data.ValueAsStringOrDefault(""))); + } + + StringPiece value(data.str()); + + int64_t seconds; + int32_t nanos; + if (!::google::protobuf::internal::ParseTime(value.ToString(), &seconds, + &nanos)) { + return util::InvalidArgumentError(StrCat("Invalid time format: ", value)); + } + + + ow->ProtoWriter::RenderDataPiece("seconds", DataPiece(seconds)); + ow->ProtoWriter::RenderDataPiece("nanos", DataPiece(nanos)); + return Status(); +} + +static inline util::Status RenderOneFieldPath(ProtoStreamObjectWriter* ow, + StringPiece path) { + ow->ProtoWriter::RenderDataPiece( + "paths", DataPiece(ConvertFieldMaskPath(path, &ToSnakeCase), true)); + return Status(); +} + +Status ProtoStreamObjectWriter::RenderFieldMask(ProtoStreamObjectWriter* ow, + const DataPiece& data) { + if (data.type() == DataPiece::TYPE_NULL) return Status(); + if (data.type() != DataPiece::TYPE_STRING) { + return util::InvalidArgumentError( + StrCat("Invalid data type for field mask, value is ", + data.ValueAsStringOrDefault(""))); + } + + // TODO(tsun): figure out how to do proto descriptor based snake case + // conversions as much as possible. Because ToSnakeCase sometimes returns the + // wrong value. + return DecodeCompactFieldMaskPaths(data.str(), + std::bind(&RenderOneFieldPath, ow, _1)); +} + +Status ProtoStreamObjectWriter::RenderDuration(ProtoStreamObjectWriter* ow, + const DataPiece& data) { + if (data.type() == DataPiece::TYPE_NULL) return Status(); + if (data.type() != DataPiece::TYPE_STRING) { + return util::InvalidArgumentError( + StrCat("Invalid data type for duration, value is ", + data.ValueAsStringOrDefault(""))); + } + + StringPiece value(data.str()); + + if (!HasSuffixString(value, "s")) { + return util::InvalidArgumentError( + "Illegal duration format; duration must end with 's'"); + } + value = value.substr(0, value.size() - 1); + int sign = 1; + if (HasPrefixString(value, "-")) { + sign = -1; + value = value.substr(1); + } + + StringPiece s_secs, s_nanos; + SplitSecondsAndNanos(value, &s_secs, &s_nanos); + uint64_t unsigned_seconds; + if (!safe_strtou64(s_secs, &unsigned_seconds)) { + return util::InvalidArgumentError( + "Invalid duration format, failed to parse seconds"); + } + + int32_t nanos = 0; + Status nanos_status = GetNanosFromStringPiece( + s_nanos, "Invalid duration format, failed to parse nano seconds", + "Duration value exceeds limits", &nanos); + if (!nanos_status.ok()) { + return nanos_status; + } + nanos = sign * nanos; + + int64_t seconds = sign * unsigned_seconds; + if (seconds > kDurationMaxSeconds || seconds < kDurationMinSeconds || + nanos <= -kNanosPerSecond || nanos >= kNanosPerSecond) { + return util::InvalidArgumentError("Duration value exceeds limits"); + } + + ow->ProtoWriter::RenderDataPiece("seconds", DataPiece(seconds)); + ow->ProtoWriter::RenderDataPiece("nanos", DataPiece(nanos)); + return Status(); +} + +Status ProtoStreamObjectWriter::RenderWrapperType(ProtoStreamObjectWriter* ow, + const DataPiece& data) { + if (data.type() == DataPiece::TYPE_NULL) return Status(); + ow->ProtoWriter::RenderDataPiece("value", data); + return Status(); +} + +ProtoStreamObjectWriter* ProtoStreamObjectWriter::RenderDataPiece( + StringPiece name, const DataPiece& data) { + Status status; + if (invalid_depth() > 0) return this; + + if (current_ == nullptr) { + const TypeRenderer* type_renderer = + FindTypeRenderer(GetFullTypeWithUrl(master_type_.name())); + if (type_renderer == nullptr) { + InvalidName(name, "Root element must be a message."); + return this; + } + // Render the special type. + // "<name>": { + // ... Render special type ... + // } + ProtoWriter::StartObject(name); + status = (*type_renderer)(this, data); + if (!status.ok()) { + InvalidValue(master_type_.name(), + StrCat("Field '", name, "', ", status.message())); + } + ProtoWriter::EndObject(); + return this; + } + + if (current_->IsAny()) { + current_->any()->RenderDataPiece(name, data); + return this; + } + + const google::protobuf::Field* field = nullptr; + if (current_->IsMap()) { + if (!ValidMapKey(name)) return this; + + field = Lookup("value"); + if (field == nullptr) { + GOOGLE_LOG(DFATAL) << "Map does not have a value field."; + return this; + } + + if (options_.ignore_null_value_map_entry) { + // If we are rendering explicit null values and the backend proto field is + // not of the google.protobuf.NullType type, interpret null as absence. + if (data.type() == DataPiece::TYPE_NULL && + field->type_url() != kStructNullValueTypeUrl) { + return this; + } + } + + // Render an item in repeated map list. + // { "key": "<name>", "value": + Push("", Item::MESSAGE, false, false); + ProtoWriter::RenderDataPiece("key", + DataPiece(name, use_strict_base64_decoding())); + + const TypeRenderer* type_renderer = FindTypeRenderer(field->type_url()); + if (type_renderer != nullptr) { + // Map's value type is a special type. Render it like a message: + // "value": { + // ... Render special type ... + // } + Push("value", Item::MESSAGE, true, false); + status = (*type_renderer)(this, data); + if (!status.ok()) { + InvalidValue(field->type_url(), + StrCat("Field '", name, "', ", status.message())); + } + Pop(); + return this; + } + + // If we are rendering explicit null values and the backend proto field is + // not of the google.protobuf.NullType type, we do nothing. + if (data.type() == DataPiece::TYPE_NULL && + field->type_url() != kStructNullValueTypeUrl) { + Pop(); + return this; + } + + // Render the map value as a primitive type. + ProtoWriter::RenderDataPiece("value", data); + Pop(); + return this; + } + + field = Lookup(name); + if (field == nullptr) return this; + + // Check if the field is of special type. Render it accordingly if so. + const TypeRenderer* type_renderer = FindTypeRenderer(field->type_url()); + if (type_renderer != nullptr) { + // Pass through null value only for google.protobuf.Value. For other + // types we ignore null value just like for regular field types. + if (data.type() != DataPiece::TYPE_NULL || + field->type_url() == kStructValueTypeUrl) { + Push(name, Item::MESSAGE, false, false); + status = (*type_renderer)(this, data); + if (!status.ok()) { + InvalidValue(field->type_url(), + StrCat("Field '", name, "', ", status.message())); + } + Pop(); + } + return this; + } + + // If we are rendering explicit null values and the backend proto field is + // not of the google.protobuf.NullType type, we do nothing. + if (data.type() == DataPiece::TYPE_NULL && + field->type_url() != kStructNullValueTypeUrl) { + return this; + } + + if (IsRepeated(*field) && !current_->is_list()) { + if (options_.disable_implicit_scalar_list) { + if (!options_.suppress_implicit_scalar_list_error) { + InvalidValue( + field->name(), + "Starting an primitive in a repeated field but the parent field " + "is not a list"); + } + + return this; + } + } + + ProtoWriter::RenderDataPiece(name, data); + return this; +} + +// Map of functions that are responsible for rendering well known type +// represented by the key. +std::unordered_map<std::string, ProtoStreamObjectWriter::TypeRenderer>* + ProtoStreamObjectWriter::renderers_ = nullptr; +PROTOBUF_NAMESPACE_ID::internal::once_flag writer_renderers_init_; + +void ProtoStreamObjectWriter::InitRendererMap() { + renderers_ = new std::unordered_map<std::string, + ProtoStreamObjectWriter::TypeRenderer>(); + (*renderers_)["type.googleapis.com/google.protobuf.Timestamp"] = + &ProtoStreamObjectWriter::RenderTimestamp; + (*renderers_)["type.googleapis.com/google.protobuf.Duration"] = + &ProtoStreamObjectWriter::RenderDuration; + (*renderers_)["type.googleapis.com/google.protobuf.FieldMask"] = + &ProtoStreamObjectWriter::RenderFieldMask; + (*renderers_)["type.googleapis.com/google.protobuf.Double"] = + &ProtoStreamObjectWriter::RenderWrapperType; + (*renderers_)["type.googleapis.com/google.protobuf.Float"] = + &ProtoStreamObjectWriter::RenderWrapperType; + (*renderers_)["type.googleapis.com/google.protobuf.Int64"] = + &ProtoStreamObjectWriter::RenderWrapperType; + (*renderers_)["type.googleapis.com/google.protobuf.UInt64"] = + &ProtoStreamObjectWriter::RenderWrapperType; + (*renderers_)["type.googleapis.com/google.protobuf.Int32"] = + &ProtoStreamObjectWriter::RenderWrapperType; + (*renderers_)["type.googleapis.com/google.protobuf.UInt32"] = + &ProtoStreamObjectWriter::RenderWrapperType; + (*renderers_)["type.googleapis.com/google.protobuf.Bool"] = + &ProtoStreamObjectWriter::RenderWrapperType; + (*renderers_)["type.googleapis.com/google.protobuf.String"] = + &ProtoStreamObjectWriter::RenderWrapperType; + (*renderers_)["type.googleapis.com/google.protobuf.Bytes"] = + &ProtoStreamObjectWriter::RenderWrapperType; + (*renderers_)["type.googleapis.com/google.protobuf.DoubleValue"] = + &ProtoStreamObjectWriter::RenderWrapperType; + (*renderers_)["type.googleapis.com/google.protobuf.FloatValue"] = + &ProtoStreamObjectWriter::RenderWrapperType; + (*renderers_)["type.googleapis.com/google.protobuf.Int64Value"] = + &ProtoStreamObjectWriter::RenderWrapperType; + (*renderers_)["type.googleapis.com/google.protobuf.UInt64Value"] = + &ProtoStreamObjectWriter::RenderWrapperType; + (*renderers_)["type.googleapis.com/google.protobuf.Int32Value"] = + &ProtoStreamObjectWriter::RenderWrapperType; + (*renderers_)["type.googleapis.com/google.protobuf.UInt32Value"] = + &ProtoStreamObjectWriter::RenderWrapperType; + (*renderers_)["type.googleapis.com/google.protobuf.BoolValue"] = + &ProtoStreamObjectWriter::RenderWrapperType; + (*renderers_)["type.googleapis.com/google.protobuf.StringValue"] = + &ProtoStreamObjectWriter::RenderWrapperType; + (*renderers_)["type.googleapis.com/google.protobuf.BytesValue"] = + &ProtoStreamObjectWriter::RenderWrapperType; + (*renderers_)["type.googleapis.com/google.protobuf.Value"] = + &ProtoStreamObjectWriter::RenderStructValue; + ::google::protobuf::internal::OnShutdown(&DeleteRendererMap); +} + +void ProtoStreamObjectWriter::DeleteRendererMap() { + delete ProtoStreamObjectWriter::renderers_; + renderers_ = nullptr; +} + +ProtoStreamObjectWriter::TypeRenderer* +ProtoStreamObjectWriter::FindTypeRenderer(const std::string& type_url) { + PROTOBUF_NAMESPACE_ID::internal::call_once(writer_renderers_init_, + InitRendererMap); + return FindOrNull(*renderers_, type_url); +} + +bool ProtoStreamObjectWriter::ValidMapKey(StringPiece unnormalized_name) { + if (current_ == nullptr) return true; + + if (!current_->InsertMapKeyIfNotPresent(unnormalized_name)) { + listener()->InvalidName( + location(), unnormalized_name, + StrCat("Repeated map key: '", unnormalized_name, + "' is already set.")); + return false; + } + + return true; +} + +void ProtoStreamObjectWriter::Push( + StringPiece name, Item::ItemType item_type, bool is_placeholder, + bool is_list) { + is_list ? ProtoWriter::StartList(name) : ProtoWriter::StartObject(name); + + // invalid_depth == 0 means it is a successful StartObject or StartList. + if (invalid_depth() == 0) + current_.reset( + new Item(current_.release(), item_type, is_placeholder, is_list)); +} + +void ProtoStreamObjectWriter::Pop() { + // Pop all placeholder items sending StartObject or StartList events to + // ProtoWriter according to is_list value. + while (current_ != nullptr && current_->is_placeholder()) { + PopOneElement(); + } + if (current_ != nullptr) { + PopOneElement(); + } +} + +void ProtoStreamObjectWriter::PopOneElement() { + current_->is_list() ? ProtoWriter::EndList() : ProtoWriter::EndObject(); + current_.reset(current_->pop<Item>()); +} + +bool ProtoStreamObjectWriter::IsMap(const google::protobuf::Field& field) { + if (field.type_url().empty() || + field.kind() != google::protobuf::Field::TYPE_MESSAGE || + field.cardinality() != google::protobuf::Field::CARDINALITY_REPEATED) { + return false; + } + const google::protobuf::Type* field_type = + typeinfo()->GetTypeByTypeUrl(field.type_url()); + + return converter::IsMap(field, *field_type); +} + +bool ProtoStreamObjectWriter::IsAny(const google::protobuf::Field& field) { + return GetTypeWithoutUrl(field.type_url()) == kAnyType; +} + +bool ProtoStreamObjectWriter::IsStruct(const google::protobuf::Field& field) { + return GetTypeWithoutUrl(field.type_url()) == kStructType; +} + +bool ProtoStreamObjectWriter::IsStructValue( + const google::protobuf::Field& field) { + return GetTypeWithoutUrl(field.type_url()) == kStructValueType; +} + +bool ProtoStreamObjectWriter::IsStructListValue( + const google::protobuf::Field& field) { + return GetTypeWithoutUrl(field.type_url()) == kStructListValueType; +} + +} // namespace converter +} // namespace util +} // namespace protobuf +} // namespace google diff --git a/toolkit/components/protobuf/src/google/protobuf/util/internal/protostream_objectwriter.h b/toolkit/components/protobuf/src/google/protobuf/util/internal/protostream_objectwriter.h new file mode 100644 index 0000000000..ce2517f9e9 --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/util/internal/protostream_objectwriter.h @@ -0,0 +1,453 @@ +// 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. + +#ifndef GOOGLE_PROTOBUF_UTIL_INTERNAL_PROTOSTREAM_OBJECTWRITER_H__ +#define GOOGLE_PROTOBUF_UTIL_INTERNAL_PROTOSTREAM_OBJECTWRITER_H__ + +#include <deque> +#include <string> +#include <unordered_map> +#include <unordered_set> + +#include <google/protobuf/stubs/common.h> +#include <google/protobuf/type.pb.h> +#include <google/protobuf/io/coded_stream.h> +#include <google/protobuf/io/zero_copy_stream_impl.h> +#include <google/protobuf/descriptor.h> +#include <google/protobuf/stubs/bytestream.h> +#include <google/protobuf/stubs/status.h> +#include <google/protobuf/util/internal/datapiece.h> +#include <google/protobuf/util/internal/error_listener.h> +#include <google/protobuf/util/internal/proto_writer.h> +#include <google/protobuf/util/internal/structured_objectwriter.h> +#include <google/protobuf/util/internal/type_info.h> +#include <google/protobuf/util/type_resolver.h> +#include <google/protobuf/stubs/hash.h> + +// Must be included last. +#include <google/protobuf/port_def.inc> + +namespace google { +namespace protobuf { +namespace util { +namespace converter { + +class ObjectLocationTracker; + +// An ObjectWriter that can write protobuf bytes directly from writer events. +// This class supports all special types like Struct and Map. It uses +// the ProtoWriter class to write raw proto bytes. +// +// It also supports streaming. +class PROTOBUF_EXPORT ProtoStreamObjectWriter : public ProtoWriter { + public: + // Options that control ProtoStreamObjectWriter class's behavior. + struct Options { + // Treats numeric inputs in google.protobuf.Struct as strings. Normally, + // numeric values are returned in double field "number_value" of + // google.protobuf.Struct. However, this can cause precision loss for + // int64/uint64/double inputs. This option is provided for cases that want + // to preserve number precision. + // + // TODO(skarvaje): Rename to struct_numbers_as_strings as it covers double + // as well. + bool struct_integers_as_strings; + + // Not treat unknown fields as an error. If there is an unknown fields, + // just ignore it and continue to process the rest. Note that this doesn't + // apply to unknown enum values. + bool ignore_unknown_fields; + + // Ignore unknown enum values. + bool ignore_unknown_enum_values; + + // If true, check if enum name in camel case or without underscore matches + // the field name. + bool use_lower_camel_for_enums; + + // If true, check if enum name in UPPER_CASE matches the field name. + bool case_insensitive_enum_parsing; + + // If true, skips rendering the map entry if map value is null unless the + // value type is google.protobuf.NullType. + bool ignore_null_value_map_entry; + + // If true, accepts repeated key/value pair for a map proto field. + bool use_legacy_json_map_format; + + // If true, disable implicitly creating message list. + bool disable_implicit_message_list; + + // If true, suppress the error of implicitly creating message list when it + // is disabled. + bool suppress_implicit_message_list_error; + + // If true, disable implicitly creating scalar list. + bool disable_implicit_scalar_list; + + // If true, suppress the error of implicitly creating scalar list when it + // is disabled. + bool suppress_implicit_scalar_list_error; + + // If true, suppress the error of rendering scalar field if the source is an + // object. + bool suppress_object_to_scalar_error; + + // If true, use the json name in missing fields errors. + bool use_json_name_in_missing_fields; + + Options() + : struct_integers_as_strings(false), + ignore_unknown_fields(false), + ignore_unknown_enum_values(false), + use_lower_camel_for_enums(false), + case_insensitive_enum_parsing(false), + ignore_null_value_map_entry(false), + use_legacy_json_map_format(false), + disable_implicit_message_list(false), + suppress_implicit_message_list_error(false), + disable_implicit_scalar_list(false), + suppress_implicit_scalar_list_error(false), + suppress_object_to_scalar_error(false), + use_json_name_in_missing_fields(false) {} + + // Default instance of Options with all options set to defaults. + static const Options& Defaults() { + static Options defaults; + return defaults; + } + }; + + // Constructor. Does not take ownership of any parameter passed in. + ProtoStreamObjectWriter(TypeResolver* type_resolver, + const google::protobuf::Type& type, + strings::ByteSink* output, ErrorListener* listener, + const ProtoStreamObjectWriter::Options& options = + ProtoStreamObjectWriter::Options::Defaults()); + ~ProtoStreamObjectWriter() override; + + // ObjectWriter methods. + ProtoStreamObjectWriter* StartObject(StringPiece name) override; + ProtoStreamObjectWriter* EndObject() override; + ProtoStreamObjectWriter* StartList(StringPiece name) override; + ProtoStreamObjectWriter* EndList() override; + + // Renders a DataPiece 'value' into a field whose wire type is determined + // from the given field 'name'. + ProtoStreamObjectWriter* RenderDataPiece(StringPiece name, + const DataPiece& data) override; + + protected: + // Function that renders a well known type with modified behavior. + typedef util::Status (*TypeRenderer)(ProtoStreamObjectWriter*, + const DataPiece&); + + // Handles writing Anys out using nested object writers and the like. + class PROTOBUF_EXPORT AnyWriter { + public: + explicit AnyWriter(ProtoStreamObjectWriter* parent); + ~AnyWriter(); + + // Passes a StartObject call through to the Any writer. + void StartObject(StringPiece name); + + // Passes an EndObject call through to the Any. Returns true if the any + // handled the EndObject call, false if the Any is now all done and is no + // longer needed. + bool EndObject(); + + // Passes a StartList call through to the Any writer. + void StartList(StringPiece name); + + // Passes an EndList call through to the Any writer. + void EndList(); + + // Renders a data piece on the any. + void RenderDataPiece(StringPiece name, const DataPiece& value); + + private: + // Before the "@type" field is encountered, we store all incoming data + // into this Event struct and replay them after we get the "@type" field. + class PROTOBUF_EXPORT Event { + public: + enum Type { + START_OBJECT = 0, + END_OBJECT = 1, + START_LIST = 2, + END_LIST = 3, + RENDER_DATA_PIECE = 4, + }; + + // Constructor for END_OBJECT and END_LIST events. + explicit Event(Type type) : type_(type), value_(DataPiece::NullData()) {} + + // Constructor for START_OBJECT and START_LIST events. + explicit Event(Type type, StringPiece name) + : type_(type), name_(name), value_(DataPiece::NullData()) {} + + // Constructor for RENDER_DATA_PIECE events. + explicit Event(StringPiece name, const DataPiece& value) + : type_(RENDER_DATA_PIECE), name_(name), value_(value) { + DeepCopy(); + } + + Event(const Event& other) + : type_(other.type_), name_(other.name_), value_(other.value_) { + DeepCopy(); + } + + Event& operator=(const Event& other) { + type_ = other.type_; + name_ = other.name_; + value_ = other.value_; + DeepCopy(); + return *this; + } + + void Replay(AnyWriter* writer) const; + + private: + void DeepCopy(); + + Type type_; + std::string name_; + DataPiece value_; + std::string value_storage_; + }; + + // Handles starting up the any once we have a type. + void StartAny(const DataPiece& value); + + // Writes the Any out to the parent writer in its serialized form. + void WriteAny(); + + // The parent of this writer, needed for various bits such as type info and + // the listeners. + ProtoStreamObjectWriter* parent_; + + // The nested object writer, used to write events. + std::unique_ptr<ProtoStreamObjectWriter> ow_; + + // The type_url_ that this Any represents. + std::string type_url_; + + // Whether this any is invalid. This allows us to only report an invalid + // Any message a single time rather than every time we get a nested field. + bool invalid_; + + // The output data and wrapping ByteSink. + std::string data_; + strings::StringByteSink output_; + + // The depth within the Any, so we can track when we're done. + int depth_; + + // True if the type is a well-known type. Well-known types in Any + // has a special formatting: + // { + // "@type": "type.googleapis.com/google.protobuf.XXX", + // "value": <JSON representation of the type>, + // } + bool is_well_known_type_; + TypeRenderer* well_known_type_render_; + + // Store data before the "@type" field. + std::vector<Event> uninterpreted_events_; + }; + + // Represents an item in a stack of items used to keep state between + // ObjectWrier events. + class PROTOBUF_EXPORT Item : public BaseElement { + public: + // Indicates the type of item. + enum ItemType { + MESSAGE, // Simple message + MAP, // Proto3 map type + ANY, // Proto3 Any type + }; + + // Constructor for the root item. + Item(ProtoStreamObjectWriter* enclosing, ItemType item_type, + bool is_placeholder, bool is_list); + + // Constructor for a field of a message. + Item(Item* parent, ItemType item_type, bool is_placeholder, bool is_list); + + ~Item() override {} + + // These functions return true if the element type is corresponding to the + // type in function name. + bool IsMap() { return item_type_ == MAP; } + bool IsAny() { return item_type_ == ANY; } + + AnyWriter* any() const { return any_.get(); } + + Item* parent() const override { + return static_cast<Item*>(BaseElement::parent()); + } + + // Inserts map key into hash set if and only if the key did NOT already + // exist in hash set. + // The hash set (map_keys_) is ONLY used to keep track of map keys. + // Return true if insert successfully; returns false if the map key was + // already present. + bool InsertMapKeyIfNotPresent(StringPiece map_key); + + bool is_placeholder() const { return is_placeholder_; } + bool is_list() const { return is_list_; } + + private: + // Used for access to variables of the enclosing instance of + // ProtoStreamObjectWriter. + ProtoStreamObjectWriter* ow_; + + // A writer for Any objects, handles all Any-related nonsense. + std::unique_ptr<AnyWriter> any_; + + // The type of this element, see enum for permissible types. + ItemType item_type_; + + // Set of map keys already seen for the type_. Used to validate incoming + // messages so no map key appears more than once. + std::unique_ptr<std::unordered_set<std::string> > map_keys_; + + // Conveys whether this Item is a placeholder or not. Placeholder items are + // pushed to stack to account for special types. + bool is_placeholder_; + + // Conveys whether this Item is a list or not. This is used to send + // StartList or EndList calls to underlying ObjectWriter. + bool is_list_; + + GOOGLE_DISALLOW_IMPLICIT_CONSTRUCTORS(Item); + }; + + ProtoStreamObjectWriter(const TypeInfo* typeinfo, + const google::protobuf::Type& type, + strings::ByteSink* output, ErrorListener* listener); + + ProtoStreamObjectWriter(const TypeInfo* typeinfo, + const google::protobuf::Type& type, + strings::ByteSink* output, ErrorListener* listener, + const ProtoStreamObjectWriter::Options& options); + + // Returns true if the field is a map. + inline bool IsMap(const google::protobuf::Field& field); + + // Returns true if the field is an any. + inline bool IsAny(const google::protobuf::Field& field); + + // Returns true if the field is google.protobuf.Struct. + inline bool IsStruct(const google::protobuf::Field& field); + + // Returns true if the field is google.protobuf.Value. + inline bool IsStructValue(const google::protobuf::Field& field); + + // Returns true if the field is google.protobuf.ListValue. + inline bool IsStructListValue(const google::protobuf::Field& field); + + // Renders google.protobuf.Value in struct.proto. It picks the right oneof + // type based on value's type. + static util::Status RenderStructValue(ProtoStreamObjectWriter* ow, + const DataPiece& data); + + // Renders google.protobuf.Timestamp value. + static util::Status RenderTimestamp(ProtoStreamObjectWriter* ow, + const DataPiece& data); + + // Renders google.protobuf.FieldMask value. + static util::Status RenderFieldMask(ProtoStreamObjectWriter* ow, + const DataPiece& data); + + // Renders google.protobuf.Duration value. + static util::Status RenderDuration(ProtoStreamObjectWriter* ow, + const DataPiece& data); + + // Renders wrapper message types for primitive types in + // google/protobuf/wrappers.proto. + static util::Status RenderWrapperType(ProtoStreamObjectWriter* ow, + const DataPiece& data); + + static void InitRendererMap(); + static void DeleteRendererMap(); + static TypeRenderer* FindTypeRenderer(const std::string& type_url); + + // Returns true if the map key for type_ is not duplicated key. + // If map key is duplicated key, this function returns false. + // Note that caller should make sure that the current proto element (current_) + // is of element type MAP or STRUCT_MAP. + // It also calls the appropriate error callback and unnormalzied_name is used + // for error string. + bool ValidMapKey(StringPiece unnormalized_name); + + // Pushes an item on to the stack. Also calls either StartObject or StartList + // on the underlying ObjectWriter depending on whether is_list is false or + // not. + // is_placeholder conveys whether the item is a placeholder item or not. + // Placeholder items are pushed when adding auxiliary types' StartObject or + // StartList calls. + void Push(StringPiece name, Item::ItemType item_type, + bool is_placeholder, bool is_list); + + + // Pops items from the stack. All placeholder items are popped until a + // non-placeholder item is found. + void Pop(); + + // Pops one element from the stack. Calls EndObject() or EndList() on the + // underlying ObjectWriter depending on the value of is_list_. + void PopOneElement(); + + private: + // Helper functions to create the map and find functions responsible for + // rendering well known types, keyed by type URL. + static std::unordered_map<std::string, TypeRenderer>* renderers_; + + // Variables for describing the structure of the input tree: + // master_type_: descriptor for the whole protobuf message. + const google::protobuf::Type& master_type_; + + // The current element, variable for internal state processing. + std::unique_ptr<Item> current_; + + // Reference to the options that control this class's behavior. + const ProtoStreamObjectWriter::Options options_; + + GOOGLE_DISALLOW_IMPLICIT_CONSTRUCTORS(ProtoStreamObjectWriter); +}; + +} // namespace converter +} // namespace util +} // namespace protobuf +} // namespace google + +#include <google/protobuf/port_undef.inc> + +#endif // GOOGLE_PROTOBUF_UTIL_INTERNAL_PROTOSTREAM_OBJECTWRITER_H__ diff --git a/toolkit/components/protobuf/src/google/protobuf/util/internal/structured_objectwriter.h b/toolkit/components/protobuf/src/google/protobuf/util/internal/structured_objectwriter.h new file mode 100644 index 0000000000..f6f7c89e57 --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/util/internal/structured_objectwriter.h @@ -0,0 +1,121 @@ +// 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. + +#ifndef GOOGLE_PROTOBUF_UTIL_INTERNAL_STRUCTURED_OBJECTWRITER_H__ +#define GOOGLE_PROTOBUF_UTIL_INTERNAL_STRUCTURED_OBJECTWRITER_H__ + +#include <memory> + +#include <google/protobuf/stubs/casts.h> +#include <google/protobuf/stubs/common.h> +#include <google/protobuf/util/internal/object_writer.h> + +// Must be included last. +#include <google/protobuf/port_def.inc> + +namespace google { +namespace protobuf { +namespace util { +namespace converter { + +// An StructuredObjectWriter is an ObjectWriter for writing +// tree-structured data in a stream of events representing objects +// and collections. Implementation of this interface can be used to +// write an object stream to an in-memory structure, protobufs, +// JSON, XML, or any other output format desired. The ObjectSource +// interface is typically used as the source of an object stream. +// +// See JsonObjectWriter for a sample implementation of +// StructuredObjectWriter and its use. +// +// Derived classes could be thread-unsafe. +class PROTOBUF_EXPORT StructuredObjectWriter : public ObjectWriter { + public: + ~StructuredObjectWriter() override {} + + protected: + // A base element class for subclasses to extend, makes tracking state easier. + // + // StructuredObjectWriter behaves as a visitor. BaseElement represents a node + // in the input tree. Implementation of StructuredObjectWriter should also + // extend BaseElement to keep track of the location in the input tree. + class PROTOBUF_EXPORT BaseElement { + public: + // Takes ownership of the parent Element. + explicit BaseElement(BaseElement* parent) + : parent_(parent), + level_(parent == nullptr ? 0 : parent->level() + 1) {} + virtual ~BaseElement() {} + + // Releases ownership of the parent and returns a pointer to it. + template <typename ElementType> + ElementType* pop() { + return down_cast<ElementType*>(parent_.release()); + } + + // Returns true if this element is the root. + bool is_root() const { return parent_ == nullptr; } + + // Returns the number of hops from this element to the root element. + int level() const { return level_; } + + protected: + // Returns pointer to parent element without releasing ownership. + virtual BaseElement* parent() const { return parent_.get(); } + + private: + // Pointer to the parent Element. + std::unique_ptr<BaseElement> parent_; + + // Number of hops to the root Element. + // The root Element has nullptr parent_ and a level_ of 0. + const int level_; + + GOOGLE_DISALLOW_IMPLICIT_CONSTRUCTORS(BaseElement); + }; + + StructuredObjectWriter() {} + + // Returns the current element. Used for indentation and name overrides. + virtual BaseElement* element() = 0; + + private: + // Do not add any data members to this class. + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(StructuredObjectWriter); +}; + +} // namespace converter +} // namespace util +} // namespace protobuf +} // namespace google + +#include <google/protobuf/port_undef.inc> + +#endif // GOOGLE_PROTOBUF_UTIL_INTERNAL_STRUCTURED_OBJECTWRITER_H__ diff --git a/toolkit/components/protobuf/src/google/protobuf/util/internal/type_info.cc b/toolkit/components/protobuf/src/google/protobuf/util/internal/type_info.cc new file mode 100644 index 0000000000..b6cf5366ae --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/util/internal/type_info.cc @@ -0,0 +1,182 @@ +// 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. + +#include <google/protobuf/util/internal/type_info.h> + +#include <map> +#include <set> + +#include <google/protobuf/stubs/common.h> +#include <google/protobuf/type.pb.h> +#include <google/protobuf/stubs/status.h> +#include <google/protobuf/stubs/statusor.h> +#include <google/protobuf/stubs/strutil.h> +#include <google/protobuf/util/internal/utility.h> +#include <google/protobuf/stubs/map_util.h> +#include <google/protobuf/stubs/status.h> + +namespace google { +namespace protobuf { +namespace util { +namespace converter { + +namespace { +// A TypeInfo that looks up information provided by a TypeResolver. +class TypeInfoForTypeResolver : public TypeInfo { + public: + explicit TypeInfoForTypeResolver(TypeResolver* type_resolver) + : type_resolver_(type_resolver) {} + + ~TypeInfoForTypeResolver() override { + DeleteCachedTypes(&cached_types_); + DeleteCachedTypes(&cached_enums_); + } + + util::StatusOr<const google::protobuf::Type*> ResolveTypeUrl( + StringPiece type_url) const override { + std::map<StringPiece, StatusOrType>::iterator it = + cached_types_.find(type_url); + if (it != cached_types_.end()) { + return it->second; + } + // Stores the string value so it can be referenced using StringPiece in the + // cached_types_ map. + const std::string& string_type_url = + *string_storage_.insert(std::string(type_url)).first; + std::unique_ptr<google::protobuf::Type> type(new google::protobuf::Type()); + util::Status status = + type_resolver_->ResolveMessageType(string_type_url, type.get()); + StatusOrType result = + status.ok() ? StatusOrType(type.release()) : StatusOrType(status); + cached_types_[string_type_url] = result; + return result; + } + + const google::protobuf::Type* GetTypeByTypeUrl( + StringPiece type_url) const override { + StatusOrType result = ResolveTypeUrl(type_url); + return result.ok() ? result.value() : NULL; + } + + const google::protobuf::Enum* GetEnumByTypeUrl( + StringPiece type_url) const override { + std::map<StringPiece, StatusOrEnum>::iterator it = + cached_enums_.find(type_url); + if (it != cached_enums_.end()) { + return it->second.ok() ? it->second.value() : NULL; + } + // Stores the string value so it can be referenced using StringPiece in the + // cached_enums_ map. + const std::string& string_type_url = + *string_storage_.insert(std::string(type_url)).first; + std::unique_ptr<google::protobuf::Enum> enum_type( + new google::protobuf::Enum()); + util::Status status = + type_resolver_->ResolveEnumType(string_type_url, enum_type.get()); + StatusOrEnum result = + status.ok() ? StatusOrEnum(enum_type.release()) : StatusOrEnum(status); + cached_enums_[string_type_url] = result; + return result.ok() ? result.value() : NULL; + } + + const google::protobuf::Field* FindField( + const google::protobuf::Type* type, + StringPiece camel_case_name) const override { + std::map<const google::protobuf::Type*, CamelCaseNameTable>::const_iterator + it = indexed_types_.find(type); + const CamelCaseNameTable& camel_case_name_table = + (it == indexed_types_.end()) + ? PopulateNameLookupTable(type, &indexed_types_[type]) + : it->second; + StringPiece name = FindWithDefault( + camel_case_name_table, camel_case_name, StringPiece()); + if (name.empty()) { + // Didn't find a mapping. Use whatever provided. + name = camel_case_name; + } + return FindFieldInTypeOrNull(type, name); + } + + private: + typedef util::StatusOr<const google::protobuf::Type*> StatusOrType; + typedef util::StatusOr<const google::protobuf::Enum*> StatusOrEnum; + typedef std::map<StringPiece, StringPiece> CamelCaseNameTable; + + template <typename T> + static void DeleteCachedTypes(std::map<StringPiece, T>* cached_types) { + for (typename std::map<StringPiece, T>::iterator it = + cached_types->begin(); + it != cached_types->end(); ++it) { + if (it->second.ok()) { + delete it->second.value(); + } + } + } + + const CamelCaseNameTable& PopulateNameLookupTable( + const google::protobuf::Type* type, + CamelCaseNameTable* camel_case_name_table) const { + for (int i = 0; i < type->fields_size(); ++i) { + const google::protobuf::Field& field = type->fields(i); + StringPiece name = field.name(); + StringPiece camel_case_name = field.json_name(); + const StringPiece* existing = InsertOrReturnExisting( + camel_case_name_table, camel_case_name, name); + if (existing && *existing != name) { + GOOGLE_LOG(WARNING) << "Field '" << name << "' and '" << *existing + << "' map to the same camel case name '" << camel_case_name + << "'."; + } + } + return *camel_case_name_table; + } + + TypeResolver* type_resolver_; + + // Stores string values that will be referenced by StringPieces in + // cached_types_, cached_enums_. + mutable std::set<std::string> string_storage_; + + mutable std::map<StringPiece, StatusOrType> cached_types_; + mutable std::map<StringPiece, StatusOrEnum> cached_enums_; + + mutable std::map<const google::protobuf::Type*, CamelCaseNameTable> + indexed_types_; +}; +} // namespace + +TypeInfo* TypeInfo::NewTypeInfo(TypeResolver* type_resolver) { + return new TypeInfoForTypeResolver(type_resolver); +} + +} // namespace converter +} // namespace util +} // namespace protobuf +} // namespace google diff --git a/toolkit/components/protobuf/src/google/protobuf/util/internal/type_info.h b/toolkit/components/protobuf/src/google/protobuf/util/internal/type_info.h new file mode 100644 index 0000000000..257df5bad6 --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/util/internal/type_info.h @@ -0,0 +1,97 @@ +// 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. + +#ifndef GOOGLE_PROTOBUF_UTIL_INTERNAL_TYPE_INFO_H__ +#define GOOGLE_PROTOBUF_UTIL_INTERNAL_TYPE_INFO_H__ + +#include <google/protobuf/stubs/common.h> +#include <google/protobuf/type.pb.h> +#include <google/protobuf/stubs/statusor.h> +#include <google/protobuf/stubs/strutil.h> +#include <google/protobuf/util/type_resolver.h> +#include <google/protobuf/stubs/status.h> + +// Must be included last. +#include <google/protobuf/port_def.inc> + +namespace google { +namespace protobuf { +namespace util { +namespace converter { +// Internal helper class for type resolving. Note that this class is not +// thread-safe and should only be accessed in one thread. +class PROTOBUF_EXPORT TypeInfo { + public: + TypeInfo() {} + virtual ~TypeInfo() {} + + // Resolves a type url into a Type. If the type url is invalid, returns + // INVALID_ARGUMENT error status. If the type url is valid but the + // corresponding type cannot be found, returns a NOT_FOUND error status. + // + // This TypeInfo class retains the ownership of the returned pointer. + virtual util::StatusOr<const google::protobuf::Type*> ResolveTypeUrl( + StringPiece type_url) const = 0; + + // Resolves a type url into a Type. Like ResolveTypeUrl() but returns + // NULL if the type url is invalid or the type cannot be found. + // + // This TypeInfo class retains the ownership of the returned pointer. + virtual const google::protobuf::Type* GetTypeByTypeUrl( + StringPiece type_url) const = 0; + + // Resolves a type url for an enum. Returns NULL if the type url is + // invalid or the type cannot be found. + // + // This TypeInfo class retains the ownership of the returned pointer. + virtual const google::protobuf::Enum* GetEnumByTypeUrl( + StringPiece type_url) const = 0; + + // Looks up a field in the specified type given a CamelCase name. + virtual const google::protobuf::Field* FindField( + const google::protobuf::Type* type, + StringPiece camel_case_name) const = 0; + + // Creates a TypeInfo object that looks up type information from a + // TypeResolver. Caller takes ownership of the returned pointer. + static TypeInfo* NewTypeInfo(TypeResolver* type_resolver); + + private: + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(TypeInfo); +}; + +} // namespace converter +} // namespace util +} // namespace protobuf +} // namespace google + +#include <google/protobuf/port_undef.inc> + +#endif // GOOGLE_PROTOBUF_UTIL_INTERNAL_TYPE_INFO_H__ diff --git a/toolkit/components/protobuf/src/google/protobuf/util/internal/utility.cc b/toolkit/components/protobuf/src/google/protobuf/util/internal/utility.cc new file mode 100644 index 0000000000..918ee17d9b --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/util/internal/utility.cc @@ -0,0 +1,416 @@ +// 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. + +#include <google/protobuf/util/internal/utility.h> + +#include <algorithm> +#include <cmath> +#include <cstdint> +#include <limits> + +#include <google/protobuf/stubs/callback.h> +#include <google/protobuf/stubs/common.h> +#include <google/protobuf/stubs/logging.h> +#include <google/protobuf/wrappers.pb.h> +#include <google/protobuf/descriptor.pb.h> +#include <google/protobuf/descriptor.h> +#include <google/protobuf/stubs/strutil.h> +#include <google/protobuf/util/internal/constants.h> +#include <google/protobuf/stubs/map_util.h> + +// clang-format off +#include <google/protobuf/port_def.inc> +// clang-format on + +namespace google { +namespace protobuf { +namespace util { +namespace converter { + +bool GetBoolOptionOrDefault( + const RepeatedPtrField<google::protobuf::Option>& options, + StringPiece option_name, bool default_value) { + const google::protobuf::Option* opt = FindOptionOrNull(options, option_name); + if (opt == nullptr) { + return default_value; + } + return GetBoolFromAny(opt->value()); +} + +int64_t GetInt64OptionOrDefault( + const RepeatedPtrField<google::protobuf::Option>& options, + StringPiece option_name, int64_t default_value) { + const google::protobuf::Option* opt = FindOptionOrNull(options, option_name); + if (opt == nullptr) { + return default_value; + } + return GetInt64FromAny(opt->value()); +} + +double GetDoubleOptionOrDefault( + const RepeatedPtrField<google::protobuf::Option>& options, + StringPiece option_name, double default_value) { + const google::protobuf::Option* opt = FindOptionOrNull(options, option_name); + if (opt == nullptr) { + return default_value; + } + return GetDoubleFromAny(opt->value()); +} + +std::string GetStringOptionOrDefault( + const RepeatedPtrField<google::protobuf::Option>& options, + StringPiece option_name, StringPiece default_value) { + const google::protobuf::Option* opt = FindOptionOrNull(options, option_name); + if (opt == nullptr) { + return std::string(default_value); + } + return GetStringFromAny(opt->value()); +} + +template <typename T> +void ParseFromAny(const std::string& data, T* result) { + result->ParseFromString(data); +} + +// Returns a boolean value contained in Any type. +// TODO(skarvaje): Add type checking & error messages here. +bool GetBoolFromAny(const google::protobuf::Any& any) { + google::protobuf::BoolValue b; + ParseFromAny(any.value(), &b); + return b.value(); +} + +int64_t GetInt64FromAny(const google::protobuf::Any& any) { + google::protobuf::Int64Value i; + ParseFromAny(any.value(), &i); + return i.value(); +} + +double GetDoubleFromAny(const google::protobuf::Any& any) { + google::protobuf::DoubleValue i; + ParseFromAny(any.value(), &i); + return i.value(); +} + +std::string GetStringFromAny(const google::protobuf::Any& any) { + google::protobuf::StringValue s; + ParseFromAny(any.value(), &s); + return s.value(); +} + +const StringPiece GetTypeWithoutUrl(StringPiece type_url) { + if (type_url.size() > kTypeUrlSize && type_url[kTypeUrlSize] == '/') { + return type_url.substr(kTypeUrlSize + 1); + } else { + size_t idx = type_url.rfind('/'); + if (idx != type_url.npos) { + type_url.remove_prefix(idx + 1); + } + return type_url; + } +} + +const std::string GetFullTypeWithUrl(StringPiece simple_type) { + return StrCat(kTypeServiceBaseUrl, "/", simple_type); +} + +const google::protobuf::Option* FindOptionOrNull( + const RepeatedPtrField<google::protobuf::Option>& options, + StringPiece option_name) { + for (int i = 0; i < options.size(); ++i) { + const google::protobuf::Option& opt = options.Get(i); + if (opt.name() == option_name) { + return &opt; + } + } + return nullptr; +} + +const google::protobuf::Field* FindFieldInTypeOrNull( + const google::protobuf::Type* type, StringPiece field_name) { + if (type != nullptr) { + for (int i = 0; i < type->fields_size(); ++i) { + const google::protobuf::Field& field = type->fields(i); + if (field.name() == field_name) { + return &field; + } + } + } + return nullptr; +} + +const google::protobuf::Field* FindJsonFieldInTypeOrNull( + const google::protobuf::Type* type, StringPiece json_name) { + if (type != nullptr) { + for (int i = 0; i < type->fields_size(); ++i) { + const google::protobuf::Field& field = type->fields(i); + if (field.json_name() == json_name) { + return &field; + } + } + } + return nullptr; +} + +const google::protobuf::Field* FindFieldInTypeByNumberOrNull( + const google::protobuf::Type* type, int32_t number) { + if (type != nullptr) { + for (int i = 0; i < type->fields_size(); ++i) { + const google::protobuf::Field& field = type->fields(i); + if (field.number() == number) { + return &field; + } + } + } + return nullptr; +} + +const google::protobuf::EnumValue* FindEnumValueByNameOrNull( + const google::protobuf::Enum* enum_type, StringPiece enum_name) { + if (enum_type != nullptr) { + for (int i = 0; i < enum_type->enumvalue_size(); ++i) { + const google::protobuf::EnumValue& enum_value = enum_type->enumvalue(i); + if (enum_value.name() == enum_name) { + return &enum_value; + } + } + } + return nullptr; +} + +const google::protobuf::EnumValue* FindEnumValueByNumberOrNull( + const google::protobuf::Enum* enum_type, int32_t value) { + if (enum_type != nullptr) { + for (int i = 0; i < enum_type->enumvalue_size(); ++i) { + const google::protobuf::EnumValue& enum_value = enum_type->enumvalue(i); + if (enum_value.number() == value) { + return &enum_value; + } + } + } + return nullptr; +} + +const google::protobuf::EnumValue* FindEnumValueByNameWithoutUnderscoreOrNull( + const google::protobuf::Enum* enum_type, StringPiece enum_name) { + if (enum_type != nullptr) { + for (int i = 0; i < enum_type->enumvalue_size(); ++i) { + const google::protobuf::EnumValue& enum_value = enum_type->enumvalue(i); + std::string enum_name_without_underscore = enum_value.name(); + + // Remove underscore from the name. + enum_name_without_underscore.erase( + std::remove(enum_name_without_underscore.begin(), + enum_name_without_underscore.end(), '_'), + enum_name_without_underscore.end()); + // Make the name uppercase. + for (std::string::iterator it = enum_name_without_underscore.begin(); + it != enum_name_without_underscore.end(); ++it) { + *it = ascii_toupper(*it); + } + + if (enum_name_without_underscore == enum_name) { + return &enum_value; + } + } + } + return nullptr; +} + +std::string EnumValueNameToLowerCamelCase(StringPiece input) { + std::string input_string(input); + std::transform(input_string.begin(), input_string.end(), input_string.begin(), + ::tolower); + return ToCamelCase(input_string); +} + +std::string ToCamelCase(StringPiece input) { + bool capitalize_next = false; + bool was_cap = true; + bool is_cap = false; + bool first_word = true; + std::string result; + result.reserve(input.size()); + + for (size_t i = 0; i < input.size(); ++i, was_cap = is_cap) { + is_cap = ascii_isupper(input[i]); + if (input[i] == '_') { + capitalize_next = true; + if (!result.empty()) first_word = false; + continue; + } else if (first_word) { + // Consider when the current character B is capitalized, + // first word ends when: + // 1) following a lowercase: "...aB..." + // 2) followed by a lowercase: "...ABc..." + if (!result.empty() && is_cap && + (!was_cap || + (i + 1 < input.size() && ascii_islower(input[i + 1])))) { + first_word = false; + result.push_back(input[i]); + } else { + result.push_back(ascii_tolower(input[i])); + continue; + } + } else if (capitalize_next) { + capitalize_next = false; + if (ascii_islower(input[i])) { + result.push_back(ascii_toupper(input[i])); + continue; + } else { + result.push_back(input[i]); + continue; + } + } else { + result.push_back(ascii_tolower(input[i])); + } + } + return result; +} + +std::string ToSnakeCase(StringPiece input) { + bool was_not_underscore = false; // Initialize to false for case 1 (below) + bool was_not_cap = false; + std::string result; + result.reserve(input.size() << 1); + + for (size_t i = 0; i < input.size(); ++i) { + if (ascii_isupper(input[i])) { + // Consider when the current character B is capitalized: + // 1) At beginning of input: "B..." => "b..." + // (e.g. "Biscuit" => "biscuit") + // 2) Following a lowercase: "...aB..." => "...a_b..." + // (e.g. "gBike" => "g_bike") + // 3) At the end of input: "...AB" => "...ab" + // (e.g. "GoogleLAB" => "google_lab") + // 4) Followed by a lowercase: "...ABc..." => "...a_bc..." + // (e.g. "GBike" => "g_bike") + if (was_not_underscore && // case 1 out + (was_not_cap || // case 2 in, case 3 out + (i + 1 < input.size() && // case 3 out + ascii_islower(input[i + 1])))) { // case 4 in + // We add an underscore for case 2 and case 4. + result.push_back('_'); + } + result.push_back(ascii_tolower(input[i])); + was_not_underscore = true; + was_not_cap = false; + } else { + result.push_back(input[i]); + was_not_underscore = input[i] != '_'; + was_not_cap = true; + } + } + return result; +} + +std::set<std::string>* well_known_types_ = nullptr; +PROTOBUF_NAMESPACE_ID::internal::once_flag well_known_types_init_; +const char* well_known_types_name_array_[] = { + "google.protobuf.Timestamp", "google.protobuf.Duration", + "google.protobuf.DoubleValue", "google.protobuf.FloatValue", + "google.protobuf.Int64Value", "google.protobuf.UInt64Value", + "google.protobuf.Int32Value", "google.protobuf.UInt32Value", + "google.protobuf.BoolValue", "google.protobuf.StringValue", + "google.protobuf.BytesValue", "google.protobuf.FieldMask"}; + +void DeleteWellKnownTypes() { delete well_known_types_; } + +void InitWellKnownTypes() { + well_known_types_ = new std::set<std::string>; + for (int i = 0; i < GOOGLE_ARRAYSIZE(well_known_types_name_array_); ++i) { + well_known_types_->insert(well_known_types_name_array_[i]); + } + google::protobuf::internal::OnShutdown(&DeleteWellKnownTypes); +} + +bool IsWellKnownType(const std::string& type_name) { + PROTOBUF_NAMESPACE_ID::internal::call_once(well_known_types_init_, + InitWellKnownTypes); + return ContainsKey(*well_known_types_, type_name); +} + +bool IsValidBoolString(StringPiece bool_string) { + return bool_string == "true" || bool_string == "false" || + bool_string == "1" || bool_string == "0"; +} + +bool IsMap(const google::protobuf::Field& field, + const google::protobuf::Type& type) { + return field.cardinality() == google::protobuf::Field::CARDINALITY_REPEATED && + (GetBoolOptionOrDefault(type.options(), "map_entry", false) || + GetBoolOptionOrDefault(type.options(), + "google.protobuf.MessageOptions.map_entry", + false)); +} + +bool IsMessageSetWireFormat(const google::protobuf::Type& type) { + return GetBoolOptionOrDefault(type.options(), "message_set_wire_format", + false) || + GetBoolOptionOrDefault( + type.options(), + "google.protobuf.MessageOptions.message_set_wire_format", false); +} + +std::string DoubleAsString(double value) { + if (value == std::numeric_limits<double>::infinity()) return "Infinity"; + if (value == -std::numeric_limits<double>::infinity()) return "-Infinity"; + if (std::isnan(value)) return "NaN"; + + return SimpleDtoa(value); +} + +std::string FloatAsString(float value) { + if (std::isfinite(value)) return SimpleFtoa(value); + return DoubleAsString(value); +} + +bool SafeStrToFloat(StringPiece str, float* value) { + double double_value; + if (!safe_strtod(str, &double_value)) { + return false; + } + + if (std::isinf(double_value) || std::isnan(double_value)) return false; + + // Fail if the value is not representable in float. + if (double_value > std::numeric_limits<float>::max() || + double_value < -std::numeric_limits<float>::max()) { + return false; + } + + *value = static_cast<float>(double_value); + return true; +} + +} // namespace converter +} // namespace util +} // namespace protobuf +} // namespace google diff --git a/toolkit/components/protobuf/src/google/protobuf/util/internal/utility.h b/toolkit/components/protobuf/src/google/protobuf/util/internal/utility.h new file mode 100644 index 0000000000..79d6779735 --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/util/internal/utility.h @@ -0,0 +1,204 @@ +// 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. + +#ifndef GOOGLE_PROTOBUF_UTIL_INTERNAL_UTILITY_H__ +#define GOOGLE_PROTOBUF_UTIL_INTERNAL_UTILITY_H__ + +#include <cstdint> +#include <memory> +#include <string> +#include <utility> + +#include <google/protobuf/stubs/common.h> +#include <google/protobuf/stubs/logging.h> +#include <google/protobuf/any.pb.h> +#include <google/protobuf/type.pb.h> +#include <google/protobuf/repeated_field.h> +#include <google/protobuf/stubs/strutil.h> +#include <google/protobuf/stubs/statusor.h> +#include <google/protobuf/stubs/status.h> + +// Must be included last. +#include <google/protobuf/port_def.inc> + +namespace google { +namespace protobuf { +namespace util { +namespace converter { + +// Size of "type.googleapis.com" +static const int64_t kTypeUrlSize = 19; + +// Finds the tech option identified by option_name. Parses the boolean value and +// returns it. +// When the option with the given name is not found, default_value is returned. +PROTOBUF_EXPORT bool GetBoolOptionOrDefault( + const RepeatedPtrField<google::protobuf::Option>& options, + StringPiece option_name, bool default_value); + +// Returns int64 option value. If the option isn't found, returns the +// default_value. +PROTOBUF_EXPORT int64_t GetInt64OptionOrDefault( + const RepeatedPtrField<google::protobuf::Option>& options, + StringPiece option_name, int64_t default_value); + +// Returns double option value. If the option isn't found, returns the +// default_value. +PROTOBUF_EXPORT double GetDoubleOptionOrDefault( + const RepeatedPtrField<google::protobuf::Option>& options, + StringPiece option_name, double default_value); + +// Returns string option value. If the option isn't found, returns the +// default_value. +PROTOBUF_EXPORT std::string GetStringOptionOrDefault( + const RepeatedPtrField<google::protobuf::Option>& options, + StringPiece option_name, StringPiece default_value); + +// Returns a boolean value contained in Any type. +// TODO(skarvaje): Make these utilities dealing with Any types more generic, +// add more error checking and move to a more public/shareable location so +// others can use. +PROTOBUF_EXPORT bool GetBoolFromAny(const google::protobuf::Any& any); + +// Returns int64 value contained in Any type. +PROTOBUF_EXPORT int64_t GetInt64FromAny(const google::protobuf::Any& any); + +// Returns double value contained in Any type. +PROTOBUF_EXPORT double GetDoubleFromAny(const google::protobuf::Any& any); + +// Returns string value contained in Any type. +PROTOBUF_EXPORT std::string GetStringFromAny(const google::protobuf::Any& any); + +// Returns the type string without the url prefix. e.g.: If the passed type is +// 'type.googleapis.com/tech.type.Bool', the returned value is 'tech.type.Bool'. +PROTOBUF_EXPORT const StringPiece GetTypeWithoutUrl( + StringPiece type_url); + +// Returns the simple_type with the base type url (kTypeServiceBaseUrl) +// prefixed. +// +// E.g: +// GetFullTypeWithUrl("google.protobuf.Timestamp") returns the string +// "type.googleapis.com/google.protobuf.Timestamp". +PROTOBUF_EXPORT const std::string GetFullTypeWithUrl( + StringPiece simple_type); + +// Finds and returns option identified by name and option_name within the +// provided map. Returns nullptr if none found. +const google::protobuf::Option* FindOptionOrNull( + const RepeatedPtrField<google::protobuf::Option>& options, + StringPiece option_name); + +// Finds and returns the field identified by field_name in the passed tech Type +// object. Returns nullptr if none found. +const google::protobuf::Field* FindFieldInTypeOrNull( + const google::protobuf::Type* type, StringPiece field_name); + +// Similar to FindFieldInTypeOrNull, but this looks up fields with given +// json_name. +const google::protobuf::Field* FindJsonFieldInTypeOrNull( + const google::protobuf::Type* type, StringPiece json_name); + +// Similar to FindFieldInTypeOrNull, but this looks up fields by number. +const google::protobuf::Field* FindFieldInTypeByNumberOrNull( + const google::protobuf::Type* type, int32_t number); + +// Finds and returns the EnumValue identified by enum_name in the passed tech +// Enum object. Returns nullptr if none found. +const google::protobuf::EnumValue* FindEnumValueByNameOrNull( + const google::protobuf::Enum* enum_type, StringPiece enum_name); + +// Finds and returns the EnumValue identified by value in the passed tech +// Enum object. Returns nullptr if none found. +const google::protobuf::EnumValue* FindEnumValueByNumberOrNull( + const google::protobuf::Enum* enum_type, int32_t value); + +// Finds and returns the EnumValue identified by enum_name without underscore in +// the passed tech Enum object. Returns nullptr if none found. +// For Ex. if enum_name is ACTIONANDADVENTURE it can get accepted if +// EnumValue's name is action_and_adventure or ACTION_AND_ADVENTURE. +const google::protobuf::EnumValue* FindEnumValueByNameWithoutUnderscoreOrNull( + const google::protobuf::Enum* enum_type, StringPiece enum_name); + +// Converts input to camel-case and returns it. +PROTOBUF_EXPORT std::string ToCamelCase(const StringPiece input); + +// Converts enum name string to camel-case and returns it. +std::string EnumValueNameToLowerCamelCase(const StringPiece input); + +// Converts input to snake_case and returns it. +PROTOBUF_EXPORT std::string ToSnakeCase(StringPiece input); + +// Returns true if type_name represents a well-known type. +PROTOBUF_EXPORT bool IsWellKnownType(const std::string& type_name); + +// Returns true if 'bool_string' represents a valid boolean value. Only "true", +// "false", "0" and "1" are allowed. +PROTOBUF_EXPORT bool IsValidBoolString(StringPiece bool_string); + +// Returns true if "field" is a protobuf map field based on its type. +PROTOBUF_EXPORT bool IsMap(const google::protobuf::Field& field, + const google::protobuf::Type& type); + +// Returns true if the given type has special MessageSet wire format. +bool IsMessageSetWireFormat(const google::protobuf::Type& type); + +// Infinity/NaN-aware conversion to string. +PROTOBUF_EXPORT std::string DoubleAsString(double value); +PROTOBUF_EXPORT std::string FloatAsString(float value); + +// Convert from int32, int64, uint32, uint64, double or float to string. +template <typename T> +std::string ValueAsString(T value) { + return StrCat(value); +} + +template <> +inline std::string ValueAsString(float value) { + return FloatAsString(value); +} + +template <> +inline std::string ValueAsString(double value) { + return DoubleAsString(value); +} + +// Converts a string to float. Unlike safe_strtof, conversion will fail if the +// value fits into double but not float (e.g., DBL_MAX). +PROTOBUF_EXPORT bool SafeStrToFloat(StringPiece str, float* value); + +} // namespace converter +} // namespace util +} // namespace protobuf +} // namespace google + +#include <google/protobuf/port_undef.inc> + +#endif // GOOGLE_PROTOBUF_UTIL_INTERNAL_UTILITY_H__ diff --git a/toolkit/components/protobuf/src/google/protobuf/util/json_format.proto b/toolkit/components/protobuf/src/google/protobuf/util/json_format.proto new file mode 100644 index 0000000000..7b7100d788 --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/util/json_format.proto @@ -0,0 +1,140 @@ +// 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. + +// Author: kenton@google.com (Kenton Varda) +// Based on original Protocol Buffers design by +// Sanjay Ghemawat, Jeff Dean, and others. +// +// A proto file we will use for unit testing. + +syntax = "proto2"; + +package protobuf_unittest; + +message TestFlagsAndStrings { + required int32 A = 1; + repeated group RepeatedGroup = 2 { + required string f = 3; + } +} + +message TestBase64ByteArrays { + required bytes a = 1; +} + +message TestJavaScriptJSON { + optional int32 a = 1; + optional float final = 2; + optional string in = 3; + optional string Var = 4; +} + +message TestJavaScriptOrderJSON1 { + optional int32 d = 1; + optional int32 c = 2; + optional bool x = 3; + optional int32 b = 4; + optional int32 a = 5; +} + +message TestJavaScriptOrderJSON2 { + optional int32 d = 1; + optional int32 c = 2; + optional bool x = 3; + optional int32 b = 4; + optional int32 a = 5; + repeated TestJavaScriptOrderJSON1 z = 6; +} + +message TestLargeInt { + required int64 a = 1; + required uint64 b = 2; +} + +message TestNumbers { + enum MyType { + OK = 0; + WARNING = 1; + ERROR = 2; + } + optional MyType a = 1; + optional int32 b = 2; + optional float c = 3; + optional bool d = 4; + optional double e = 5; + optional uint32 f = 6; +} + + +message TestCamelCase { + optional string normal_field = 1; + optional int32 CAPITAL_FIELD = 2; + optional int32 CamelCaseField = 3; +} + +message TestBoolMap { + map<bool, int32> bool_map = 1; +} + +message TestRecursion { + optional int32 value = 1; + optional TestRecursion child = 2; +} + +message TestStringMap { + map<string, string> string_map = 1; +} + +message TestStringSerializer { + optional string scalar_string = 1; + repeated string repeated_string = 2; + map<string, string> string_map = 3; +} + +message TestMessageWithExtension { + extensions 100 to max; +} + +message TestExtension { + extend TestMessageWithExtension { + optional TestExtension ext = 100; + } + optional string value = 1; +} + +enum EnumValue { + PROTOCOL = 0; + BUFFER = 1; + DEFAULT = 2; +} + +message TestDefaultEnumValue { + optional EnumValue enum_value = 1 [default = DEFAULT]; +} diff --git a/toolkit/components/protobuf/src/google/protobuf/util/json_format_proto3.proto b/toolkit/components/protobuf/src/google/protobuf/util/json_format_proto3.proto new file mode 100644 index 0000000000..0eec9da319 --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/util/json_format_proto3.proto @@ -0,0 +1,194 @@ +// 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. + +syntax = "proto3"; + +package proto3; + +import "google/protobuf/any.proto"; +import "google/protobuf/duration.proto"; +import "google/protobuf/field_mask.proto"; +import "google/protobuf/struct.proto"; +import "google/protobuf/timestamp.proto"; +import "google/protobuf/wrappers.proto"; +import "google/protobuf/unittest.proto"; + +option java_package = "com.google.protobuf.util"; +option java_outer_classname = "JsonFormatProto3"; + +enum EnumType { + FOO = 0; + BAR = 1; +} + +message MessageType { + int32 value = 1; +} + +message TestMessage { + bool bool_value = 1; + int32 int32_value = 2; + int64 int64_value = 3; + uint32 uint32_value = 4; + uint64 uint64_value = 5; + float float_value = 6; + double double_value = 7; + string string_value = 8; + bytes bytes_value = 9; + EnumType enum_value = 10; + MessageType message_value = 11; + + repeated bool repeated_bool_value = 21; + repeated int32 repeated_int32_value = 22; + repeated int64 repeated_int64_value = 23; + repeated uint32 repeated_uint32_value = 24; + repeated uint64 repeated_uint64_value = 25; + repeated float repeated_float_value = 26; + repeated double repeated_double_value = 27; + repeated string repeated_string_value = 28; + repeated bytes repeated_bytes_value = 29; + repeated EnumType repeated_enum_value = 30; + repeated MessageType repeated_message_value = 31; +} + +message TestOneof { + // In JSON format oneof fields behave mostly the same as optional + // fields except that: + // 1. Oneof fields have field presence information and will be + // printed if it's set no matter whether it's the default value. + // 2. Multiple oneof fields in the same oneof cannot appear at the + // same time in the input. + oneof oneof_value { + int32 oneof_int32_value = 1; + string oneof_string_value = 2; + bytes oneof_bytes_value = 3; + EnumType oneof_enum_value = 4; + MessageType oneof_message_value = 5; + google.protobuf.NullValue oneof_null_value = 6; + } +} + +message TestMap { + map<bool, int32> bool_map = 1; + map<int32, int32> int32_map = 2; + map<int64, int32> int64_map = 3; + map<uint32, int32> uint32_map = 4; + map<uint64, int32> uint64_map = 5; + map<string, int32> string_map = 6; +} + +message TestNestedMap { + map<bool, int32> bool_map = 1; + map<int32, int32> int32_map = 2; + map<int64, int32> int64_map = 3; + map<uint32, int32> uint32_map = 4; + map<uint64, int32> uint64_map = 5; + map<string, int32> string_map = 6; + map<string, TestNestedMap> map_map = 7; +} + +message TestStringMap { + map<string, string> string_map = 1; +} + +message TestWrapper { + google.protobuf.BoolValue bool_value = 1; + google.protobuf.Int32Value int32_value = 2; + google.protobuf.Int64Value int64_value = 3; + google.protobuf.UInt32Value uint32_value = 4; + google.protobuf.UInt64Value uint64_value = 5; + google.protobuf.FloatValue float_value = 6; + google.protobuf.DoubleValue double_value = 7; + google.protobuf.StringValue string_value = 8; + google.protobuf.BytesValue bytes_value = 9; + + repeated google.protobuf.BoolValue repeated_bool_value = 11; + repeated google.protobuf.Int32Value repeated_int32_value = 12; + repeated google.protobuf.Int64Value repeated_int64_value = 13; + repeated google.protobuf.UInt32Value repeated_uint32_value = 14; + repeated google.protobuf.UInt64Value repeated_uint64_value = 15; + repeated google.protobuf.FloatValue repeated_float_value = 16; + repeated google.protobuf.DoubleValue repeated_double_value = 17; + repeated google.protobuf.StringValue repeated_string_value = 18; + repeated google.protobuf.BytesValue repeated_bytes_value = 19; +} + +message TestTimestamp { + google.protobuf.Timestamp value = 1; + repeated google.protobuf.Timestamp repeated_value = 2; +} + +message TestDuration { + google.protobuf.Duration value = 1; + repeated google.protobuf.Duration repeated_value = 2; +} + +message TestFieldMask { + google.protobuf.FieldMask value = 1; +} + +message TestStruct { + google.protobuf.Struct value = 1; + repeated google.protobuf.Struct repeated_value = 2; +} + +message TestAny { + google.protobuf.Any value = 1; + repeated google.protobuf.Any repeated_value = 2; +} + +message TestValue { + google.protobuf.Value value = 1; + repeated google.protobuf.Value repeated_value = 2; +} + +message TestListValue { + google.protobuf.ListValue value = 1; + repeated google.protobuf.ListValue repeated_value = 2; +} + +message TestBoolValue { + bool bool_value = 1; + map<bool, int32> bool_map = 2; +} + +message TestCustomJsonName { + int32 value = 1 [json_name = "@value"]; +} + +message TestExtensions { + .protobuf_unittest.TestAllExtensions extensions = 1; +} + +message TestEnumValue { + EnumType enum_value1 = 1; + EnumType enum_value2 = 2; + EnumType enum_value3 = 3; +} diff --git a/toolkit/components/protobuf/src/google/protobuf/util/json_util.cc b/toolkit/components/protobuf/src/google/protobuf/util/json_util.cc new file mode 100644 index 0000000000..c39c10d87b --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/util/json_util.cc @@ -0,0 +1,284 @@ +// 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. + +#include <google/protobuf/util/json_util.h> + +#include <google/protobuf/stubs/common.h> +#include <google/protobuf/stubs/once.h> +#include <google/protobuf/stubs/status.h> +#include <google/protobuf/stubs/bytestream.h> +#include <google/protobuf/stubs/strutil.h> +#include <google/protobuf/io/coded_stream.h> +#include <google/protobuf/io/zero_copy_stream.h> +#include <google/protobuf/util/internal/default_value_objectwriter.h> +#include <google/protobuf/util/internal/error_listener.h> +#include <google/protobuf/util/internal/json_objectwriter.h> +#include <google/protobuf/util/internal/json_stream_parser.h> +#include <google/protobuf/util/internal/protostream_objectsource.h> +#include <google/protobuf/util/internal/protostream_objectwriter.h> +#include <google/protobuf/util/type_resolver.h> +#include <google/protobuf/util/type_resolver_util.h> +#include <google/protobuf/stubs/status_macros.h> + +// clang-format off +#include <google/protobuf/port_def.inc> +// clang-format on + +namespace google { +namespace protobuf { +namespace util { + +namespace internal { +ZeroCopyStreamByteSink::~ZeroCopyStreamByteSink() { + if (buffer_size_ > 0) { + stream_->BackUp(buffer_size_); + } +} + +void ZeroCopyStreamByteSink::Append(const char* bytes, size_t len) { + while (true) { + if (len <= buffer_size_) { // NOLINT + memcpy(buffer_, bytes, len); + buffer_ = static_cast<char*>(buffer_) + len; + buffer_size_ -= len; + return; + } + if (buffer_size_ > 0) { + memcpy(buffer_, bytes, buffer_size_); + bytes += buffer_size_; + len -= buffer_size_; + } + if (!stream_->Next(&buffer_, &buffer_size_)) { + // There isn't a way for ByteSink to report errors. + buffer_size_ = 0; + return; + } + } +} +} // namespace internal + +util::Status BinaryToJsonStream(TypeResolver* resolver, + const std::string& type_url, + io::ZeroCopyInputStream* binary_input, + io::ZeroCopyOutputStream* json_output, + const JsonPrintOptions& options) { + io::CodedInputStream in_stream(binary_input); + google::protobuf::Type type; + RETURN_IF_ERROR(resolver->ResolveMessageType(type_url, &type)); + converter::ProtoStreamObjectSource::RenderOptions render_options; + render_options.use_ints_for_enums = options.always_print_enums_as_ints; + render_options.preserve_proto_field_names = + options.preserve_proto_field_names; + converter::ProtoStreamObjectSource proto_source(&in_stream, resolver, type, + render_options); + io::CodedOutputStream out_stream(json_output); + converter::JsonObjectWriter json_writer(options.add_whitespace ? " " : "", + &out_stream); + if (options.always_print_primitive_fields) { + converter::DefaultValueObjectWriter default_value_writer(resolver, type, + &json_writer); + default_value_writer.set_preserve_proto_field_names( + options.preserve_proto_field_names); + default_value_writer.set_print_enums_as_ints( + options.always_print_enums_as_ints); + return proto_source.WriteTo(&default_value_writer); + } else { + return proto_source.WriteTo(&json_writer); + } +} + +util::Status BinaryToJsonString(TypeResolver* resolver, + const std::string& type_url, + const std::string& binary_input, + std::string* json_output, + const JsonPrintOptions& options) { + io::ArrayInputStream input_stream(binary_input.data(), binary_input.size()); + io::StringOutputStream output_stream(json_output); + return BinaryToJsonStream(resolver, type_url, &input_stream, &output_stream, + options); +} + +namespace { +class StatusErrorListener : public converter::ErrorListener { + public: + StatusErrorListener() {} + ~StatusErrorListener() override {} + + util::Status GetStatus() { return status_; } + + void InvalidName(const converter::LocationTrackerInterface& loc, + StringPiece unknown_name, + StringPiece message) override { + std::string loc_string = GetLocString(loc); + if (!loc_string.empty()) { + loc_string.append(" "); + } + status_ = util::InvalidArgumentError( + StrCat(loc_string, unknown_name, ": ", message)); + } + + void InvalidValue(const converter::LocationTrackerInterface& loc, + StringPiece type_name, + StringPiece value) override { + status_ = util::InvalidArgumentError( + StrCat(GetLocString(loc), ": invalid value ", std::string(value), + " for type ", std::string(type_name))); + } + + void MissingField(const converter::LocationTrackerInterface& loc, + StringPiece missing_name) override { + status_ = util::InvalidArgumentError(StrCat( + GetLocString(loc), ": missing field ", std::string(missing_name))); + } + + private: + util::Status status_; + + std::string GetLocString(const converter::LocationTrackerInterface& loc) { + std::string loc_string = loc.ToString(); + StripWhitespace(&loc_string); + if (!loc_string.empty()) { + loc_string = StrCat("(", loc_string, ")"); + } + return loc_string; + } + + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(StatusErrorListener); +}; +} // namespace + +util::Status JsonToBinaryStream(TypeResolver* resolver, + const std::string& type_url, + io::ZeroCopyInputStream* json_input, + io::ZeroCopyOutputStream* binary_output, + const JsonParseOptions& options) { + google::protobuf::Type type; + RETURN_IF_ERROR(resolver->ResolveMessageType(type_url, &type)); + internal::ZeroCopyStreamByteSink sink(binary_output); + StatusErrorListener listener; + converter::ProtoStreamObjectWriter::Options proto_writer_options; + proto_writer_options.ignore_unknown_fields = options.ignore_unknown_fields; + proto_writer_options.ignore_unknown_enum_values = + options.ignore_unknown_fields; + proto_writer_options.case_insensitive_enum_parsing = + options.case_insensitive_enum_parsing; + converter::ProtoStreamObjectWriter proto_writer( + resolver, type, &sink, &listener, proto_writer_options); + + converter::JsonStreamParser parser(&proto_writer); + const void* buffer; + int length; + while (json_input->Next(&buffer, &length)) { + if (length == 0) continue; + RETURN_IF_ERROR(parser.Parse( + StringPiece(static_cast<const char*>(buffer), length))); + } + RETURN_IF_ERROR(parser.FinishParse()); + + return listener.GetStatus(); +} + +util::Status JsonToBinaryString(TypeResolver* resolver, + const std::string& type_url, + StringPiece json_input, + std::string* binary_output, + const JsonParseOptions& options) { + io::ArrayInputStream input_stream(json_input.data(), json_input.size()); + io::StringOutputStream output_stream(binary_output); + return JsonToBinaryStream(resolver, type_url, &input_stream, &output_stream, + options); +} + +namespace { +const char* kTypeUrlPrefix = "type.googleapis.com"; +TypeResolver* generated_type_resolver_ = nullptr; +PROTOBUF_NAMESPACE_ID::internal::once_flag generated_type_resolver_init_; + +std::string GetTypeUrl(const Message& message) { + return std::string(kTypeUrlPrefix) + "/" + + message.GetDescriptor()->full_name(); +} + +void DeleteGeneratedTypeResolver() { // NOLINT + delete generated_type_resolver_; +} + +void InitGeneratedTypeResolver() { + generated_type_resolver_ = NewTypeResolverForDescriptorPool( + kTypeUrlPrefix, DescriptorPool::generated_pool()); + ::google::protobuf::internal::OnShutdown(&DeleteGeneratedTypeResolver); +} + +TypeResolver* GetGeneratedTypeResolver() { + PROTOBUF_NAMESPACE_ID::internal::call_once(generated_type_resolver_init_, + InitGeneratedTypeResolver); + return generated_type_resolver_; +} +} // namespace + +util::Status MessageToJsonString(const Message& message, std::string* output, + const JsonOptions& options) { + const DescriptorPool* pool = message.GetDescriptor()->file()->pool(); + TypeResolver* resolver = + pool == DescriptorPool::generated_pool() + ? GetGeneratedTypeResolver() + : NewTypeResolverForDescriptorPool(kTypeUrlPrefix, pool); + util::Status result = + BinaryToJsonString(resolver, GetTypeUrl(message), + message.SerializeAsString(), output, options); + if (pool != DescriptorPool::generated_pool()) { + delete resolver; + } + return result; +} + +util::Status JsonStringToMessage(StringPiece input, Message* message, + const JsonParseOptions& options) { + const DescriptorPool* pool = message->GetDescriptor()->file()->pool(); + TypeResolver* resolver = + pool == DescriptorPool::generated_pool() + ? GetGeneratedTypeResolver() + : NewTypeResolverForDescriptorPool(kTypeUrlPrefix, pool); + std::string binary; + util::Status result = JsonToBinaryString(resolver, GetTypeUrl(*message), + input, &binary, options); + if (result.ok() && !message->ParseFromString(binary)) { + result = util::InvalidArgumentError( + "JSON transcoder produced invalid protobuf output."); + } + if (pool != DescriptorPool::generated_pool()) { + delete resolver; + } + return result; +} + +} // namespace util +} // namespace protobuf +} // namespace google diff --git a/toolkit/components/protobuf/src/google/protobuf/util/json_util.h b/toolkit/components/protobuf/src/google/protobuf/util/json_util.h new file mode 100644 index 0000000000..0f1c4d8b5f --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/util/json_util.h @@ -0,0 +1,204 @@ +// 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. + +// Utility functions to convert between protobuf binary format and proto3 JSON +// format. +#ifndef GOOGLE_PROTOBUF_UTIL_JSON_UTIL_H__ +#define GOOGLE_PROTOBUF_UTIL_JSON_UTIL_H__ + +#include <google/protobuf/stubs/bytestream.h> +#include <google/protobuf/stubs/status.h> +#include <google/protobuf/stubs/strutil.h> +#include <google/protobuf/message.h> +#include <google/protobuf/util/type_resolver.h> + +// Must be included last. +#include <google/protobuf/port_def.inc> + +namespace google { +namespace protobuf { +namespace io { +class ZeroCopyInputStream; +class ZeroCopyOutputStream; +} // namespace io +namespace util { + +struct JsonParseOptions { + // Whether to ignore unknown JSON fields during parsing + bool ignore_unknown_fields; + + // If true, when a lowercase enum value fails to parse, try convert it to + // UPPER_CASE and see if it matches a valid enum. + // WARNING: This option exists only to preserve legacy behavior. Avoid using + // this option. If your enum needs to support different casing, consider using + // allow_alias instead. + bool case_insensitive_enum_parsing; + + JsonParseOptions() + : ignore_unknown_fields(false), case_insensitive_enum_parsing(false) {} +}; + +struct JsonPrintOptions { + // Whether to add spaces, line breaks and indentation to make the JSON output + // easy to read. + bool add_whitespace; + // Whether to always print primitive fields. By default proto3 primitive + // fields with default values will be omitted in JSON output. For example, an + // int32 field set to 0 will be omitted. Set this flag to true will override + // the default behavior and print primitive fields regardless of their values. + bool always_print_primitive_fields; + // Whether to always print enums as ints. By default they are rendered as + // strings. + bool always_print_enums_as_ints; + // Whether to preserve proto field names + bool preserve_proto_field_names; + + JsonPrintOptions() + : add_whitespace(false), + always_print_primitive_fields(false), + always_print_enums_as_ints(false), + preserve_proto_field_names(false) {} +}; + +// DEPRECATED. Use JsonPrintOptions instead. +typedef JsonPrintOptions JsonOptions; + +// Converts from protobuf message to JSON and appends it to |output|. This is a +// simple wrapper of BinaryToJsonString(). It will use the DescriptorPool of the +// passed-in message to resolve Any types. +PROTOBUF_EXPORT util::Status MessageToJsonString(const Message& message, + std::string* output, + const JsonOptions& options); + +inline util::Status MessageToJsonString(const Message& message, + std::string* output) { + return MessageToJsonString(message, output, JsonOptions()); +} + +// Converts from JSON to protobuf message. This is a simple wrapper of +// JsonStringToBinary(). It will use the DescriptorPool of the passed-in +// message to resolve Any types. +PROTOBUF_EXPORT util::Status JsonStringToMessage( + StringPiece input, Message* message, const JsonParseOptions& options); + +inline util::Status JsonStringToMessage(StringPiece input, + Message* message) { + return JsonStringToMessage(input, message, JsonParseOptions()); +} + +// Converts protobuf binary data to JSON. +// The conversion will fail if: +// 1. TypeResolver fails to resolve a type. +// 2. input is not valid protobuf wire format, or conflicts with the type +// information returned by TypeResolver. +// Note that unknown fields will be discarded silently. +PROTOBUF_EXPORT util::Status BinaryToJsonStream( + TypeResolver* resolver, const std::string& type_url, + io::ZeroCopyInputStream* binary_input, + io::ZeroCopyOutputStream* json_output, const JsonPrintOptions& options); + +inline util::Status BinaryToJsonStream(TypeResolver* resolver, + const std::string& type_url, + io::ZeroCopyInputStream* binary_input, + io::ZeroCopyOutputStream* json_output) { + return BinaryToJsonStream(resolver, type_url, binary_input, json_output, + JsonPrintOptions()); +} + +PROTOBUF_EXPORT util::Status BinaryToJsonString( + TypeResolver* resolver, const std::string& type_url, + const std::string& binary_input, std::string* json_output, + const JsonPrintOptions& options); + +inline util::Status BinaryToJsonString(TypeResolver* resolver, + const std::string& type_url, + const std::string& binary_input, + std::string* json_output) { + return BinaryToJsonString(resolver, type_url, binary_input, json_output, + JsonPrintOptions()); +} + +// Converts JSON data to protobuf binary format. +// The conversion will fail if: +// 1. TypeResolver fails to resolve a type. +// 2. input is not valid JSON format, or conflicts with the type +// information returned by TypeResolver. +PROTOBUF_EXPORT util::Status JsonToBinaryStream( + TypeResolver* resolver, const std::string& type_url, + io::ZeroCopyInputStream* json_input, + io::ZeroCopyOutputStream* binary_output, const JsonParseOptions& options); + +inline util::Status JsonToBinaryStream( + TypeResolver* resolver, const std::string& type_url, + io::ZeroCopyInputStream* json_input, + io::ZeroCopyOutputStream* binary_output) { + return JsonToBinaryStream(resolver, type_url, json_input, binary_output, + JsonParseOptions()); +} + +PROTOBUF_EXPORT util::Status JsonToBinaryString( + TypeResolver* resolver, const std::string& type_url, + StringPiece json_input, std::string* binary_output, + const JsonParseOptions& options); + +inline util::Status JsonToBinaryString(TypeResolver* resolver, + const std::string& type_url, + StringPiece json_input, + std::string* binary_output) { + return JsonToBinaryString(resolver, type_url, json_input, binary_output, + JsonParseOptions()); +} + +namespace internal { +// Internal helper class. Put in the header so we can write unit-tests for it. +class PROTOBUF_EXPORT ZeroCopyStreamByteSink : public strings::ByteSink { + public: + explicit ZeroCopyStreamByteSink(io::ZeroCopyOutputStream* stream) + : stream_(stream), buffer_(nullptr), buffer_size_(0) {} + ~ZeroCopyStreamByteSink() override; + + void Append(const char* bytes, size_t len) override; + + private: + io::ZeroCopyOutputStream* stream_; + void* buffer_; + int buffer_size_; + + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ZeroCopyStreamByteSink); +}; +} // namespace internal + +} // namespace util +} // namespace protobuf +} // namespace google + +#include <google/protobuf/port_undef.inc> + +#endif // GOOGLE_PROTOBUF_UTIL_JSON_UTIL_H__ diff --git a/toolkit/components/protobuf/src/google/protobuf/util/message_differencer.cc b/toolkit/components/protobuf/src/google/protobuf/util/message_differencer.cc new file mode 100644 index 0000000000..30560ed5f4 --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/util/message_differencer.cc @@ -0,0 +1,2246 @@ +// 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. + +// Author: jschorr@google.com (Joseph Schorr) +// Based on original Protocol Buffers design by +// Sanjay Ghemawat, Jeff Dean, and others. + +#include <google/protobuf/util/message_differencer.h> + +#include <algorithm> +#include <cstddef> +#include <cstdint> +#include <functional> +#include <limits> +#include <memory> +#include <utility> + +#include <google/protobuf/stubs/logging.h> +#include <google/protobuf/stubs/common.h> +#include <google/protobuf/io/printer.h> +#include <google/protobuf/io/zero_copy_stream.h> +#include <google/protobuf/io/zero_copy_stream_impl.h> +#include <google/protobuf/descriptor.pb.h> +#include <google/protobuf/descriptor.h> +#include <google/protobuf/dynamic_message.h> +#include <google/protobuf/generated_enum_reflection.h> +#include <google/protobuf/map_field.h> +#include <google/protobuf/message.h> +#include <google/protobuf/text_format.h> +#include <google/protobuf/stubs/strutil.h> +#include <google/protobuf/stubs/stringprintf.h> +#include <google/protobuf/util/field_comparator.h> + +// Always include as last one, otherwise it can break compilation +#include <google/protobuf/port_def.inc> + +namespace google { +namespace protobuf { + +namespace util { + +namespace { + +std::string PrintShortTextFormat(const google::protobuf::Message& message) { + std::string debug_string; + + google::protobuf::TextFormat::Printer printer; + printer.SetSingleLineMode(true); + printer.SetExpandAny(true); + + printer.PrintToString(message, &debug_string); + // Single line mode currently might have an extra space at the end. + if (!debug_string.empty() && debug_string[debug_string.size() - 1] == ' ') { + debug_string.resize(debug_string.size() - 1); + } + + return debug_string; +} + +} // namespace + +// A reporter to report the total number of diffs. +// TODO(ykzhu): we can improve this to take into account the value differencers. +class NumDiffsReporter : public google::protobuf::util::MessageDifferencer::Reporter { + public: + NumDiffsReporter() : num_diffs_(0) {} + + // Returns the total number of diffs. + int32_t GetNumDiffs() const { return num_diffs_; } + void Reset() { num_diffs_ = 0; } + + // Report that a field has been added into Message2. + void ReportAdded( + const google::protobuf::Message& /* message1 */, + const google::protobuf::Message& /* message2 */, + const std::vector<google::protobuf::util::MessageDifferencer::SpecificField>& + /*field_path*/) override { + ++num_diffs_; + } + + // Report that a field has been deleted from Message1. + void ReportDeleted( + const google::protobuf::Message& /* message1 */, + const google::protobuf::Message& /* message2 */, + const std::vector<google::protobuf::util::MessageDifferencer::SpecificField>& + /*field_path*/) override { + ++num_diffs_; + } + + // Report that the value of a field has been modified. + void ReportModified( + const google::protobuf::Message& /* message1 */, + const google::protobuf::Message& /* message2 */, + const std::vector<google::protobuf::util::MessageDifferencer::SpecificField>& + /*field_path*/) override { + ++num_diffs_; + } + + private: + int32_t num_diffs_; +}; + +// When comparing a repeated field as map, MultipleFieldMapKeyComparator can +// be used to specify multiple fields as key for key comparison. +// Two elements of a repeated field will be regarded as having the same key +// iff they have the same value for every specified key field. +// Note that you can also specify only one field as key. +class MessageDifferencer::MultipleFieldsMapKeyComparator + : public MessageDifferencer::MapKeyComparator { + public: + MultipleFieldsMapKeyComparator( + MessageDifferencer* message_differencer, + const std::vector<std::vector<const FieldDescriptor*> >& key_field_paths) + : message_differencer_(message_differencer), + key_field_paths_(key_field_paths) { + GOOGLE_CHECK(!key_field_paths_.empty()); + for (const auto& path : key_field_paths_) { + GOOGLE_CHECK(!path.empty()); + } + } + MultipleFieldsMapKeyComparator(MessageDifferencer* message_differencer, + const FieldDescriptor* key) + : message_differencer_(message_differencer) { + std::vector<const FieldDescriptor*> key_field_path; + key_field_path.push_back(key); + key_field_paths_.push_back(key_field_path); + } + bool IsMatch(const Message& message1, const Message& message2, + const std::vector<SpecificField>& parent_fields) const override { + for (const auto& path : key_field_paths_) { + if (!IsMatchInternal(message1, message2, parent_fields, path, 0)) { + return false; + } + } + return true; + } + + private: + bool IsMatchInternal( + const Message& message1, const Message& message2, + const std::vector<SpecificField>& parent_fields, + const std::vector<const FieldDescriptor*>& key_field_path, + int path_index) const { + const FieldDescriptor* field = key_field_path[path_index]; + std::vector<SpecificField> current_parent_fields(parent_fields); + if (path_index == static_cast<int64_t>(key_field_path.size() - 1)) { + if (field->is_map()) { + return message_differencer_->CompareMapField(message1, message2, field, + ¤t_parent_fields); + } else if (field->is_repeated()) { + return message_differencer_->CompareRepeatedField( + message1, message2, field, ¤t_parent_fields); + } else { + return message_differencer_->CompareFieldValueUsingParentFields( + message1, message2, field, -1, -1, ¤t_parent_fields); + } + } else { + const Reflection* reflection1 = message1.GetReflection(); + const Reflection* reflection2 = message2.GetReflection(); + bool has_field1 = reflection1->HasField(message1, field); + bool has_field2 = reflection2->HasField(message2, field); + if (!has_field1 && !has_field2) { + return true; + } + if (has_field1 != has_field2) { + return false; + } + SpecificField specific_field; + specific_field.field = field; + current_parent_fields.push_back(specific_field); + return IsMatchInternal(reflection1->GetMessage(message1, field), + reflection2->GetMessage(message2, field), + current_parent_fields, key_field_path, + path_index + 1); + } + } + MessageDifferencer* message_differencer_; + std::vector<std::vector<const FieldDescriptor*> > key_field_paths_; + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MultipleFieldsMapKeyComparator); +}; + +// Preserve the order when treating repeated field as SMART_LIST. The current +// implementation is to find the longest matching sequence from the first +// element. The optimal solution requires to use //util/diff/lcs.h, which is +// not open sourced yet. Overwrite this method if you want to have that. +// TODO(ykzhu): change to use LCS once it is open sourced. +void MatchIndicesPostProcessorForSmartList(std::vector<int>* match_list1, + std::vector<int>* match_list2) { + int last_matched_index = -1; + for (size_t i = 0; i < match_list1->size(); ++i) { + if (match_list1->at(i) < 0) { + continue; + } + if (last_matched_index < 0 || match_list1->at(i) > last_matched_index) { + last_matched_index = match_list1->at(i); + } else { + match_list2->at(match_list1->at(i)) = -1; + match_list1->at(i) = -1; + } + } +} + +void AddSpecificIndex( + google::protobuf::util::MessageDifferencer::SpecificField* specific_field, + const Message& message, const FieldDescriptor* field, int index) { + if (field->is_map()) { + const Reflection* reflection = message.GetReflection(); + specific_field->map_entry1 = + &reflection->GetRepeatedMessage(message, field, index); + } + specific_field->index = index; +} + +void AddSpecificNewIndex( + google::protobuf::util::MessageDifferencer::SpecificField* specific_field, + const Message& message, const FieldDescriptor* field, int index) { + if (field->is_map()) { + const Reflection* reflection = message.GetReflection(); + specific_field->map_entry2 = + &reflection->GetRepeatedMessage(message, field, index); + } + specific_field->new_index = index; +} + +MessageDifferencer::MapEntryKeyComparator::MapEntryKeyComparator( + MessageDifferencer* message_differencer) + : message_differencer_(message_differencer) {} + +bool MessageDifferencer::MapEntryKeyComparator::IsMatch( + const Message& message1, const Message& message2, + const std::vector<SpecificField>& parent_fields) const { + // Map entry has its key in the field with tag 1. See the comment for + // map_entry in MessageOptions. + const FieldDescriptor* key = message1.GetDescriptor()->FindFieldByNumber(1); + // If key is not present in message1 and we're doing partial comparison or if + // map key is explicitly ignored treat the field as set instead, + const bool treat_as_set = + (message_differencer_->scope() == PARTIAL && + !message1.GetReflection()->HasField(message1, key)) || + message_differencer_->IsIgnored(message1, message2, key, parent_fields); + + std::vector<SpecificField> current_parent_fields(parent_fields); + if (treat_as_set) { + return message_differencer_->Compare(message1, message2, + ¤t_parent_fields); + } + return message_differencer_->CompareFieldValueUsingParentFields( + message1, message2, key, -1, -1, ¤t_parent_fields); +} + +bool MessageDifferencer::Equals(const Message& message1, + const Message& message2) { + MessageDifferencer differencer; + + return differencer.Compare(message1, message2); +} + +bool MessageDifferencer::Equivalent(const Message& message1, + const Message& message2) { + MessageDifferencer differencer; + differencer.set_message_field_comparison(MessageDifferencer::EQUIVALENT); + + return differencer.Compare(message1, message2); +} + +bool MessageDifferencer::ApproximatelyEquals(const Message& message1, + const Message& message2) { + MessageDifferencer differencer; + differencer.set_float_comparison(MessageDifferencer::APPROXIMATE); + + return differencer.Compare(message1, message2); +} + +bool MessageDifferencer::ApproximatelyEquivalent(const Message& message1, + const Message& message2) { + MessageDifferencer differencer; + differencer.set_message_field_comparison(MessageDifferencer::EQUIVALENT); + differencer.set_float_comparison(MessageDifferencer::APPROXIMATE); + + return differencer.Compare(message1, message2); +} + +// =========================================================================== + +MessageDifferencer::MessageDifferencer() + : reporter_(NULL), + message_field_comparison_(EQUAL), + scope_(FULL), + repeated_field_comparison_(AS_LIST), + map_entry_key_comparator_(this), + report_matches_(false), + report_moves_(true), + report_ignores_(true), + output_string_(nullptr), + match_indices_for_smart_list_callback_( + MatchIndicesPostProcessorForSmartList) {} + +MessageDifferencer::~MessageDifferencer() { + for (MapKeyComparator* comparator : owned_key_comparators_) { + delete comparator; + } + for (IgnoreCriteria* criteria : ignore_criteria_) { + delete criteria; + } +} + +void MessageDifferencer::set_field_comparator(FieldComparator* comparator) { + GOOGLE_CHECK(comparator) << "Field comparator can't be NULL."; + field_comparator_kind_ = kFCBase; + field_comparator_.base = comparator; +} + +#ifdef PROTOBUF_FUTURE_BREAKING_CHANGES +void MessageDifferencer::set_field_comparator( + DefaultFieldComparator* comparator) { + GOOGLE_CHECK(comparator) << "Field comparator can't be NULL."; + field_comparator_kind_ = kFCDefault; + field_comparator_.default_impl = comparator; +} +#endif // PROTOBUF_FUTURE_BREAKING_CHANGES + +void MessageDifferencer::set_message_field_comparison( + MessageFieldComparison comparison) { + message_field_comparison_ = comparison; +} + +MessageDifferencer::MessageFieldComparison +MessageDifferencer::message_field_comparison() const { + return message_field_comparison_; +} + +void MessageDifferencer::set_scope(Scope scope) { scope_ = scope; } + +MessageDifferencer::Scope MessageDifferencer::scope() const { return scope_; } + +void MessageDifferencer::set_float_comparison(FloatComparison comparison) { + default_field_comparator_.set_float_comparison( + comparison == EXACT ? DefaultFieldComparator::EXACT + : DefaultFieldComparator::APPROXIMATE); +} + +void MessageDifferencer::set_repeated_field_comparison( + RepeatedFieldComparison comparison) { + repeated_field_comparison_ = comparison; +} + +MessageDifferencer::RepeatedFieldComparison +MessageDifferencer::repeated_field_comparison() const { + return repeated_field_comparison_; +} + +void MessageDifferencer::CheckRepeatedFieldComparisons( + const FieldDescriptor* field, + const RepeatedFieldComparison& new_comparison) { + GOOGLE_CHECK(field->is_repeated()) + << "Field must be repeated: " << field->full_name(); + const MapKeyComparator* key_comparator = GetMapKeyComparator(field); + GOOGLE_CHECK(key_comparator == NULL) + << "Cannot treat this repeated field as both MAP and " << new_comparison + << " for comparison. Field name is: " << field->full_name(); +} + +void MessageDifferencer::TreatAsSet(const FieldDescriptor* field) { + CheckRepeatedFieldComparisons(field, AS_SET); + repeated_field_comparisons_[field] = AS_SET; +} + +void MessageDifferencer::TreatAsSmartSet(const FieldDescriptor* field) { + CheckRepeatedFieldComparisons(field, AS_SMART_SET); + repeated_field_comparisons_[field] = AS_SMART_SET; +} + +void MessageDifferencer::SetMatchIndicesForSmartListCallback( + std::function<void(std::vector<int>*, std::vector<int>*)> callback) { + match_indices_for_smart_list_callback_ = callback; +} + +void MessageDifferencer::TreatAsList(const FieldDescriptor* field) { + CheckRepeatedFieldComparisons(field, AS_LIST); + repeated_field_comparisons_[field] = AS_LIST; +} + +void MessageDifferencer::TreatAsSmartList(const FieldDescriptor* field) { + CheckRepeatedFieldComparisons(field, AS_SMART_LIST); + repeated_field_comparisons_[field] = AS_SMART_LIST; +} + +void MessageDifferencer::TreatAsMap(const FieldDescriptor* field, + const FieldDescriptor* key) { + GOOGLE_CHECK_EQ(FieldDescriptor::CPPTYPE_MESSAGE, field->cpp_type()) + << "Field has to be message type. Field name is: " << field->full_name(); + GOOGLE_CHECK(key->containing_type() == field->message_type()) + << key->full_name() + << " must be a direct subfield within the repeated field " + << field->full_name() << ", not " << key->containing_type()->full_name(); + GOOGLE_CHECK(repeated_field_comparisons_.find(field) == + repeated_field_comparisons_.end()) + << "Cannot treat the same field as both " + << repeated_field_comparisons_[field] + << " and MAP. Field name is: " << field->full_name(); + MapKeyComparator* key_comparator = + new MultipleFieldsMapKeyComparator(this, key); + owned_key_comparators_.push_back(key_comparator); + map_field_key_comparator_[field] = key_comparator; +} + +void MessageDifferencer::TreatAsMapWithMultipleFieldsAsKey( + const FieldDescriptor* field, + const std::vector<const FieldDescriptor*>& key_fields) { + std::vector<std::vector<const FieldDescriptor*> > key_field_paths; + for (const FieldDescriptor* key_filed : key_fields) { + std::vector<const FieldDescriptor*> key_field_path; + key_field_path.push_back(key_filed); + key_field_paths.push_back(key_field_path); + } + TreatAsMapWithMultipleFieldPathsAsKey(field, key_field_paths); +} + +void MessageDifferencer::TreatAsMapWithMultipleFieldPathsAsKey( + const FieldDescriptor* field, + const std::vector<std::vector<const FieldDescriptor*> >& key_field_paths) { + GOOGLE_CHECK(field->is_repeated()) + << "Field must be repeated: " << field->full_name(); + GOOGLE_CHECK_EQ(FieldDescriptor::CPPTYPE_MESSAGE, field->cpp_type()) + << "Field has to be message type. Field name is: " << field->full_name(); + for (const auto& key_field_path : key_field_paths) { + for (size_t j = 0; j < key_field_path.size(); ++j) { + const FieldDescriptor* parent_field = + j == 0 ? field : key_field_path[j - 1]; + const FieldDescriptor* child_field = key_field_path[j]; + GOOGLE_CHECK(child_field->containing_type() == parent_field->message_type()) + << child_field->full_name() + << " must be a direct subfield within the field: " + << parent_field->full_name(); + if (j != 0) { + GOOGLE_CHECK_EQ(FieldDescriptor::CPPTYPE_MESSAGE, parent_field->cpp_type()) + << parent_field->full_name() << " has to be of type message."; + GOOGLE_CHECK(!parent_field->is_repeated()) + << parent_field->full_name() << " cannot be a repeated field."; + } + } + } + GOOGLE_CHECK(repeated_field_comparisons_.find(field) == + repeated_field_comparisons_.end()) + << "Cannot treat the same field as both " + << repeated_field_comparisons_[field] + << " and MAP. Field name is: " << field->full_name(); + MapKeyComparator* key_comparator = + new MultipleFieldsMapKeyComparator(this, key_field_paths); + owned_key_comparators_.push_back(key_comparator); + map_field_key_comparator_[field] = key_comparator; +} + +void MessageDifferencer::TreatAsMapUsingKeyComparator( + const FieldDescriptor* field, const MapKeyComparator* key_comparator) { + GOOGLE_CHECK(field->is_repeated()) + << "Field must be repeated: " << field->full_name(); + GOOGLE_CHECK(repeated_field_comparisons_.find(field) == + repeated_field_comparisons_.end()) + << "Cannot treat the same field as both " + << repeated_field_comparisons_[field] + << " and MAP. Field name is: " << field->full_name(); + map_field_key_comparator_[field] = key_comparator; +} + +void MessageDifferencer::AddIgnoreCriteria(IgnoreCriteria* ignore_criteria) { + ignore_criteria_.push_back(ignore_criteria); +} + +void MessageDifferencer::IgnoreField(const FieldDescriptor* field) { + ignored_fields_.insert(field); +} + +void MessageDifferencer::SetFractionAndMargin(const FieldDescriptor* field, + double fraction, double margin) { + default_field_comparator_.SetFractionAndMargin(field, fraction, margin); +} + +void MessageDifferencer::ReportDifferencesToString(std::string* output) { + GOOGLE_DCHECK(output) << "Specified output string was NULL"; + + output_string_ = output; + output_string_->clear(); +} + +void MessageDifferencer::ReportDifferencesTo(Reporter* reporter) { + // If an output string is set, clear it to prevent + // it superseding the specified reporter. + if (output_string_) { + output_string_ = NULL; + } + + reporter_ = reporter; +} + +bool MessageDifferencer::FieldBefore(const FieldDescriptor* field1, + const FieldDescriptor* field2) { + // Handle sentinel values (i.e. make sure NULLs are always ordered + // at the end of the list). + if (field1 == NULL) { + return false; + } + + if (field2 == NULL) { + return true; + } + + // Always order fields by their tag number + return (field1->number() < field2->number()); +} + +bool MessageDifferencer::Compare(const Message& message1, + const Message& message2) { + std::vector<SpecificField> parent_fields; + + bool result = false; + // Setup the internal reporter if need be. + if (output_string_) { + io::StringOutputStream output_stream(output_string_); + StreamReporter reporter(&output_stream); + reporter.SetMessages(message1, message2); + reporter_ = &reporter; + result = Compare(message1, message2, &parent_fields); + reporter_ = NULL; + } else { + result = Compare(message1, message2, &parent_fields); + } + return result; +} + +bool MessageDifferencer::CompareWithFields( + const Message& message1, const Message& message2, + const std::vector<const FieldDescriptor*>& message1_fields_arg, + const std::vector<const FieldDescriptor*>& message2_fields_arg) { + if (message1.GetDescriptor() != message2.GetDescriptor()) { + GOOGLE_LOG(DFATAL) << "Comparison between two messages with different " + << "descriptors."; + return false; + } + + std::vector<SpecificField> parent_fields; + + bool result = false; + + FieldDescriptorArray message1_fields(message1_fields_arg.size() + 1); + FieldDescriptorArray message2_fields(message2_fields_arg.size() + 1); + + std::copy(message1_fields_arg.cbegin(), message1_fields_arg.cend(), + message1_fields.begin()); + std::copy(message2_fields_arg.cbegin(), message2_fields_arg.cend(), + message2_fields.begin()); + + // Append sentinel values. + message1_fields[message1_fields_arg.size()] = nullptr; + message2_fields[message2_fields_arg.size()] = nullptr; + + std::sort(message1_fields.begin(), message1_fields.end(), FieldBefore); + std::sort(message2_fields.begin(), message2_fields.end(), FieldBefore); + + // Setup the internal reporter if need be. + if (output_string_) { + io::StringOutputStream output_stream(output_string_); + StreamReporter reporter(&output_stream); + reporter_ = &reporter; + result = CompareRequestedFieldsUsingSettings( + message1, message2, message1_fields, message2_fields, &parent_fields); + reporter_ = NULL; + } else { + result = CompareRequestedFieldsUsingSettings( + message1, message2, message1_fields, message2_fields, &parent_fields); + } + + return result; +} + +bool MessageDifferencer::Compare(const Message& message1, + const Message& message2, + std::vector<SpecificField>* parent_fields) { + const Descriptor* descriptor1 = message1.GetDescriptor(); + const Descriptor* descriptor2 = message2.GetDescriptor(); + if (descriptor1 != descriptor2) { + GOOGLE_LOG(DFATAL) << "Comparison between two messages with different " + << "descriptors. " << descriptor1->full_name() << " vs " + << descriptor2->full_name(); + return false; + } + + // Expand google.protobuf.Any payload if possible. + if (descriptor1->full_name() == internal::kAnyFullTypeName) { + std::unique_ptr<Message> data1; + std::unique_ptr<Message> data2; + if (unpack_any_field_.UnpackAny(message1, &data1) && + unpack_any_field_.UnpackAny(message2, &data2)) { + // Avoid DFATAL for different descriptors in google.protobuf.Any payloads. + if (data1->GetDescriptor() != data2->GetDescriptor()) { + return false; + } + return Compare(*data1, *data2, parent_fields); + } + } + const Reflection* reflection1 = message1.GetReflection(); + const Reflection* reflection2 = message2.GetReflection(); + + bool unknown_compare_result = true; + // Ignore unknown fields in EQUIVALENT mode + if (message_field_comparison_ != EQUIVALENT) { + const UnknownFieldSet& unknown_field_set1 = + reflection1->GetUnknownFields(message1); + const UnknownFieldSet& unknown_field_set2 = + reflection2->GetUnknownFields(message2); + if (!CompareUnknownFields(message1, message2, unknown_field_set1, + unknown_field_set2, parent_fields)) { + if (reporter_ == NULL) { + return false; + } + unknown_compare_result = false; + } + } + + FieldDescriptorArray message1_fields = RetrieveFields(message1, true); + FieldDescriptorArray message2_fields = RetrieveFields(message2, false); + + return CompareRequestedFieldsUsingSettings(message1, message2, + message1_fields, message2_fields, + parent_fields) && + unknown_compare_result; +} + +FieldDescriptorArray MessageDifferencer::RetrieveFields(const Message& message, + bool base_message) { + const Descriptor* descriptor = message.GetDescriptor(); + + tmp_message_fields_.clear(); + tmp_message_fields_.reserve(descriptor->field_count() + 1); + + const Reflection* reflection = message.GetReflection(); + if (descriptor->options().map_entry()) { + if (this->scope_ == PARTIAL && base_message) { + reflection->ListFields(message, &tmp_message_fields_); + } else { + // Map entry fields are always considered present. + for (int i = 0; i < descriptor->field_count(); i++) { + tmp_message_fields_.push_back(descriptor->field(i)); + } + } + } else { + reflection->ListFields(message, &tmp_message_fields_); + } + // Add sentinel values to deal with the + // case where the number of the fields in + // each list are different. + tmp_message_fields_.push_back(nullptr); + + FieldDescriptorArray message_fields(tmp_message_fields_.begin(), + tmp_message_fields_.end()); + + return message_fields; +} + +bool MessageDifferencer::CompareRequestedFieldsUsingSettings( + const Message& message1, const Message& message2, + const FieldDescriptorArray& message1_fields, + const FieldDescriptorArray& message2_fields, + std::vector<SpecificField>* parent_fields) { + if (scope_ == FULL) { + if (message_field_comparison_ == EQUIVALENT) { + // We need to merge the field lists of both messages (i.e. + // we are merely checking for a difference in field values, + // rather than the addition or deletion of fields). + FieldDescriptorArray fields_union = + CombineFields(message1_fields, FULL, message2_fields, FULL); + return CompareWithFieldsInternal(message1, message2, fields_union, + fields_union, parent_fields); + } else { + // Simple equality comparison, use the unaltered field lists. + return CompareWithFieldsInternal(message1, message2, message1_fields, + message2_fields, parent_fields); + } + } else { + if (message_field_comparison_ == EQUIVALENT) { + // We use the list of fields for message1 for both messages when + // comparing. This way, extra fields in message2 are ignored, + // and missing fields in message2 use their default value. + return CompareWithFieldsInternal(message1, message2, message1_fields, + message1_fields, parent_fields); + } else { + // We need to consider the full list of fields for message1 + // but only the intersection for message2. This way, any fields + // only present in message2 will be ignored, but any fields only + // present in message1 will be marked as a difference. + FieldDescriptorArray fields_intersection = + CombineFields(message1_fields, PARTIAL, message2_fields, PARTIAL); + return CompareWithFieldsInternal(message1, message2, message1_fields, + fields_intersection, parent_fields); + } + } +} + +FieldDescriptorArray MessageDifferencer::CombineFields( + const FieldDescriptorArray& fields1, Scope fields1_scope, + const FieldDescriptorArray& fields2, Scope fields2_scope) { + size_t index1 = 0; + size_t index2 = 0; + + tmp_message_fields_.clear(); + + while (index1 < fields1.size() && index2 < fields2.size()) { + const FieldDescriptor* field1 = fields1[index1]; + const FieldDescriptor* field2 = fields2[index2]; + + if (FieldBefore(field1, field2)) { + if (fields1_scope == FULL) { + tmp_message_fields_.push_back(fields1[index1]); + } + ++index1; + } else if (FieldBefore(field2, field1)) { + if (fields2_scope == FULL) { + tmp_message_fields_.push_back(fields2[index2]); + } + ++index2; + } else { + tmp_message_fields_.push_back(fields1[index1]); + ++index1; + ++index2; + } + } + + tmp_message_fields_.push_back(nullptr); + + FieldDescriptorArray combined_fields(tmp_message_fields_.begin(), + tmp_message_fields_.end()); + + return combined_fields; +} + +bool MessageDifferencer::CompareWithFieldsInternal( + const Message& message1, const Message& message2, + const FieldDescriptorArray& message1_fields, + const FieldDescriptorArray& message2_fields, + std::vector<SpecificField>* parent_fields) { + bool isDifferent = false; + int field_index1 = 0; + int field_index2 = 0; + + const Reflection* reflection1 = message1.GetReflection(); + const Reflection* reflection2 = message2.GetReflection(); + + while (true) { + const FieldDescriptor* field1 = message1_fields[field_index1]; + const FieldDescriptor* field2 = message2_fields[field_index2]; + + // Once we have reached sentinel values, we are done the comparison. + if (field1 == NULL && field2 == NULL) { + break; + } + + // Check for differences in the field itself. + if (FieldBefore(field1, field2)) { + // Field 1 is not in the field list for message 2. + if (IsIgnored(message1, message2, field1, *parent_fields)) { + // We are ignoring field1. Report the ignore and move on to + // the next field in message1_fields. + if (reporter_ != NULL) { + SpecificField specific_field; + specific_field.field = field1; + parent_fields->push_back(specific_field); + if (report_ignores_) { + reporter_->ReportIgnored(message1, message2, *parent_fields); + } + parent_fields->pop_back(); + } + ++field_index1; + continue; + } + + if (reporter_ != NULL) { + assert(field1 != NULL); + int count = field1->is_repeated() + ? reflection1->FieldSize(message1, field1) + : 1; + + for (int i = 0; i < count; ++i) { + SpecificField specific_field; + specific_field.field = field1; + if (field1->is_repeated()) { + AddSpecificIndex(&specific_field, message1, field1, i); + } else { + specific_field.index = -1; + } + + parent_fields->push_back(specific_field); + reporter_->ReportDeleted(message1, message2, *parent_fields); + parent_fields->pop_back(); + } + + isDifferent = true; + } else { + return false; + } + + ++field_index1; + continue; + } else if (FieldBefore(field2, field1)) { + // Field 2 is not in the field list for message 1. + if (IsIgnored(message1, message2, field2, *parent_fields)) { + // We are ignoring field2. Report the ignore and move on to + // the next field in message2_fields. + if (reporter_ != NULL) { + SpecificField specific_field; + specific_field.field = field2; + parent_fields->push_back(specific_field); + if (report_ignores_) { + reporter_->ReportIgnored(message1, message2, *parent_fields); + } + parent_fields->pop_back(); + } + ++field_index2; + continue; + } + + if (reporter_ != NULL) { + int count = field2->is_repeated() + ? reflection2->FieldSize(message2, field2) + : 1; + + for (int i = 0; i < count; ++i) { + SpecificField specific_field; + specific_field.field = field2; + if (field2->is_repeated()) { + specific_field.index = i; + AddSpecificNewIndex(&specific_field, message2, field2, i); + } else { + specific_field.index = -1; + specific_field.new_index = -1; + } + + parent_fields->push_back(specific_field); + reporter_->ReportAdded(message1, message2, *parent_fields); + parent_fields->pop_back(); + } + + isDifferent = true; + } else { + return false; + } + + ++field_index2; + continue; + } + + // By this point, field1 and field2 are guaranteed to point to the same + // field, so we can now compare the values. + if (IsIgnored(message1, message2, field1, *parent_fields)) { + // Ignore this field. Report and move on. + if (reporter_ != NULL) { + SpecificField specific_field; + specific_field.field = field1; + parent_fields->push_back(specific_field); + if (report_ignores_) { + reporter_->ReportIgnored(message1, message2, *parent_fields); + } + parent_fields->pop_back(); + } + + ++field_index1; + ++field_index2; + continue; + } + + bool fieldDifferent = false; + assert(field1 != NULL); + if (field1->is_map()) { + fieldDifferent = + !CompareMapField(message1, message2, field1, parent_fields); + } else if (field1->is_repeated()) { + fieldDifferent = + !CompareRepeatedField(message1, message2, field1, parent_fields); + } else { + fieldDifferent = !CompareFieldValueUsingParentFields( + message1, message2, field1, -1, -1, parent_fields); + + if (reporter_ != nullptr) { + SpecificField specific_field; + specific_field.field = field1; + parent_fields->push_back(specific_field); + if (fieldDifferent) { + reporter_->ReportModified(message1, message2, *parent_fields); + isDifferent = true; + } else if (report_matches_) { + reporter_->ReportMatched(message1, message2, *parent_fields); + } + parent_fields->pop_back(); + } + } + if (fieldDifferent) { + if (reporter_ == nullptr) return false; + isDifferent = true; + } + // Increment the field indices. + ++field_index1; + ++field_index2; + } + + return !isDifferent; +} + +bool MessageDifferencer::IsMatch( + const FieldDescriptor* repeated_field, + const MapKeyComparator* key_comparator, const Message* message1, + const Message* message2, const std::vector<SpecificField>& parent_fields, + Reporter* reporter, int index1, int index2) { + std::vector<SpecificField> current_parent_fields(parent_fields); + if (repeated_field->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE) { + return CompareFieldValueUsingParentFields(*message1, *message2, + repeated_field, index1, index2, + ¤t_parent_fields); + } + // Back up the Reporter and output_string_. They will be reset in the + // following code. + Reporter* backup_reporter = reporter_; + std::string* output_string = output_string_; + reporter_ = reporter; + output_string_ = NULL; + bool match; + + if (key_comparator == NULL) { + match = CompareFieldValueUsingParentFields(*message1, *message2, + repeated_field, index1, index2, + ¤t_parent_fields); + } else { + const Reflection* reflection1 = message1->GetReflection(); + const Reflection* reflection2 = message2->GetReflection(); + const Message& m1 = + reflection1->GetRepeatedMessage(*message1, repeated_field, index1); + const Message& m2 = + reflection2->GetRepeatedMessage(*message2, repeated_field, index2); + SpecificField specific_field; + specific_field.field = repeated_field; + if (repeated_field->is_map()) { + specific_field.map_entry1 = &m1; + specific_field.map_entry2 = &m2; + } + specific_field.index = index1; + specific_field.new_index = index2; + current_parent_fields.push_back(specific_field); + match = key_comparator->IsMatch(m1, m2, current_parent_fields); + } + + reporter_ = backup_reporter; + output_string_ = output_string; + return match; +} + +bool MessageDifferencer::CompareMapFieldByMapReflection( + const Message& message1, const Message& message2, + const FieldDescriptor* map_field, std::vector<SpecificField>* parent_fields, + DefaultFieldComparator* comparator) { + GOOGLE_DCHECK_EQ(nullptr, reporter_); + GOOGLE_DCHECK(map_field->is_map()); + GOOGLE_DCHECK(map_field_key_comparator_.find(map_field) == + map_field_key_comparator_.end()); + GOOGLE_DCHECK_EQ(repeated_field_comparison_, AS_LIST); + const Reflection* reflection1 = message1.GetReflection(); + const Reflection* reflection2 = message2.GetReflection(); + const int count1 = reflection1->MapSize(message1, map_field); + const int count2 = reflection2->MapSize(message2, map_field); + const bool treated_as_subset = IsTreatedAsSubset(map_field); + if (count1 != count2 && !treated_as_subset) { + return false; + } + if (count1 > count2) { + return false; + } + + // First pass: check whether the same keys are present. + for (MapIterator it = reflection1->MapBegin(const_cast<Message*>(&message1), + map_field), + it_end = reflection1->MapEnd(const_cast<Message*>(&message1), + map_field); + it != it_end; ++it) { + if (!reflection2->ContainsMapKey(message2, map_field, it.GetKey())) { + return false; + } + } + + // Second pass: compare values for matching keys. + const FieldDescriptor* val_des = map_field->message_type()->map_value(); + switch (val_des->cpp_type()) { +#define HANDLE_TYPE(CPPTYPE, METHOD, COMPAREMETHOD) \ + case FieldDescriptor::CPPTYPE_##CPPTYPE: { \ + for (MapIterator it = reflection1->MapBegin( \ + const_cast<Message*>(&message1), map_field), \ + it_end = reflection1->MapEnd( \ + const_cast<Message*>(&message1), map_field); \ + it != it_end; ++it) { \ + MapValueConstRef value2; \ + reflection2->LookupMapValue(message2, map_field, it.GetKey(), &value2); \ + if (!comparator->Compare##COMPAREMETHOD(*val_des, \ + it.GetValueRef().Get##METHOD(), \ + value2.Get##METHOD())) { \ + return false; \ + } \ + } \ + break; \ + } + HANDLE_TYPE(INT32, Int32Value, Int32); + HANDLE_TYPE(INT64, Int64Value, Int64); + HANDLE_TYPE(UINT32, UInt32Value, UInt32); + HANDLE_TYPE(UINT64, UInt64Value, UInt64); + HANDLE_TYPE(DOUBLE, DoubleValue, Double); + HANDLE_TYPE(FLOAT, FloatValue, Float); + HANDLE_TYPE(BOOL, BoolValue, Bool); + HANDLE_TYPE(STRING, StringValue, String); + HANDLE_TYPE(ENUM, EnumValue, Int32); +#undef HANDLE_TYPE + case FieldDescriptor::CPPTYPE_MESSAGE: { + for (MapIterator it = reflection1->MapBegin( + const_cast<Message*>(&message1), map_field); + it != + reflection1->MapEnd(const_cast<Message*>(&message1), map_field); + ++it) { + if (!reflection2->ContainsMapKey(message2, map_field, it.GetKey())) { + return false; + } + bool compare_result; + MapValueConstRef value2; + reflection2->LookupMapValue(message2, map_field, it.GetKey(), &value2); + // Append currently compared field to the end of parent_fields. + SpecificField specific_value_field; + specific_value_field.field = val_des; + parent_fields->push_back(specific_value_field); + compare_result = Compare(it.GetValueRef().GetMessageValue(), + value2.GetMessageValue(), parent_fields); + parent_fields->pop_back(); + if (!compare_result) { + return false; + } + } + break; + } + } + return true; +} + +bool MessageDifferencer::CompareMapField( + const Message& message1, const Message& message2, + const FieldDescriptor* repeated_field, + std::vector<SpecificField>* parent_fields) { + GOOGLE_DCHECK(repeated_field->is_map()); + + // the input FieldDescriptor is guaranteed to be repeated field. + const Reflection* reflection1 = message1.GetReflection(); + const Reflection* reflection2 = message2.GetReflection(); + + // When both map fields are on map, do not sync to repeated field. + if (reflection1->GetMapData(message1, repeated_field)->IsMapValid() && + reflection2->GetMapData(message2, repeated_field)->IsMapValid() && + // TODO(jieluo): Add support for reporter + reporter_ == nullptr && + // Users didn't set custom map field key comparator + map_field_key_comparator_.find(repeated_field) == + map_field_key_comparator_.end() && + // Users didn't set repeated field comparison + repeated_field_comparison_ == AS_LIST && + // Users didn't set their own FieldComparator implementation + field_comparator_kind_ == kFCDefault) { + const FieldDescriptor* key_des = repeated_field->message_type()->map_key(); + const FieldDescriptor* val_des = + repeated_field->message_type()->map_value(); + std::vector<SpecificField> current_parent_fields(*parent_fields); + SpecificField specific_field; + specific_field.field = repeated_field; + current_parent_fields.push_back(specific_field); + if (!IsIgnored(message1, message2, key_des, current_parent_fields) && + !IsIgnored(message1, message2, val_des, current_parent_fields)) { + return CompareMapFieldByMapReflection(message1, message2, repeated_field, + ¤t_parent_fields, + field_comparator_.default_impl); + } + } + + return CompareRepeatedRep(message1, message2, repeated_field, parent_fields); +} + +bool MessageDifferencer::CompareRepeatedField( + const Message& message1, const Message& message2, + const FieldDescriptor* repeated_field, + std::vector<SpecificField>* parent_fields) { + GOOGLE_DCHECK(!repeated_field->is_map()); + return CompareRepeatedRep(message1, message2, repeated_field, parent_fields); +} + +bool MessageDifferencer::CompareRepeatedRep( + const Message& message1, const Message& message2, + const FieldDescriptor* repeated_field, + std::vector<SpecificField>* parent_fields) { + // the input FieldDescriptor is guaranteed to be repeated field. + GOOGLE_DCHECK(repeated_field->is_repeated()); + const Reflection* reflection1 = message1.GetReflection(); + const Reflection* reflection2 = message2.GetReflection(); + + const int count1 = reflection1->FieldSize(message1, repeated_field); + const int count2 = reflection2->FieldSize(message2, repeated_field); + const bool treated_as_subset = IsTreatedAsSubset(repeated_field); + + // If the field is not treated as subset and no detailed reports is needed, + // we do a quick check on the number of the elements to avoid unnecessary + // comparison. + if (count1 != count2 && reporter_ == NULL && !treated_as_subset) { + return false; + } + // A match can never be found if message1 has more items than message2. + if (count1 > count2 && reporter_ == NULL) { + return false; + } + + // These two list are used for store the index of the correspondent + // element in peer repeated field. + std::vector<int> match_list1; + std::vector<int> match_list2; + + const MapKeyComparator* key_comparator = GetMapKeyComparator(repeated_field); + bool smart_list = IsTreatedAsSmartList(repeated_field); + bool simple_list = key_comparator == nullptr && + !IsTreatedAsSet(repeated_field) && + !IsTreatedAsSmartSet(repeated_field) && !smart_list; + + // For simple lists, we avoid matching repeated field indices, saving the + // memory allocations that would otherwise be needed for match_list1 and + // match_list2. + if (!simple_list) { + // Try to match indices of the repeated fields. Return false if match fails. + if (!MatchRepeatedFieldIndices(message1, message2, repeated_field, + key_comparator, *parent_fields, &match_list1, + &match_list2) && + reporter_ == nullptr) { + return false; + } + } + + bool fieldDifferent = false; + SpecificField specific_field; + specific_field.field = repeated_field; + + // At this point, we have already matched pairs of fields (with the reporting + // to be done later). Now to check if the paired elements are different. + int next_unmatched_index = 0; + for (int i = 0; i < count1; i++) { + if (simple_list && i >= count2) { + break; + } + if (!simple_list && match_list1[i] == -1) { + if (smart_list) { + if (reporter_ == nullptr) return false; + AddSpecificIndex(&specific_field, message1, repeated_field, i); + parent_fields->push_back(specific_field); + reporter_->ReportDeleted(message1, message2, *parent_fields); + parent_fields->pop_back(); + fieldDifferent = true; + // Use -2 to mark this element has been reported. + match_list1[i] = -2; + } + continue; + } + if (smart_list) { + for (int j = next_unmatched_index; j < match_list1[i]; ++j) { + GOOGLE_CHECK_LE(0, j); + if (reporter_ == nullptr) return false; + specific_field.index = j; + AddSpecificNewIndex(&specific_field, message2, repeated_field, j); + parent_fields->push_back(specific_field); + reporter_->ReportAdded(message1, message2, *parent_fields); + parent_fields->pop_back(); + fieldDifferent = true; + // Use -2 to mark this element has been reported. + match_list2[j] = -2; + } + } + AddSpecificIndex(&specific_field, message1, repeated_field, i); + if (simple_list) { + AddSpecificNewIndex(&specific_field, message2, repeated_field, i); + } else { + AddSpecificNewIndex(&specific_field, message2, repeated_field, + match_list1[i]); + next_unmatched_index = match_list1[i] + 1; + } + + const bool result = CompareFieldValueUsingParentFields( + message1, message2, repeated_field, i, specific_field.new_index, + parent_fields); + + // If we have found differences, either report them or terminate if + // no reporter is present. Note that ReportModified, ReportMoved, and + // ReportMatched are all mutually exclusive. + if (!result) { + if (reporter_ == NULL) return false; + parent_fields->push_back(specific_field); + reporter_->ReportModified(message1, message2, *parent_fields); + parent_fields->pop_back(); + fieldDifferent = true; + } else if (reporter_ != NULL && + specific_field.index != specific_field.new_index && + !specific_field.field->is_map() && report_moves_) { + parent_fields->push_back(specific_field); + reporter_->ReportMoved(message1, message2, *parent_fields); + parent_fields->pop_back(); + } else if (report_matches_ && reporter_ != NULL) { + parent_fields->push_back(specific_field); + reporter_->ReportMatched(message1, message2, *parent_fields); + parent_fields->pop_back(); + } + } + + // Report any remaining additions or deletions. + for (int i = 0; i < count2; ++i) { + if (!simple_list && match_list2[i] != -1) continue; + if (simple_list && i < count1) continue; + if (!treated_as_subset) { + fieldDifferent = true; + } + + if (reporter_ == NULL) continue; + specific_field.index = i; + AddSpecificNewIndex(&specific_field, message2, repeated_field, i); + parent_fields->push_back(specific_field); + reporter_->ReportAdded(message1, message2, *parent_fields); + parent_fields->pop_back(); + } + + for (int i = 0; i < count1; ++i) { + if (!simple_list && match_list1[i] != -1) continue; + if (simple_list && i < count2) continue; + assert(reporter_ != NULL); + AddSpecificIndex(&specific_field, message1, repeated_field, i); + parent_fields->push_back(specific_field); + reporter_->ReportDeleted(message1, message2, *parent_fields); + parent_fields->pop_back(); + fieldDifferent = true; + } + return !fieldDifferent; +} + +bool MessageDifferencer::CompareFieldValue(const Message& message1, + const Message& message2, + const FieldDescriptor* field, + int index1, int index2) { + return CompareFieldValueUsingParentFields(message1, message2, field, index1, + index2, NULL); +} + +bool MessageDifferencer::CompareFieldValueUsingParentFields( + const Message& message1, const Message& message2, + const FieldDescriptor* field, int index1, int index2, + std::vector<SpecificField>* parent_fields) { + FieldContext field_context(parent_fields); + FieldComparator::ComparisonResult result = GetFieldComparisonResult( + message1, message2, field, index1, index2, &field_context); + + if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE && + result == FieldComparator::RECURSE) { + // Get the nested messages and compare them using one of the Compare + // methods. + const Reflection* reflection1 = message1.GetReflection(); + const Reflection* reflection2 = message2.GetReflection(); + const Message& m1 = + field->is_repeated() + ? reflection1->GetRepeatedMessage(message1, field, index1) + : reflection1->GetMessage(message1, field); + const Message& m2 = + field->is_repeated() + ? reflection2->GetRepeatedMessage(message2, field, index2) + : reflection2->GetMessage(message2, field); + + // parent_fields is used in calls to Reporter methods. + if (parent_fields != NULL) { + // Append currently compared field to the end of parent_fields. + SpecificField specific_field; + specific_field.field = field; + AddSpecificIndex(&specific_field, message1, field, index1); + AddSpecificNewIndex(&specific_field, message2, field, index2); + parent_fields->push_back(specific_field); + const bool compare_result = Compare(m1, m2, parent_fields); + parent_fields->pop_back(); + return compare_result; + } else { + // Recreates parent_fields as if m1 and m2 had no parents. + return Compare(m1, m2); + } + } else { + return (result == FieldComparator::SAME); + } +} + +bool MessageDifferencer::CheckPathChanged( + const std::vector<SpecificField>& field_path) { + for (const SpecificField& specific_field : field_path) { + // Don't check indexes for map entries -- maps are unordered. + if (specific_field.field != nullptr && specific_field.field->is_map()) + continue; + if (specific_field.index != specific_field.new_index) return true; + } + return false; +} + +bool MessageDifferencer::IsTreatedAsSet(const FieldDescriptor* field) { + if (!field->is_repeated()) return false; + if (repeated_field_comparisons_.find(field) != + repeated_field_comparisons_.end()) { + return repeated_field_comparisons_[field] == AS_SET; + } + return GetMapKeyComparator(field) == nullptr && + repeated_field_comparison_ == AS_SET; +} + +bool MessageDifferencer::IsTreatedAsSmartSet(const FieldDescriptor* field) { + if (!field->is_repeated()) return false; + if (repeated_field_comparisons_.find(field) != + repeated_field_comparisons_.end()) { + return repeated_field_comparisons_[field] == AS_SMART_SET; + } + return GetMapKeyComparator(field) == nullptr && + repeated_field_comparison_ == AS_SMART_SET; +} + +bool MessageDifferencer::IsTreatedAsSmartList(const FieldDescriptor* field) { + if (!field->is_repeated()) return false; + if (repeated_field_comparisons_.find(field) != + repeated_field_comparisons_.end()) { + return repeated_field_comparisons_[field] == AS_SMART_LIST; + } + return GetMapKeyComparator(field) == nullptr && + repeated_field_comparison_ == AS_SMART_LIST; +} + +bool MessageDifferencer::IsTreatedAsSubset(const FieldDescriptor* field) { + return scope_ == PARTIAL && + (IsTreatedAsSet(field) || GetMapKeyComparator(field) != NULL); +} + +bool MessageDifferencer::IsIgnored( + const Message& message1, const Message& message2, + const FieldDescriptor* field, + const std::vector<SpecificField>& parent_fields) { + if (ignored_fields_.find(field) != ignored_fields_.end()) { + return true; + } + for (IgnoreCriteria* criteria : ignore_criteria_) { + if (criteria->IsIgnored(message1, message2, field, parent_fields)) { + return true; + } + } + return false; +} + +bool MessageDifferencer::IsUnknownFieldIgnored( + const Message& message1, const Message& message2, + const SpecificField& field, + const std::vector<SpecificField>& parent_fields) { + for (IgnoreCriteria* criteria : ignore_criteria_) { + if (criteria->IsUnknownFieldIgnored(message1, message2, field, + parent_fields)) { + return true; + } + } + return false; +} + +const MessageDifferencer::MapKeyComparator* +MessageDifferencer ::GetMapKeyComparator(const FieldDescriptor* field) const { + if (!field->is_repeated()) return NULL; + FieldKeyComparatorMap::const_iterator it = + map_field_key_comparator_.find(field); + if (it != map_field_key_comparator_.end()) { + return it->second; + } + if (field->is_map()) { + // field cannot already be treated as list or set since TreatAsList() and + // TreatAsSet() call GetMapKeyComparator() and fail if it returns non-NULL. + return &map_entry_key_comparator_; + } + return NULL; +} + +namespace { + +typedef std::pair<int, const UnknownField*> IndexUnknownFieldPair; + +struct UnknownFieldOrdering { + inline bool operator()(const IndexUnknownFieldPair& a, + const IndexUnknownFieldPair& b) const { + if (a.second->number() < b.second->number()) return true; + if (a.second->number() > b.second->number()) return false; + return a.second->type() < b.second->type(); + } +}; + +} // namespace + +bool MessageDifferencer::UnpackAnyField::UnpackAny( + const Message& any, std::unique_ptr<Message>* data) { + const Reflection* reflection = any.GetReflection(); + const FieldDescriptor* type_url_field; + const FieldDescriptor* value_field; + if (!internal::GetAnyFieldDescriptors(any, &type_url_field, &value_field)) { + return false; + } + const std::string& type_url = reflection->GetString(any, type_url_field); + std::string full_type_name; + if (!internal::ParseAnyTypeUrl(type_url, &full_type_name)) { + return false; + } + + const Descriptor* desc = + any.GetDescriptor()->file()->pool()->FindMessageTypeByName( + full_type_name); + if (desc == NULL) { + GOOGLE_LOG(INFO) << "Proto type '" << full_type_name << "' not found"; + return false; + } + + if (dynamic_message_factory_ == NULL) { + dynamic_message_factory_.reset(new DynamicMessageFactory()); + } + data->reset(dynamic_message_factory_->GetPrototype(desc)->New()); + std::string serialized_value = reflection->GetString(any, value_field); + if (!(*data)->ParsePartialFromString(serialized_value)) { + GOOGLE_DLOG(ERROR) << "Failed to parse value for " << full_type_name; + return false; + } + return true; +} + +bool MessageDifferencer::CompareUnknownFields( + const Message& message1, const Message& message2, + const UnknownFieldSet& unknown_field_set1, + const UnknownFieldSet& unknown_field_set2, + std::vector<SpecificField>* parent_field) { + // Ignore unknown fields in EQUIVALENT mode. + if (message_field_comparison_ == EQUIVALENT) return true; + + if (unknown_field_set1.empty() && unknown_field_set2.empty()) { + return true; + } + + bool is_different = false; + + // We first sort the unknown fields by field number and type (in other words, + // in tag order), making sure to preserve ordering of values with the same + // tag. This allows us to report only meaningful differences between the + // two sets -- that is, differing values for the same tag. We use + // IndexUnknownFieldPairs to keep track of the field's original index for + // reporting purposes. + std::vector<IndexUnknownFieldPair> fields1; // unknown_field_set1, sorted + std::vector<IndexUnknownFieldPair> fields2; // unknown_field_set2, sorted + fields1.reserve(unknown_field_set1.field_count()); + fields2.reserve(unknown_field_set2.field_count()); + + for (int i = 0; i < unknown_field_set1.field_count(); i++) { + fields1.push_back(std::make_pair(i, &unknown_field_set1.field(i))); + } + for (int i = 0; i < unknown_field_set2.field_count(); i++) { + fields2.push_back(std::make_pair(i, &unknown_field_set2.field(i))); + } + + UnknownFieldOrdering is_before; + std::stable_sort(fields1.begin(), fields1.end(), is_before); + std::stable_sort(fields2.begin(), fields2.end(), is_before); + + // In order to fill in SpecificField::index, we have to keep track of how + // many values we've seen with the same field number and type. + // current_repeated points at the first field in this range, and + // current_repeated_start{1,2} are the indexes of the first field in the + // range within fields1 and fields2. + const UnknownField* current_repeated = NULL; + int current_repeated_start1 = 0; + int current_repeated_start2 = 0; + + // Now that we have two sorted lists, we can detect fields which appear only + // in one list or the other by traversing them simultaneously. + size_t index1 = 0; + size_t index2 = 0; + while (index1 < fields1.size() || index2 < fields2.size()) { + enum { + ADDITION, + DELETION, + MODIFICATION, + COMPARE_GROUPS, + NO_CHANGE + } change_type; + + // focus_field is the field we're currently reporting on. (In the case + // of a modification, it's the field on the left side.) + const UnknownField* focus_field; + bool match = false; + + if (index2 == fields2.size() || + (index1 < fields1.size() && + is_before(fields1[index1], fields2[index2]))) { + // fields1[index1] is not present in fields2. + change_type = DELETION; + focus_field = fields1[index1].second; + } else if (index1 == fields1.size() || + is_before(fields2[index2], fields1[index1])) { + // fields2[index2] is not present in fields1. + if (scope_ == PARTIAL) { + // Ignore. + ++index2; + continue; + } + change_type = ADDITION; + focus_field = fields2[index2].second; + } else { + // Field type and number are the same. See if the values differ. + change_type = MODIFICATION; + focus_field = fields1[index1].second; + + switch (focus_field->type()) { + case UnknownField::TYPE_VARINT: + match = fields1[index1].second->varint() == + fields2[index2].second->varint(); + break; + case UnknownField::TYPE_FIXED32: + match = fields1[index1].second->fixed32() == + fields2[index2].second->fixed32(); + break; + case UnknownField::TYPE_FIXED64: + match = fields1[index1].second->fixed64() == + fields2[index2].second->fixed64(); + break; + case UnknownField::TYPE_LENGTH_DELIMITED: + match = fields1[index1].second->length_delimited() == + fields2[index2].second->length_delimited(); + break; + case UnknownField::TYPE_GROUP: + // We must deal with this later, after building the SpecificField. + change_type = COMPARE_GROUPS; + break; + } + if (match && change_type != COMPARE_GROUPS) { + change_type = NO_CHANGE; + } + } + + if (current_repeated == NULL || + focus_field->number() != current_repeated->number() || + focus_field->type() != current_repeated->type()) { + // We've started a new repeated field. + current_repeated = focus_field; + current_repeated_start1 = index1; + current_repeated_start2 = index2; + } + + if (change_type == NO_CHANGE && reporter_ == NULL) { + // Fields were already compared and matched and we have no reporter. + ++index1; + ++index2; + continue; + } + + // Build the SpecificField. This is slightly complicated. + SpecificField specific_field; + specific_field.unknown_field_number = focus_field->number(); + specific_field.unknown_field_type = focus_field->type(); + + specific_field.unknown_field_set1 = &unknown_field_set1; + specific_field.unknown_field_set2 = &unknown_field_set2; + + if (change_type != ADDITION) { + specific_field.unknown_field_index1 = fields1[index1].first; + } + if (change_type != DELETION) { + specific_field.unknown_field_index2 = fields2[index2].first; + } + + // Calculate the field index. + if (change_type == ADDITION) { + specific_field.index = index2 - current_repeated_start2; + specific_field.new_index = index2 - current_repeated_start2; + } else { + specific_field.index = index1 - current_repeated_start1; + specific_field.new_index = index2 - current_repeated_start2; + } + + if (IsUnknownFieldIgnored(message1, message2, specific_field, + *parent_field)) { + if (report_ignores_ && reporter_ != NULL) { + parent_field->push_back(specific_field); + reporter_->ReportUnknownFieldIgnored(message1, message2, *parent_field); + parent_field->pop_back(); + } + if (change_type != ADDITION) ++index1; + if (change_type != DELETION) ++index2; + continue; + } + + if (change_type == ADDITION || change_type == DELETION || + change_type == MODIFICATION) { + if (reporter_ == NULL) { + // We found a difference and we have no reporter. + return false; + } + is_different = true; + } + + parent_field->push_back(specific_field); + + switch (change_type) { + case ADDITION: + reporter_->ReportAdded(message1, message2, *parent_field); + ++index2; + break; + case DELETION: + reporter_->ReportDeleted(message1, message2, *parent_field); + ++index1; + break; + case MODIFICATION: + reporter_->ReportModified(message1, message2, *parent_field); + ++index1; + ++index2; + break; + case COMPARE_GROUPS: + if (!CompareUnknownFields( + message1, message2, fields1[index1].second->group(), + fields2[index2].second->group(), parent_field)) { + if (reporter_ == NULL) return false; + is_different = true; + reporter_->ReportModified(message1, message2, *parent_field); + } + ++index1; + ++index2; + break; + case NO_CHANGE: + ++index1; + ++index2; + if (report_matches_) { + reporter_->ReportMatched(message1, message2, *parent_field); + } + } + + parent_field->pop_back(); + } + + return !is_different; +} + +namespace { + +// Find maximum bipartite matching using the argumenting path algorithm. +class MaximumMatcher { + public: + typedef std::function<bool(int, int)> NodeMatchCallback; + // MaximumMatcher takes ownership of the passed in callback and uses it to + // determine whether a node on the left side of the bipartial graph matches + // a node on the right side. count1 is the number of nodes on the left side + // of the graph and count2 to is the number of nodes on the right side. + // Every node is referred to using 0-based indices. + // If a maximum match is found, the result will be stored in match_list1 and + // match_list2. match_list1[i] == j means the i-th node on the left side is + // matched to the j-th node on the right side and match_list2[x] == y means + // the x-th node on the right side is matched to y-th node on the left side. + // match_list1[i] == -1 means the node is not matched. Same with match_list2. + MaximumMatcher(int count1, int count2, NodeMatchCallback callback, + std::vector<int>* match_list1, std::vector<int>* match_list2); + // Find a maximum match and return the number of matched node pairs. + // If early_return is true, this method will return 0 immediately when it + // finds that not all nodes on the left side can be matched. + int FindMaximumMatch(bool early_return); + + private: + // Determines whether the node on the left side of the bipartial graph + // matches the one on the right side. + bool Match(int left, int right); + // Find an argumenting path starting from the node v on the left side. If a + // path can be found, update match_list2_ to reflect the path and return + // true. + bool FindArgumentPathDFS(int v, std::vector<bool>* visited); + + int count1_; + int count2_; + NodeMatchCallback match_callback_; + std::map<std::pair<int, int>, bool> cached_match_results_; + std::vector<int>* match_list1_; + std::vector<int>* match_list2_; + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MaximumMatcher); +}; + +MaximumMatcher::MaximumMatcher(int count1, int count2, + NodeMatchCallback callback, + std::vector<int>* match_list1, + std::vector<int>* match_list2) + : count1_(count1), + count2_(count2), + match_callback_(std::move(callback)), + match_list1_(match_list1), + match_list2_(match_list2) { + match_list1_->assign(count1, -1); + match_list2_->assign(count2, -1); +} + +int MaximumMatcher::FindMaximumMatch(bool early_return) { + int result = 0; + for (int i = 0; i < count1_; ++i) { + std::vector<bool> visited(count1_); + if (FindArgumentPathDFS(i, &visited)) { + ++result; + } else if (early_return) { + return 0; + } + } + // Backfill match_list1_ as we only filled match_list2_ when finding + // argumenting paths. + for (int i = 0; i < count2_; ++i) { + if ((*match_list2_)[i] != -1) { + (*match_list1_)[(*match_list2_)[i]] = i; + } + } + return result; +} + +bool MaximumMatcher::Match(int left, int right) { + std::pair<int, int> p(left, right); + std::map<std::pair<int, int>, bool>::iterator it = + cached_match_results_.find(p); + if (it != cached_match_results_.end()) { + return it->second; + } + cached_match_results_[p] = match_callback_(left, right); + return cached_match_results_[p]; +} + +bool MaximumMatcher::FindArgumentPathDFS(int v, std::vector<bool>* visited) { + (*visited)[v] = true; + // We try to match those un-matched nodes on the right side first. This is + // the step that the naive greedy matching algorithm uses. In the best cases + // where the greedy algorithm can find a maximum matching, we will always + // find a match in this step and the performance will be identical to the + // greedy algorithm. + for (int i = 0; i < count2_; ++i) { + int matched = (*match_list2_)[i]; + if (matched == -1 && Match(v, i)) { + (*match_list2_)[i] = v; + return true; + } + } + // Then we try those already matched nodes and see if we can find an + // alternative match for the node matched to them. + // The greedy algorithm will stop before this and fail to produce the + // correct result. + for (int i = 0; i < count2_; ++i) { + int matched = (*match_list2_)[i]; + if (matched != -1 && Match(v, i)) { + if (!(*visited)[matched] && FindArgumentPathDFS(matched, visited)) { + (*match_list2_)[i] = v; + return true; + } + } + } + return false; +} + +} // namespace + +bool MessageDifferencer::MatchRepeatedFieldIndices( + const Message& message1, const Message& message2, + const FieldDescriptor* repeated_field, + const MapKeyComparator* key_comparator, + const std::vector<SpecificField>& parent_fields, + std::vector<int>* match_list1, std::vector<int>* match_list2) { + const int count1 = + message1.GetReflection()->FieldSize(message1, repeated_field); + const int count2 = + message2.GetReflection()->FieldSize(message2, repeated_field); + const bool is_treated_as_smart_set = IsTreatedAsSmartSet(repeated_field); + + match_list1->assign(count1, -1); + match_list2->assign(count2, -1); + // Ensure that we don't report differences during the matching process. Since + // field comparators could potentially use this message differencer object to + // perform further comparisons, turn off reporting here and re-enable it + // before returning. + Reporter* reporter = reporter_; + reporter_ = NULL; + NumDiffsReporter num_diffs_reporter; + std::vector<int32_t> num_diffs_list1; + if (is_treated_as_smart_set) { + num_diffs_list1.assign(count1, std::numeric_limits<int32_t>::max()); + } + + bool success = true; + // Find potential match if this is a special repeated field. + if (scope_ == PARTIAL) { + // When partial matching is enabled, Compare(a, b) && Compare(a, c) + // doesn't necessarily imply Compare(b, c). Therefore a naive greedy + // algorithm will fail to find a maximum matching. + // Here we use the augmenting path algorithm. + auto callback = [&](int i1, int i2) { + return IsMatch(repeated_field, key_comparator, &message1, &message2, + parent_fields, nullptr, i1, i2); + }; + MaximumMatcher matcher(count1, count2, std::move(callback), match_list1, + match_list2); + // If diff info is not needed, we should end the matching process as + // soon as possible if not all items can be matched. + bool early_return = (reporter == nullptr); + int match_count = matcher.FindMaximumMatch(early_return); + if (match_count != count1 && early_return) return false; + success = success && (match_count == count1); + } else { + int start_offset = 0; + // If the two repeated fields are treated as sets, optimize for the case + // where both start with same items stored in the same order. + if (IsTreatedAsSet(repeated_field) || is_treated_as_smart_set || + IsTreatedAsSmartList(repeated_field)) { + start_offset = std::min(count1, count2); + for (int i = 0; i < count1 && i < count2; i++) { + if (IsMatch(repeated_field, key_comparator, &message1, &message2, + parent_fields, nullptr, i, i)) { + match_list1->at(i) = i; + match_list2->at(i) = i; + } else { + start_offset = i; + break; + } + } + } + for (int i = start_offset; i < count1; ++i) { + // Indicates any matched elements for this repeated field. + bool match = false; + int matched_j = -1; + + for (int j = start_offset; j < count2; j++) { + if (match_list2->at(j) != -1) { + if (!is_treated_as_smart_set || num_diffs_list1[i] == 0 || + num_diffs_list1[match_list2->at(j)] == 0) { + continue; + } + } + + if (is_treated_as_smart_set) { + num_diffs_reporter.Reset(); + match = IsMatch(repeated_field, key_comparator, &message1, &message2, + parent_fields, &num_diffs_reporter, i, j); + } else { + match = IsMatch(repeated_field, key_comparator, &message1, &message2, + parent_fields, nullptr, i, j); + } + + if (is_treated_as_smart_set) { + if (match) { + num_diffs_list1[i] = 0; + } else if (repeated_field->cpp_type() == + FieldDescriptor::CPPTYPE_MESSAGE) { + // Replace with the one with fewer diffs. + const int32_t num_diffs = num_diffs_reporter.GetNumDiffs(); + if (num_diffs < num_diffs_list1[i]) { + // If j has been already matched to some element, ensure the + // current num_diffs is smaller. + if (match_list2->at(j) == -1 || + num_diffs < num_diffs_list1[match_list2->at(j)]) { + num_diffs_list1[i] = num_diffs; + match = true; + } + } + } + } + + if (match) { + matched_j = j; + if (!is_treated_as_smart_set || num_diffs_list1[i] == 0) { + break; + } + } + } + + match = (matched_j != -1); + if (match) { + if (is_treated_as_smart_set && match_list2->at(matched_j) != -1) { + // This is to revert the previously matched index in list2. + match_list1->at(match_list2->at(matched_j)) = -1; + match = false; + } + match_list1->at(i) = matched_j; + match_list2->at(matched_j) = i; + } + if (!match && reporter == nullptr) return false; + success = success && match; + } + } + + if (IsTreatedAsSmartList(repeated_field)) { + match_indices_for_smart_list_callback_(match_list1, match_list2); + } + + reporter_ = reporter; + + return success; +} + +FieldComparator::ComparisonResult MessageDifferencer::GetFieldComparisonResult( + const Message& message1, const Message& message2, + const FieldDescriptor* field, int index1, int index2, + const FieldContext* field_context) { + FieldComparator* comparator = field_comparator_kind_ == kFCBase + ? field_comparator_.base + : field_comparator_.default_impl; + return comparator->Compare(message1, message2, field, index1, index2, + field_context); +} + +// =========================================================================== + +MessageDifferencer::Reporter::Reporter() {} +MessageDifferencer::Reporter::~Reporter() {} + +// =========================================================================== + +MessageDifferencer::MapKeyComparator::MapKeyComparator() {} +MessageDifferencer::MapKeyComparator::~MapKeyComparator() {} + +// =========================================================================== + +MessageDifferencer::IgnoreCriteria::IgnoreCriteria() {} +MessageDifferencer::IgnoreCriteria::~IgnoreCriteria() {} + +// =========================================================================== + +// Note that the printer's delimiter is not used, because if we are given a +// printer, we don't know its delimiter. +MessageDifferencer::StreamReporter::StreamReporter( + io::ZeroCopyOutputStream* output) + : printer_(new io::Printer(output, '$')), + delete_printer_(true), + report_modified_aggregates_(false), + message1_(nullptr), + message2_(nullptr) {} + +MessageDifferencer::StreamReporter::StreamReporter(io::Printer* printer) + : printer_(printer), + delete_printer_(false), + report_modified_aggregates_(false), + message1_(nullptr), + message2_(nullptr) {} + +MessageDifferencer::StreamReporter::~StreamReporter() { + if (delete_printer_) delete printer_; +} + +void MessageDifferencer::StreamReporter::PrintPath( + const std::vector<SpecificField>& field_path, bool left_side) { + for (size_t i = 0; i < field_path.size(); ++i) { + SpecificField specific_field = field_path[i]; + + if (specific_field.field != nullptr && + specific_field.field->name() == "value") { + // check to see if this the value label of a map value. If so, skip it + // because it isn't meaningful + if (i > 0 && field_path[i - 1].field->is_map()) { + continue; + } + } + if (i > 0) { + printer_->Print("."); + } + if (specific_field.field != NULL) { + if (specific_field.field->is_extension()) { + printer_->Print("($name$)", "name", specific_field.field->full_name()); + } else { + printer_->PrintRaw(specific_field.field->name()); + } + + if (specific_field.field->is_map()) { + PrintMapKey(left_side, specific_field); + continue; + } + } else { + printer_->PrintRaw(StrCat(specific_field.unknown_field_number)); + } + if (left_side && specific_field.index >= 0) { + printer_->Print("[$name$]", "name", StrCat(specific_field.index)); + } + if (!left_side && specific_field.new_index >= 0) { + printer_->Print("[$name$]", "name", + StrCat(specific_field.new_index)); + } + } +} + + +void MessageDifferencer::StreamReporter::PrintValue( + const Message& message, const std::vector<SpecificField>& field_path, + bool left_side) { + const SpecificField& specific_field = field_path.back(); + const FieldDescriptor* field = specific_field.field; + if (field != NULL) { + std::string output; + int index = left_side ? specific_field.index : specific_field.new_index; + if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { + const Reflection* reflection = message.GetReflection(); + const Message& field_message = + field->is_repeated() + ? reflection->GetRepeatedMessage(message, field, index) + : reflection->GetMessage(message, field); + const FieldDescriptor* fd = nullptr; + + if (field->is_map() && message1_ != nullptr && message2_ != nullptr) { + fd = field_message.GetDescriptor()->field(1); + if (fd->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { + output = PrintShortTextFormat( + field_message.GetReflection()->GetMessage(field_message, fd)); + } else { + TextFormat::PrintFieldValueToString(field_message, fd, -1, &output); + } + } else { + output = PrintShortTextFormat(field_message); + } + if (output.empty()) { + printer_->Print("{ }"); + } else { + if ((fd != nullptr) && + (fd->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE)) { + printer_->PrintRaw(output); + } else { + printer_->Print("{ $name$ }", "name", output); + } + } + } else { + TextFormat::PrintFieldValueToString(message, field, index, &output); + printer_->PrintRaw(output); + } + } else { + const UnknownFieldSet* unknown_fields = + (left_side ? specific_field.unknown_field_set1 + : specific_field.unknown_field_set2); + const UnknownField* unknown_field = + &unknown_fields->field(left_side ? specific_field.unknown_field_index1 + : specific_field.unknown_field_index2); + PrintUnknownFieldValue(unknown_field); + } +} + +void MessageDifferencer::StreamReporter::PrintUnknownFieldValue( + const UnknownField* unknown_field) { + GOOGLE_CHECK(unknown_field != NULL) << " Cannot print NULL unknown_field."; + + std::string output; + switch (unknown_field->type()) { + case UnknownField::TYPE_VARINT: + output = StrCat(unknown_field->varint()); + break; + case UnknownField::TYPE_FIXED32: + output = StrCat( + "0x", strings::Hex(unknown_field->fixed32(), strings::ZERO_PAD_8)); + break; + case UnknownField::TYPE_FIXED64: + output = StrCat( + "0x", strings::Hex(unknown_field->fixed64(), strings::ZERO_PAD_16)); + break; + case UnknownField::TYPE_LENGTH_DELIMITED: + output = StringPrintf( + "\"%s\"", CEscape(unknown_field->length_delimited()).c_str()); + break; + case UnknownField::TYPE_GROUP: + // TODO(kenton): Print the contents of the group like we do for + // messages. Requires an equivalent of ShortDebugString() for + // UnknownFieldSet. + output = "{ ... }"; + break; + } + printer_->PrintRaw(output); +} + +void MessageDifferencer::StreamReporter::Print(const std::string& str) { + printer_->Print(str.c_str()); +} + +void MessageDifferencer::StreamReporter::PrintMapKey( + bool left_side, const SpecificField& specific_field) { + if (message1_ == nullptr || message2_ == nullptr) { + GOOGLE_LOG(INFO) << "PrintPath cannot log map keys; " + "use SetMessages to provide the messages " + "being compared prior to any processing."; + return; + } + + const Message* found_message = + left_side ? specific_field.map_entry1 : specific_field.map_entry2; + std::string key_string = ""; + if (found_message != nullptr) { + // NB: the map key is always the first field + const FieldDescriptor* fd = found_message->GetDescriptor()->field(0); + if (fd->cpp_type() == FieldDescriptor::CPPTYPE_STRING) { + // Not using PrintFieldValueToString for strings to avoid extra + // characters + key_string = found_message->GetReflection()->GetString( + *found_message, found_message->GetDescriptor()->field(0)); + } else { + TextFormat::PrintFieldValueToString(*found_message, fd, -1, &key_string); + } + if (key_string.empty()) { + key_string = "''"; + } + printer_->PrintRaw(StrCat("[", key_string, "]")); + } +} + +void MessageDifferencer::StreamReporter::ReportAdded( + const Message& /*message1*/, const Message& message2, + const std::vector<SpecificField>& field_path) { + printer_->Print("added: "); + PrintPath(field_path, false); + printer_->Print(": "); + PrintValue(message2, field_path, false); + printer_->Print("\n"); // Print for newlines. +} + +void MessageDifferencer::StreamReporter::ReportDeleted( + const Message& message1, const Message& /*message2*/, + const std::vector<SpecificField>& field_path) { + printer_->Print("deleted: "); + PrintPath(field_path, true); + printer_->Print(": "); + PrintValue(message1, field_path, true); + printer_->Print("\n"); // Print for newlines +} + +void MessageDifferencer::StreamReporter::ReportModified( + const Message& message1, const Message& message2, + const std::vector<SpecificField>& field_path) { + if (!report_modified_aggregates_ && field_path.back().field == NULL) { + if (field_path.back().unknown_field_type == UnknownField::TYPE_GROUP) { + // Any changes to the subfields have already been printed. + return; + } + } else if (!report_modified_aggregates_) { + if (field_path.back().field->cpp_type() == + FieldDescriptor::CPPTYPE_MESSAGE) { + // Any changes to the subfields have already been printed. + return; + } + } + + printer_->Print("modified: "); + PrintPath(field_path, true); + if (CheckPathChanged(field_path)) { + printer_->Print(" -> "); + PrintPath(field_path, false); + } + printer_->Print(": "); + PrintValue(message1, field_path, true); + printer_->Print(" -> "); + PrintValue(message2, field_path, false); + printer_->Print("\n"); // Print for newlines. +} + +void MessageDifferencer::StreamReporter::ReportMoved( + const Message& message1, const Message& /*message2*/, + const std::vector<SpecificField>& field_path) { + printer_->Print("moved: "); + PrintPath(field_path, true); + printer_->Print(" -> "); + PrintPath(field_path, false); + printer_->Print(" : "); + PrintValue(message1, field_path, true); + printer_->Print("\n"); // Print for newlines. +} + +void MessageDifferencer::StreamReporter::ReportMatched( + const Message& message1, const Message& /*message2*/, + const std::vector<SpecificField>& field_path) { + printer_->Print("matched: "); + PrintPath(field_path, true); + if (CheckPathChanged(field_path)) { + printer_->Print(" -> "); + PrintPath(field_path, false); + } + printer_->Print(" : "); + PrintValue(message1, field_path, true); + printer_->Print("\n"); // Print for newlines. +} + +void MessageDifferencer::StreamReporter::ReportIgnored( + const Message& /*message1*/, const Message& /*message2*/, + const std::vector<SpecificField>& field_path) { + printer_->Print("ignored: "); + PrintPath(field_path, true); + if (CheckPathChanged(field_path)) { + printer_->Print(" -> "); + PrintPath(field_path, false); + } + printer_->Print("\n"); // Print for newlines. +} + +void MessageDifferencer::StreamReporter::SetMessages(const Message& message1, + const Message& message2) { + message1_ = &message1; + message2_ = &message2; +} + +void MessageDifferencer::StreamReporter::ReportUnknownFieldIgnored( + const Message& /*message1*/, const Message& /*message2*/, + const std::vector<SpecificField>& field_path) { + printer_->Print("ignored: "); + PrintPath(field_path, true); + if (CheckPathChanged(field_path)) { + printer_->Print(" -> "); + PrintPath(field_path, false); + } + printer_->Print("\n"); // Print for newlines. +} + +MessageDifferencer::MapKeyComparator* +MessageDifferencer::CreateMultipleFieldsMapKeyComparator( + const std::vector<std::vector<const FieldDescriptor*> >& key_field_paths) { + return new MultipleFieldsMapKeyComparator(this, key_field_paths); +} + +} // namespace util +} // namespace protobuf +} // namespace google diff --git a/toolkit/components/protobuf/src/google/protobuf/util/message_differencer.h b/toolkit/components/protobuf/src/google/protobuf/util/message_differencer.h new file mode 100644 index 0000000000..f63cd54185 --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/util/message_differencer.h @@ -0,0 +1,980 @@ +// 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. + +// Author: jschorr@google.com (Joseph Schorr) +// Based on original Protocol Buffers design by +// Sanjay Ghemawat, Jeff Dean, and others. +// +// This file defines static methods and classes for comparing Protocol +// Messages. +// +// Aug. 2008: Added Unknown Fields Comparison for messages. +// Aug. 2009: Added different options to compare repeated fields. +// Apr. 2010: Moved field comparison to FieldComparator +// Sep. 2020: Added option to output map keys in path + +#ifndef GOOGLE_PROTOBUF_UTIL_MESSAGE_DIFFERENCER_H__ +#define GOOGLE_PROTOBUF_UTIL_MESSAGE_DIFFERENCER_H__ + + +#include <functional> +#include <map> +#include <memory> +#include <set> +#include <string> +#include <vector> + +#include <google/protobuf/descriptor.h> // FieldDescriptor +#include <google/protobuf/message.h> // Message +#include <google/protobuf/unknown_field_set.h> +#include <google/protobuf/util/field_comparator.h> + +// Always include as last one, otherwise it can break compilation +#include <google/protobuf/port_def.inc> + +namespace google { +namespace protobuf { + +class DynamicMessageFactory; +class FieldDescriptor; + +namespace io { +class ZeroCopyOutputStream; +class Printer; +} // namespace io + +namespace util { + +class DefaultFieldComparator; +class FieldContext; // declared below MessageDifferencer + +// Defines a collection of field descriptors. +// In case of internal google codebase we are using absl::FixedArray instead +// of vector. It significantly speeds up proto comparison (by ~30%) by +// reducing the number of malloc/free operations +typedef std::vector<const FieldDescriptor*> FieldDescriptorArray; + +// A basic differencer that can be used to determine +// the differences between two specified Protocol Messages. If any differences +// are found, the Compare method will return false, and any differencer reporter +// specified via ReportDifferencesTo will have its reporting methods called (see +// below for implementation of the report). Based off of the original +// ProtocolDifferencer implementation in //net/proto/protocol-differencer.h +// (Thanks Todd!). +// +// MessageDifferencer REQUIRES that compared messages be the same type, defined +// as messages that share the same descriptor. If not, the behavior of this +// class is undefined. +// +// People disagree on what MessageDifferencer should do when asked to compare +// messages with different descriptors. Some people think it should always +// return false. Others expect it to try to look for similar fields and +// compare them anyway -- especially if the descriptors happen to be identical. +// If we chose either of these behaviors, some set of people would find it +// surprising, and could end up writing code expecting the other behavior +// without realizing their error. Therefore, we forbid that usage. +// +// This class is implemented based on the proto2 reflection. The performance +// should be good enough for normal usages. However, for places where the +// performance is extremely sensitive, there are several alternatives: +// - Comparing serialized string +// Downside: false negatives (there are messages that are the same but their +// serialized strings are different). +// - Equals code generator by compiler plugin (net/proto2/contrib/equals_plugin) +// Downside: more generated code; maintenance overhead for the additional rule +// (must be in sync with the original proto_library). +// +// Note on handling of google.protobuf.Any: MessageDifferencer automatically +// unpacks Any::value into a Message and compares its individual fields. +// Messages encoded in a repeated Any cannot be compared using TreatAsMap. +// +// Note on thread-safety: MessageDifferencer is *not* thread-safe. You need to +// guard it with a lock to use the same MessageDifferencer instance from +// multiple threads. Note that it's fine to call static comparison methods +// (like MessageDifferencer::Equals) concurrently, but it's not recommended for +// performance critical code as it leads to extra allocations. +class PROTOBUF_EXPORT MessageDifferencer { + public: + // Determines whether the supplied messages are equal. Equality is defined as + // all fields within the two messages being set to the same value. Primitive + // fields and strings are compared by value while embedded messages/groups + // are compared as if via a recursive call. Use Compare() with IgnoreField() + // if some fields should be ignored in the comparison. Use Compare() with + // TreatAsSet() if there are repeated fields where ordering does not matter. + // + // This method REQUIRES that the two messages have the same + // Descriptor (message1.GetDescriptor() == message2.GetDescriptor()). + static bool Equals(const Message& message1, const Message& message2); + + // Determines whether the supplied messages are equivalent. Equivalency is + // defined as all fields within the two messages having the same value. This + // differs from the Equals method above in that fields with default values + // are considered set to said value automatically. For details on how default + // values are defined for each field type, see: + // https://developers.google.com/protocol-buffers/docs/proto?csw=1#optional. + // Also, Equivalent() ignores unknown fields. Use IgnoreField() and Compare() + // if some fields should be ignored in the comparison. + // + // This method REQUIRES that the two messages have the same + // Descriptor (message1.GetDescriptor() == message2.GetDescriptor()). + static bool Equivalent(const Message& message1, const Message& message2); + + // Determines whether the supplied messages are approximately equal. + // Approximate equality is defined as all fields within the two messages + // being approximately equal. Primitive (non-float) fields and strings are + // compared by value, floats are compared using MathUtil::AlmostEquals() and + // embedded messages/groups are compared as if via a recursive call. Use + // IgnoreField() and Compare() if some fields should be ignored in the + // comparison. + // + // This method REQUIRES that the two messages have the same + // Descriptor (message1.GetDescriptor() == message2.GetDescriptor()). + static bool ApproximatelyEquals(const Message& message1, + const Message& message2); + + // Determines whether the supplied messages are approximately equivalent. + // Approximate equivalency is defined as all fields within the two messages + // being approximately equivalent. As in + // MessageDifferencer::ApproximatelyEquals, primitive (non-float) fields and + // strings are compared by value, floats are compared using + // MathUtil::AlmostEquals() and embedded messages/groups are compared as if + // via a recursive call. However, fields with default values are considered + // set to said value, as per MessageDiffencer::Equivalent. Use IgnoreField() + // and Compare() if some fields should be ignored in the comparison. + // + // This method REQUIRES that the two messages have the same + // Descriptor (message1.GetDescriptor() == message2.GetDescriptor()). + static bool ApproximatelyEquivalent(const Message& message1, + const Message& message2); + + // Identifies an individual field in a message instance. Used for field_path, + // below. + struct SpecificField { + // For known fields, "field" is filled in and "unknown_field_number" is -1. + // For unknown fields, "field" is NULL, "unknown_field_number" is the field + // number, and "unknown_field_type" is its type. + const FieldDescriptor* field = nullptr; + int unknown_field_number = -1; + UnknownField::Type unknown_field_type = UnknownField::Type::TYPE_VARINT; + + // If this a repeated field, "index" is the index within it. For unknown + // fields, this is the index of the field among all unknown fields of the + // same field number and type. + int index = -1; + + // If "field" is a repeated field which is being treated as a map or + // a set (see TreatAsMap() and TreatAsSet(), below), new_index indicates + // the index the position to which the element has moved. If the element + // has not moved, "new_index" will have the same value as "index". + int new_index = -1; + + // If "field" is a map field, point to the map entry. + const Message* map_entry1 = nullptr; + const Message* map_entry2 = nullptr; + + // For unknown fields, these are the pointers to the UnknownFieldSet + // containing the unknown fields. In certain cases (e.g. proto1's + // MessageSet, or nested groups of unknown fields), these may differ from + // the messages' internal UnknownFieldSets. + const UnknownFieldSet* unknown_field_set1 = nullptr; + const UnknownFieldSet* unknown_field_set2 = nullptr; + + // For unknown fields, these are the index of the field within the + // UnknownFieldSets. One or the other will be -1 when + // reporting an addition or deletion. + int unknown_field_index1 = -1; + int unknown_field_index2 = -1; + }; + + // Abstract base class from which all MessageDifferencer + // reporters derive. The five Report* methods below will be called when + // a field has been added, deleted, modified, moved, or matched. The third + // argument is a vector of FieldDescriptor pointers which describes the chain + // of fields that was taken to find the current field. For example, for a + // field found in an embedded message, the vector will contain two + // FieldDescriptors. The first will be the field of the embedded message + // itself and the second will be the actual field in the embedded message + // that was added/deleted/modified. + // Fields will be reported in PostTraversalOrder. + // For example, given following proto, if both baz and mooo are changed. + // foo { + // bar { + // baz: 1 + // mooo: 2 + // } + // } + // ReportModified will be invoked with following order: + // 1. foo.bar.baz or foo.bar.mooo + // 2. foo.bar.mooo or foo.bar.baz + // 2. foo.bar + // 3. foo + class PROTOBUF_EXPORT Reporter { + public: + Reporter(); + virtual ~Reporter(); + + // Reports that a field has been added into Message2. + virtual void ReportAdded(const Message& message1, const Message& message2, + const std::vector<SpecificField>& field_path) = 0; + + // Reports that a field has been deleted from Message1. + virtual void ReportDeleted( + const Message& message1, const Message& message2, + const std::vector<SpecificField>& field_path) = 0; + + // Reports that the value of a field has been modified. + virtual void ReportModified( + const Message& message1, const Message& message2, + const std::vector<SpecificField>& field_path) = 0; + + // Reports that a repeated field has been moved to another location. This + // only applies when using TreatAsSet or TreatAsMap() -- see below. Also + // note that for any given field, ReportModified and ReportMoved are + // mutually exclusive. If a field has been both moved and modified, then + // only ReportModified will be called. + virtual void ReportMoved( + const Message& /* message1 */, const Message& /* message2 */, + const std::vector<SpecificField>& /* field_path */) {} + + // Reports that two fields match. Useful for doing side-by-side diffs. + // This function is mutually exclusive with ReportModified and ReportMoved. + // Note that you must call set_report_matches(true) before calling Compare + // to make use of this function. + virtual void ReportMatched( + const Message& /* message1 */, const Message& /* message2 */, + const std::vector<SpecificField>& /* field_path */) {} + + // Reports that two fields would have been compared, but the + // comparison has been skipped because the field was marked as + // 'ignored' using IgnoreField(). This function is mutually + // exclusive with all the other Report() functions. + // + // The contract of ReportIgnored is slightly different than the + // other Report() functions, in that |field_path.back().index| is + // always equal to -1, even if the last field is repeated. This is + // because while the other Report() functions indicate where in a + // repeated field the action (Addition, Deletion, etc...) + // happened, when a repeated field is 'ignored', the differencer + // simply calls ReportIgnored on the repeated field as a whole and + // moves on without looking at its individual elements. + // + // Furthermore, ReportIgnored() does not indicate whether the + // fields were in fact equal or not, as Compare() does not inspect + // these fields at all. It is up to the Reporter to decide whether + // the fields are equal or not (perhaps with a second call to + // Compare()), if it cares. + virtual void ReportIgnored( + const Message& /* message1 */, const Message& /* message2 */, + const std::vector<SpecificField>& /* field_path */) {} + + // Report that an unknown field is ignored. (see comment above). + // Note this is a different function since the last SpecificField in field + // path has a null field. This could break existing Reporter. + virtual void ReportUnknownFieldIgnored( + const Message& /* message1 */, const Message& /* message2 */, + const std::vector<SpecificField>& /* field_path */) {} + + private: + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Reporter); + }; + + // MapKeyComparator is used to determine if two elements have the same key + // when comparing elements of a repeated field as a map. + class PROTOBUF_EXPORT MapKeyComparator { + public: + MapKeyComparator(); + virtual ~MapKeyComparator(); + + virtual bool IsMatch( + const Message& /* message1 */, const Message& /* message2 */, + const std::vector<SpecificField>& /* parent_fields */) const { + GOOGLE_CHECK(false) << "IsMatch() is not implemented."; + return false; + } + + private: + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MapKeyComparator); + }; + + // Abstract base class from which all IgnoreCriteria derive. + // By adding IgnoreCriteria more complex ignore logic can be implemented. + // IgnoreCriteria are registered with AddIgnoreCriteria. For each compared + // field IsIgnored is called on each added IgnoreCriteria until one returns + // true or all return false. + // IsIgnored is called for fields where at least one side has a value. + class PROTOBUF_EXPORT IgnoreCriteria { + public: + IgnoreCriteria(); + virtual ~IgnoreCriteria(); + + // Returns true if the field should be ignored. + virtual bool IsIgnored( + const Message& /* message1 */, const Message& /* message2 */, + const FieldDescriptor* /* field */, + const std::vector<SpecificField>& /* parent_fields */) = 0; + + // Returns true if the unknown field should be ignored. + // Note: This will be called for unknown fields as well in which case + // field.field will be null. + virtual bool IsUnknownFieldIgnored( + const Message& /* message1 */, const Message& /* message2 */, + const SpecificField& /* field */, + const std::vector<SpecificField>& /* parent_fields */) { + return false; + } + }; + + // To add a Reporter, construct default here, then use ReportDifferencesTo or + // ReportDifferencesToString. + explicit MessageDifferencer(); + + ~MessageDifferencer(); + + enum MessageFieldComparison { + EQUAL, // Fields must be present in both messages + // for the messages to be considered the same. + EQUIVALENT, // Fields with default values are considered set + // for comparison purposes even if not explicitly + // set in the messages themselves. Unknown fields + // are ignored. + }; + + enum Scope { + FULL, // All fields of both messages are considered in the comparison. + PARTIAL // Only fields present in the first message are considered; fields + // set only in the second message will be skipped during + // comparison. + }; + + // DEPRECATED. Use FieldComparator::FloatComparison instead. + enum FloatComparison { + EXACT, // Floats and doubles are compared exactly. + APPROXIMATE // Floats and doubles are compared using the + // MathUtil::AlmostEquals method. + }; + + enum RepeatedFieldComparison { + AS_LIST, // Repeated fields are compared in order. Differing values at + // the same index are reported using ReportModified(). If the + // repeated fields have different numbers of elements, the + // unpaired elements are reported using ReportAdded() or + // ReportDeleted(). + AS_SET, // Treat all the repeated fields as sets. + // See TreatAsSet(), as below. + AS_SMART_LIST, // Similar to AS_SET, but preserve the order and find the + // longest matching sequence from the first matching + // element. To use an optimal solution, call + // SetMatchIndicesForSmartListCallback() to pass it in. + AS_SMART_SET, // Similar to AS_SET, but match elements with fewest diffs. + }; + + // The elements of the given repeated field will be treated as a set for + // diffing purposes, so different orderings of the same elements will be + // considered equal. Elements which are present on both sides of the + // comparison but which have changed position will be reported with + // ReportMoved(). Elements which only exist on one side or the other are + // reported with ReportAdded() and ReportDeleted() regardless of their + // positions. ReportModified() is never used for this repeated field. If + // the only differences between the compared messages is that some fields + // have been moved, then the comparison returns true. + // + // Note that despite the name of this method, this is really + // comparison as multisets: if one side of the comparison has a duplicate + // in the repeated field but the other side doesn't, this will count as + // a mismatch. + // + // If the scope of comparison is set to PARTIAL, then in addition to what's + // above, extra values added to repeated fields of the second message will + // not cause the comparison to fail. + // + // Note that set comparison is currently O(k * n^2) (where n is the total + // number of elements, and k is the average size of each element). In theory + // it could be made O(n * k) with a more complex hashing implementation. Feel + // free to contribute one if the current implementation is too slow for you. + // If partial matching is also enabled, the time complexity will be O(k * n^2 + // + n^3) in which n^3 is the time complexity of the maximum matching + // algorithm. + // + // REQUIRES: field->is_repeated() and field not registered with TreatAsMap* + void TreatAsSet(const FieldDescriptor* field); + void TreatAsSmartSet(const FieldDescriptor* field); + + // The elements of the given repeated field will be treated as a list for + // diffing purposes, so different orderings of the same elements will NOT be + // considered equal. + // + // REQUIRES: field->is_repeated() and field not registered with TreatAsMap* + void TreatAsList(const FieldDescriptor* field); + // Note that the complexity is similar to treating as SET. + void TreatAsSmartList(const FieldDescriptor* field); + + // The elements of the given repeated field will be treated as a map for + // diffing purposes, with |key| being the map key. Thus, elements with the + // same key will be compared even if they do not appear at the same index. + // Differences are reported similarly to TreatAsSet(), except that + // ReportModified() is used to report elements with the same key but + // different values. Note that if an element is both moved and modified, + // only ReportModified() will be called. As with TreatAsSet, if the only + // differences between the compared messages is that some fields have been + // moved, then the comparison returns true. See TreatAsSet for notes on + // performance. + // + // REQUIRES: field->is_repeated() + // REQUIRES: field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE + // REQUIRES: key->containing_type() == field->message_type() + void TreatAsMap(const FieldDescriptor* field, const FieldDescriptor* key); + // Same as TreatAsMap except that this method will use multiple fields as + // the key in comparison. All specified fields in 'key_fields' should be + // present in the compared elements. Two elements will be treated as having + // the same key iff they have the same value for every specified field. There + // are two steps in the comparison process. The first one is key matching. + // Every element from one message will be compared to every element from + // the other message. Only fields in 'key_fields' are compared in this step + // to decide if two elements have the same key. The second step is value + // comparison. Those pairs of elements with the same key (with equal value + // for every field in 'key_fields') will be compared in this step. + // Time complexity of the first step is O(s * m * n ^ 2) where s is the + // average size of the fields specified in 'key_fields', m is the number of + // fields in 'key_fields' and n is the number of elements. If partial + // matching is enabled, an extra O(n^3) will be incured by the maximum + // matching algorithm. The second step is O(k * n) where k is the average + // size of each element. + void TreatAsMapWithMultipleFieldsAsKey( + const FieldDescriptor* field, + const std::vector<const FieldDescriptor*>& key_fields); + // Same as TreatAsMapWithMultipleFieldsAsKey, except that each of the field + // do not necessarily need to be a direct subfield. Each element in + // key_field_paths indicate a path from the message being compared, listing + // successive subfield to reach the key field. + // + // REQUIRES: + // for key_field_path in key_field_paths: + // key_field_path[0]->containing_type() == field->message_type() + // for i in [0, key_field_path.size() - 1): + // key_field_path[i+1]->containing_type() == + // key_field_path[i]->message_type() + // key_field_path[i]->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE + // !key_field_path[i]->is_repeated() + void TreatAsMapWithMultipleFieldPathsAsKey( + const FieldDescriptor* field, + const std::vector<std::vector<const FieldDescriptor*> >& key_field_paths); + + // Uses a custom MapKeyComparator to determine if two elements have the same + // key when comparing a repeated field as a map. + // The caller is responsible to delete the key_comparator. + // This method varies from TreatAsMapWithMultipleFieldsAsKey only in the + // first key matching step. Rather than comparing some specified fields, it + // will invoke the IsMatch method of the given 'key_comparator' to decide if + // two elements have the same key. + void TreatAsMapUsingKeyComparator(const FieldDescriptor* field, + const MapKeyComparator* key_comparator); + + // Initiates and returns a new instance of MultipleFieldsMapKeyComparator. + MapKeyComparator* CreateMultipleFieldsMapKeyComparator( + const std::vector<std::vector<const FieldDescriptor*> >& key_field_paths); + + // Add a custom ignore criteria that is evaluated in addition to the + // ignored fields added with IgnoreField. + // Takes ownership of ignore_criteria. + void AddIgnoreCriteria(IgnoreCriteria* ignore_criteria); + + // Indicates that any field with the given descriptor should be + // ignored for the purposes of comparing two messages. This applies + // to fields nested in the message structure as well as top level + // ones. When the MessageDifferencer encounters an ignored field, + // ReportIgnored is called on the reporter, if one is specified. + // + // The only place where the field's 'ignored' status is not applied is when + // it is being used as a key in a field passed to TreatAsMap or is one of + // the fields passed to TreatAsMapWithMultipleFieldsAsKey. + // In this case it is compared in key matching but after that it's ignored + // in value comparison. + void IgnoreField(const FieldDescriptor* field); + + // Sets the field comparator used to determine differences between protocol + // buffer fields. By default it's set to a DefaultFieldComparator instance. + // MessageDifferencer doesn't take ownership over the passed object. + // Note that this method must be called before Compare for the comparator to + // be used. + void set_field_comparator(FieldComparator* comparator); +#ifdef PROTOBUF_FUTURE_BREAKING_CHANGES + void set_field_comparator(DefaultFieldComparator* comparator); +#endif // PROTOBUF_FUTURE_BREAKING_CHANGES + + // DEPRECATED. Pass a DefaultFieldComparator instance instead. + // Sets the fraction and margin for the float comparison of a given field. + // Uses MathUtil::WithinFractionOrMargin to compare the values. + // NOTE: this method does nothing if differencer's field comparator has been + // set to a custom object. + // + // REQUIRES: field->cpp_type == FieldDescriptor::CPPTYPE_DOUBLE or + // field->cpp_type == FieldDescriptor::CPPTYPE_FLOAT + // REQUIRES: float_comparison_ == APPROXIMATE + void SetFractionAndMargin(const FieldDescriptor* field, double fraction, + double margin); + + // Sets the type of comparison (as defined in the MessageFieldComparison + // enumeration above) that is used by this differencer when determining how + // to compare fields in messages. + void set_message_field_comparison(MessageFieldComparison comparison); + + // Returns the current message field comparison used in this differencer. + MessageFieldComparison message_field_comparison() const; + + // Tells the differencer whether or not to report matches. This method must + // be called before Compare. The default for a new differencer is false. + void set_report_matches(bool report_matches) { + report_matches_ = report_matches; + } + + // Tells the differencer whether or not to report moves (in a set or map + // repeated field). This method must be called before Compare. The default for + // a new differencer is true. + void set_report_moves(bool report_moves) { report_moves_ = report_moves; } + + // Tells the differencer whether or not to report ignored values. This method + // must be called before Compare. The default for a new differencer is true. + void set_report_ignores(bool report_ignores) { + report_ignores_ = report_ignores; + } + + // Sets the scope of the comparison (as defined in the Scope enumeration + // above) that is used by this differencer when determining which fields to + // compare between the messages. + void set_scope(Scope scope); + + // Returns the current scope used by this differencer. + Scope scope() const; + + // DEPRECATED. Pass a DefaultFieldComparator instance instead. + // Sets the type of comparison (as defined in the FloatComparison enumeration + // above) that is used by this differencer when comparing float (and double) + // fields in messages. + // NOTE: this method does nothing if differencer's field comparator has been + // set to a custom object. + void set_float_comparison(FloatComparison comparison); + + // Sets the type of comparison for repeated field (as defined in the + // RepeatedFieldComparison enumeration above) that is used by this + // differencer when compare repeated fields in messages. + void set_repeated_field_comparison(RepeatedFieldComparison comparison); + + // Returns the current repeated field comparison used by this differencer. + RepeatedFieldComparison repeated_field_comparison() const; + + // Compares the two specified messages, returning true if they are the same, + // false otherwise. If this method returns false, any changes between the + // two messages will be reported if a Reporter was specified via + // ReportDifferencesTo (see also ReportDifferencesToString). + // + // This method REQUIRES that the two messages have the same + // Descriptor (message1.GetDescriptor() == message2.GetDescriptor()). + bool Compare(const Message& message1, const Message& message2); + + // Same as above, except comparing only the list of fields specified by the + // two vectors of FieldDescriptors. + bool CompareWithFields( + const Message& message1, const Message& message2, + const std::vector<const FieldDescriptor*>& message1_fields, + const std::vector<const FieldDescriptor*>& message2_fields); + + // Automatically creates a reporter that will output the differences + // found (if any) to the specified output string pointer. Note that this + // method must be called before Compare. + void ReportDifferencesToString(std::string* output); + + // Tells the MessageDifferencer to report differences via the specified + // reporter. Note that this method must be called before Compare for + // the reporter to be used. It is the responsibility of the caller to delete + // this object. + // If the provided pointer equals NULL, the MessageDifferencer stops reporting + // differences to any previously set reporters or output strings. + void ReportDifferencesTo(Reporter* reporter); + + private: + // Class for processing Any deserialization. This logic is used by both the + // MessageDifferencer and StreamReporter classes. + class UnpackAnyField { + private: + std::unique_ptr<DynamicMessageFactory> dynamic_message_factory_; + + public: + UnpackAnyField() = default; + ~UnpackAnyField() = default; + // If "any" is of type google.protobuf.Any, extract its payload using + // DynamicMessageFactory and store in "data". + bool UnpackAny(const Message& any, std::unique_ptr<Message>* data); + }; + + public: + // An implementation of the MessageDifferencer Reporter that outputs + // any differences found in human-readable form to the supplied + // ZeroCopyOutputStream or Printer. If a printer is used, the delimiter + // *must* be '$'. + // + // WARNING: this reporter does not necessarily flush its output until it is + // destroyed. As a result, it is not safe to assume the output is valid or + // complete until after you destroy the reporter. For example, if you use a + // StreamReporter to write to a StringOutputStream, the target string may + // contain uninitialized data until the reporter is destroyed. + class PROTOBUF_EXPORT StreamReporter : public Reporter { + public: + explicit StreamReporter(io::ZeroCopyOutputStream* output); + explicit StreamReporter(io::Printer* printer); // delimiter '$' + ~StreamReporter() override; + + // When set to true, the stream reporter will also output aggregates nodes + // (i.e. messages and groups) whose subfields have been modified. When + // false, will only report the individual subfields. Defaults to false. + void set_report_modified_aggregates(bool report) { + report_modified_aggregates_ = report; + } + + // The following are implementations of the methods described above. + + void ReportAdded(const Message& message1, const Message& message2, + const std::vector<SpecificField>& field_path) override; + + void ReportDeleted(const Message& message1, const Message& message2, + const std::vector<SpecificField>& field_path) override; + + void ReportModified(const Message& message1, const Message& message2, + const std::vector<SpecificField>& field_path) override; + + void ReportMoved(const Message& message1, const Message& message2, + const std::vector<SpecificField>& field_path) override; + + void ReportMatched(const Message& message1, const Message& message2, + const std::vector<SpecificField>& field_path) override; + + void ReportIgnored(const Message& message1, const Message& message2, + const std::vector<SpecificField>& field_path) override; + + void ReportUnknownFieldIgnored( + const Message& message1, const Message& message2, + const std::vector<SpecificField>& field_path) override; + + // Messages that are being compared must be provided to StreamReporter prior + // to processing + void SetMessages(const Message& message1, const Message& message2); + + protected: + // Prints the specified path of fields to the buffer. + virtual void PrintPath(const std::vector<SpecificField>& field_path, + bool left_side); + + // Prints the value of fields to the buffer. left_side is true if the + // given message is from the left side of the comparison, false if it + // was the right. This is relevant only to decide whether to follow + // unknown_field_index1 or unknown_field_index2 when an unknown field + // is encountered in field_path. + virtual void PrintValue(const Message& message, + const std::vector<SpecificField>& field_path, + bool left_side); + + // Prints the specified path of unknown fields to the buffer. + virtual void PrintUnknownFieldValue(const UnknownField* unknown_field); + + // Just print a string + void Print(const std::string& str); + + private: + // helper function for PrintPath that contains logic for printing maps + void PrintMapKey(bool left_side, const SpecificField& specific_field); + + io::Printer* printer_; + bool delete_printer_; + bool report_modified_aggregates_; + const Message* message1_; + const Message* message2_; + MessageDifferencer::UnpackAnyField unpack_any_field_; + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(StreamReporter); + }; + + private: + friend class SimpleFieldComparator; + + // A MapKeyComparator to be used in TreatAsMapUsingKeyComparator. + // Implementation of this class needs to do field value comparison which + // relies on some private methods of MessageDifferencer. That's why this + // class is declared as a nested class of MessageDifferencer. + class MultipleFieldsMapKeyComparator; + + // A MapKeyComparator for use with map_entries. + class PROTOBUF_EXPORT MapEntryKeyComparator : public MapKeyComparator { + public: + explicit MapEntryKeyComparator(MessageDifferencer* message_differencer); + bool IsMatch( + const Message& message1, const Message& message2, + const std::vector<SpecificField>& parent_fields) const override; + + private: + MessageDifferencer* message_differencer_; + }; + + // Returns true if field1's number() is less than field2's. + static bool FieldBefore(const FieldDescriptor* field1, + const FieldDescriptor* field2); + + // Retrieve all the set fields, including extensions. + FieldDescriptorArray RetrieveFields(const Message& message, + bool base_message); + + // Combine the two lists of fields into the combined_fields output vector. + // All fields present in both lists will always be included in the combined + // list. Fields only present in one of the lists will only appear in the + // combined list if the corresponding fields_scope option is set to FULL. + FieldDescriptorArray CombineFields(const FieldDescriptorArray& fields1, + Scope fields1_scope, + const FieldDescriptorArray& fields2, + Scope fields2_scope); + + // Internal version of the Compare method which performs the actual + // comparison. The parent_fields vector is a vector containing field + // descriptors of all fields accessed to get to this comparison operation + // (i.e. if the current message is an embedded message, the parent_fields + // vector will contain the field that has this embedded message). + bool Compare(const Message& message1, const Message& message2, + std::vector<SpecificField>* parent_fields); + + // Compares all the unknown fields in two messages. + bool CompareUnknownFields(const Message& message1, const Message& message2, + const UnknownFieldSet&, const UnknownFieldSet&, + std::vector<SpecificField>* parent_fields); + + // Compares the specified messages for the requested field lists. The field + // lists are modified depending on comparison settings, and then passed to + // CompareWithFieldsInternal. + bool CompareRequestedFieldsUsingSettings( + const Message& message1, const Message& message2, + const FieldDescriptorArray& message1_fields, + const FieldDescriptorArray& message2_fields, + std::vector<SpecificField>* parent_fields); + + // Compares the specified messages with the specified field lists. + bool CompareWithFieldsInternal(const Message& message1, + const Message& message2, + const FieldDescriptorArray& message1_fields, + const FieldDescriptorArray& message2_fields, + std::vector<SpecificField>* parent_fields); + + // Compares the repeated fields, and report the error. + bool CompareRepeatedField(const Message& message1, const Message& message2, + const FieldDescriptor* field, + std::vector<SpecificField>* parent_fields); + + // Compares map fields, and report the error. + bool CompareMapField(const Message& message1, const Message& message2, + const FieldDescriptor* field, + std::vector<SpecificField>* parent_fields); + + // Helper for CompareRepeatedField and CompareMapField: compares and reports + // differences element-wise. This is the implementation for non-map fields, + // and can also compare map fields by using the underlying representation. + bool CompareRepeatedRep(const Message& message1, const Message& message2, + const FieldDescriptor* field, + std::vector<SpecificField>* parent_fields); + + // Helper for CompareMapField: compare the map fields using map reflection + // instead of sync to repeated. + bool CompareMapFieldByMapReflection(const Message& message1, + const Message& message2, + const FieldDescriptor* field, + std::vector<SpecificField>* parent_fields, + DefaultFieldComparator* comparator); + + // Shorthand for CompareFieldValueUsingParentFields with NULL parent_fields. + bool CompareFieldValue(const Message& message1, const Message& message2, + const FieldDescriptor* field, int index1, int index2); + + // Compares the specified field on the two messages, returning + // true if they are the same, false otherwise. For repeated fields, + // this method only compares the value in the specified index. This method + // uses Compare functions to recurse into submessages. + // The parent_fields vector is used in calls to a Reporter instance calls. + // It can be NULL, in which case the MessageDifferencer will create new + // list of parent messages if it needs to recursively compare the given field. + // To avoid confusing users you should not set it to NULL unless you modified + // Reporter to handle the change of parent_fields correctly. + bool CompareFieldValueUsingParentFields( + const Message& message1, const Message& message2, + const FieldDescriptor* field, int index1, int index2, + std::vector<SpecificField>* parent_fields); + + // Compares the specified field on the two messages, returning comparison + // result, as returned by appropriate FieldComparator. + FieldComparator::ComparisonResult GetFieldComparisonResult( + const Message& message1, const Message& message2, + const FieldDescriptor* field, int index1, int index2, + const FieldContext* field_context); + + // Check if the two elements in the repeated field are match to each other. + // if the key_comprator is NULL, this function returns true when the two + // elements are equal. + bool IsMatch(const FieldDescriptor* repeated_field, + const MapKeyComparator* key_comparator, const Message* message1, + const Message* message2, + const std::vector<SpecificField>& parent_fields, + Reporter* reporter, int index1, int index2); + + // Returns true when this repeated field has been configured to be treated + // as a Set / SmartSet / SmartList. + bool IsTreatedAsSet(const FieldDescriptor* field); + bool IsTreatedAsSmartSet(const FieldDescriptor* field); + + bool IsTreatedAsSmartList(const FieldDescriptor* field); + // When treating as SMART_LIST, it uses MatchIndicesPostProcessorForSmartList + // by default to find the longest matching sequence from the first matching + // element. The callback takes two vectors showing the matching indices from + // the other vector, where -1 means an unmatch. + void SetMatchIndicesForSmartListCallback( + std::function<void(std::vector<int>*, std::vector<int>*)> callback); + + // Returns true when this repeated field is to be compared as a subset, ie. + // has been configured to be treated as a set or map and scope is set to + // PARTIAL. + bool IsTreatedAsSubset(const FieldDescriptor* field); + + // Returns true if this field is to be ignored when this + // MessageDifferencer compares messages. + bool IsIgnored(const Message& message1, const Message& message2, + const FieldDescriptor* field, + const std::vector<SpecificField>& parent_fields); + + // Returns true if this unknown field is to be ignored when this + // MessageDifferencer compares messages. + bool IsUnknownFieldIgnored(const Message& message1, const Message& message2, + const SpecificField& field, + const std::vector<SpecificField>& parent_fields); + + // Returns MapKeyComparator* when this field has been configured to be treated + // as a map or its is_map() return true. If not, returns NULL. + const MapKeyComparator* GetMapKeyComparator( + const FieldDescriptor* field) const; + + // Attempts to match indices of a repeated field, so that the contained values + // match. Clears output vectors and sets their values to indices of paired + // messages, ie. if message1[0] matches message2[1], then match_list1[0] == 1 + // and match_list2[1] == 0. The unmatched indices are indicated by -1. + // Assumes the repeated field is not treated as a simple list. + // This method returns false if the match failed. However, it doesn't mean + // that the comparison succeeds when this method returns true (you need to + // double-check in this case). + bool MatchRepeatedFieldIndices( + const Message& message1, const Message& message2, + const FieldDescriptor* repeated_field, + const MapKeyComparator* key_comparator, + const std::vector<SpecificField>& parent_fields, + std::vector<int>* match_list1, std::vector<int>* match_list2); + + // Checks if index is equal to new_index in all the specific fields. + static bool CheckPathChanged(const std::vector<SpecificField>& parent_fields); + + // CHECKs that the given repeated field can be compared according to + // new_comparison. + void CheckRepeatedFieldComparisons( + const FieldDescriptor* field, + const RepeatedFieldComparison& new_comparison); + + // Defines a map between field descriptors and their MapKeyComparators. + // Used for repeated fields when they are configured as TreatAsMap. + typedef std::map<const FieldDescriptor*, const MapKeyComparator*> + FieldKeyComparatorMap; + + // Defines a set to store field descriptors. Used for repeated fields when + // they are configured as TreatAsSet. + typedef std::set<const FieldDescriptor*> FieldSet; + typedef std::map<const FieldDescriptor*, RepeatedFieldComparison> FieldMap; + + Reporter* reporter_; + DefaultFieldComparator default_field_comparator_; + MessageFieldComparison message_field_comparison_; + Scope scope_; + RepeatedFieldComparison repeated_field_comparison_; + + FieldMap repeated_field_comparisons_; + // Keeps track of MapKeyComparators that are created within + // MessageDifferencer. These MapKeyComparators should be deleted + // before MessageDifferencer is destroyed. + // When TreatAsMap or TreatAsMapWithMultipleFieldsAsKey is called, we don't + // store the supplied FieldDescriptors directly. Instead, a new + // MapKeyComparator is created for comparison purpose. + std::vector<MapKeyComparator*> owned_key_comparators_; + FieldKeyComparatorMap map_field_key_comparator_; + MapEntryKeyComparator map_entry_key_comparator_; + std::vector<IgnoreCriteria*> ignore_criteria_; + // Reused multiple times in RetrieveFields to avoid extra allocations + std::vector<const FieldDescriptor*> tmp_message_fields_; + + FieldSet ignored_fields_; + + union { + DefaultFieldComparator* default_impl; + FieldComparator* base; + } field_comparator_ = {&default_field_comparator_}; + enum { kFCDefault, kFCBase } field_comparator_kind_ = kFCDefault; + + bool report_matches_; + bool report_moves_; + bool report_ignores_; + + std::string* output_string_; + + // Callback to post-process the matched indices to support SMART_LIST. + std::function<void(std::vector<int>*, std::vector<int>*)> + match_indices_for_smart_list_callback_; + + MessageDifferencer::UnpackAnyField unpack_any_field_; + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessageDifferencer); +}; + +// This class provides extra information to the FieldComparator::Compare +// function. +class PROTOBUF_EXPORT FieldContext { + public: + explicit FieldContext( + std::vector<MessageDifferencer::SpecificField>* parent_fields) + : parent_fields_(parent_fields) {} + + std::vector<MessageDifferencer::SpecificField>* parent_fields() const { + return parent_fields_; + } + + private: + std::vector<MessageDifferencer::SpecificField>* parent_fields_; +}; + +} // namespace util +} // namespace protobuf +} // namespace google + +#include <google/protobuf/port_undef.inc> + +#endif // GOOGLE_PROTOBUF_UTIL_MESSAGE_DIFFERENCER_H__ diff --git a/toolkit/components/protobuf/src/google/protobuf/util/package_info.h b/toolkit/components/protobuf/src/google/protobuf/util/package_info.h new file mode 100644 index 0000000000..96019203bc --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/util/package_info.h @@ -0,0 +1,46 @@ +// 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. + +// This file exists solely to document the google::protobuf::util namespace. +// It is not compiled into anything, but it may be read by an automated +// documentation generator. + +namespace google { + +namespace protobuf { + +// Utility classes. +// +// This package contains various utilities for message comparison, JSON +// conversion, well known types, etc. +namespace util {} + +} // namespace protobuf +} // namespace google diff --git a/toolkit/components/protobuf/src/google/protobuf/util/time_util.cc b/toolkit/components/protobuf/src/google/protobuf/util/time_util.cc new file mode 100644 index 0000000000..9893aa35df --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/util/time_util.cc @@ -0,0 +1,514 @@ +// 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. + +#include <google/protobuf/util/time_util.h> + +#include <cstdint> + +#include <google/protobuf/stubs/strutil.h> +#include <google/protobuf/duration.pb.h> +#include <google/protobuf/timestamp.pb.h> +#include <google/protobuf/stubs/int128.h> +#include <google/protobuf/stubs/stringprintf.h> +#include <google/protobuf/stubs/time.h> + +// Must go after other includes. +#include <google/protobuf/port_def.inc> + +namespace google { +namespace protobuf { +namespace util { + +using google::protobuf::Duration; +using google::protobuf::Timestamp; + +namespace { +static const int kNanosPerSecond = 1000000000; +static const int kMicrosPerSecond = 1000000; +static const int kMillisPerSecond = 1000; +static const int kNanosPerMillisecond = 1000000; +static const int kNanosPerMicrosecond = 1000; +static const int kSecondsPerMinute = 60; // Note that we ignore leap seconds. +static const int kSecondsPerHour = 3600; + +template <typename T> +T CreateNormalized(int64_t seconds, int64_t nanos); + +template <> +Timestamp CreateNormalized(int64_t seconds, int64_t nanos) { + // Make sure nanos is in the range. + if (nanos <= -kNanosPerSecond || nanos >= kNanosPerSecond) { + seconds += nanos / kNanosPerSecond; + nanos = nanos % kNanosPerSecond; + } + // For Timestamp nanos should be in the range [0, 999999999] + if (nanos < 0) { + seconds -= 1; + nanos += kNanosPerSecond; + } + GOOGLE_DCHECK(seconds >= TimeUtil::kTimestampMinSeconds && + seconds <= TimeUtil::kTimestampMaxSeconds); + Timestamp result; + result.set_seconds(seconds); + result.set_nanos(static_cast<int32_t>(nanos)); + return result; +} + +template <> +Duration CreateNormalized(int64_t seconds, int64_t nanos) { + // Make sure nanos is in the range. + if (nanos <= -kNanosPerSecond || nanos >= kNanosPerSecond) { + seconds += nanos / kNanosPerSecond; + nanos = nanos % kNanosPerSecond; + } + // nanos should have the same sign as seconds. + if (seconds < 0 && nanos > 0) { + seconds += 1; + nanos -= kNanosPerSecond; + } else if (seconds > 0 && nanos < 0) { + seconds -= 1; + nanos += kNanosPerSecond; + } + GOOGLE_DCHECK(seconds >= TimeUtil::kDurationMinSeconds && + seconds <= TimeUtil::kDurationMaxSeconds); + Duration result; + result.set_seconds(seconds); + result.set_nanos(static_cast<int32_t>(nanos)); + return result; +} + +// Format nanoseconds with either 3, 6, or 9 digits depending on the required +// precision to represent the exact value. +std::string FormatNanos(int32_t nanos) { + if (nanos % kNanosPerMillisecond == 0) { + return StringPrintf("%03d", nanos / kNanosPerMillisecond); + } else if (nanos % kNanosPerMicrosecond == 0) { + return StringPrintf("%06d", nanos / kNanosPerMicrosecond); + } else { + return StringPrintf("%09d", nanos); + } +} + +std::string FormatTime(int64_t seconds, int32_t nanos) { + return ::google::protobuf::internal::FormatTime(seconds, nanos); +} + +bool ParseTime(const std::string& value, int64_t* seconds, int32_t* nanos) { + return ::google::protobuf::internal::ParseTime(value, seconds, nanos); +} + +void CurrentTime(int64_t* seconds, int32_t* nanos) { + return ::google::protobuf::internal::GetCurrentTime(seconds, nanos); +} + +// Truncates the remainder part after division. +int64_t RoundTowardZero(int64_t value, int64_t divider) { + int64_t result = value / divider; + int64_t remainder = value % divider; + // Before C++11, the sign of the remainder is implementation dependent if + // any of the operands is negative. Here we try to enforce C++11's "rounded + // toward zero" semantics. For example, for (-5) / 2 an implementation may + // give -3 as the result with the remainder being 1. This function ensures + // we always return -2 (closer to zero) regardless of the implementation. + if (result < 0 && remainder > 0) { + return result + 1; + } else { + return result; + } +} +} // namespace + +// Actually define these static const integers. Required by C++ standard (but +// some compilers don't like it). +#ifndef _MSC_VER +const int64_t TimeUtil::kTimestampMinSeconds; +const int64_t TimeUtil::kTimestampMaxSeconds; +const int64_t TimeUtil::kDurationMaxSeconds; +const int64_t TimeUtil::kDurationMinSeconds; +#endif // !_MSC_VER + +std::string TimeUtil::ToString(const Timestamp& timestamp) { + return FormatTime(timestamp.seconds(), timestamp.nanos()); +} + +bool TimeUtil::FromString(const std::string& value, Timestamp* timestamp) { + int64_t seconds; + int32_t nanos; + if (!ParseTime(value, &seconds, &nanos)) { + return false; + } + *timestamp = CreateNormalized<Timestamp>(seconds, nanos); + return true; +} + +Timestamp TimeUtil::GetCurrentTime() { + int64_t seconds; + int32_t nanos; + CurrentTime(&seconds, &nanos); + return CreateNormalized<Timestamp>(seconds, nanos); +} + +Timestamp TimeUtil::GetEpoch() { return Timestamp(); } + +std::string TimeUtil::ToString(const Duration& duration) { + std::string result; + int64_t seconds = duration.seconds(); + int32_t nanos = duration.nanos(); + if (seconds < 0 || nanos < 0) { + result += "-"; + seconds = -seconds; + nanos = -nanos; + } + result += StrCat(seconds); + if (nanos != 0) { + result += "." + FormatNanos(nanos); + } + result += "s"; + return result; +} + +static int64_t Pow(int64_t x, int y) { + int64_t result = 1; + for (int i = 0; i < y; ++i) { + result *= x; + } + return result; +} + +bool TimeUtil::FromString(const std::string& value, Duration* duration) { + if (value.length() <= 1 || value[value.length() - 1] != 's') { + return false; + } + bool negative = (value[0] == '-'); + size_t sign_length = (negative ? 1 : 0); + // Parse the duration value as two integers rather than a float value + // to avoid precision loss. + std::string seconds_part, nanos_part; + size_t pos = value.find_last_of('.'); + if (pos == std::string::npos) { + seconds_part = value.substr(sign_length, value.length() - 1 - sign_length); + nanos_part = "0"; + } else { + seconds_part = value.substr(sign_length, pos - sign_length); + nanos_part = value.substr(pos + 1, value.length() - pos - 2); + } + char* end; + int64_t seconds = strto64(seconds_part.c_str(), &end, 10); + if (end != seconds_part.c_str() + seconds_part.length()) { + return false; + } + int64_t nanos = strto64(nanos_part.c_str(), &end, 10); + if (end != nanos_part.c_str() + nanos_part.length()) { + return false; + } + nanos = nanos * Pow(10, static_cast<int>(9 - nanos_part.length())); + if (negative) { + // If a Duration is negative, both seconds and nanos should be negative. + seconds = -seconds; + nanos = -nanos; + } + duration->set_seconds(seconds); + duration->set_nanos(static_cast<int32_t>(nanos)); + return true; +} + +Duration TimeUtil::NanosecondsToDuration(int64_t nanos) { + return CreateNormalized<Duration>(nanos / kNanosPerSecond, + nanos % kNanosPerSecond); +} + +Duration TimeUtil::MicrosecondsToDuration(int64_t micros) { + return CreateNormalized<Duration>( + micros / kMicrosPerSecond, + (micros % kMicrosPerSecond) * kNanosPerMicrosecond); +} + +Duration TimeUtil::MillisecondsToDuration(int64_t millis) { + return CreateNormalized<Duration>( + millis / kMillisPerSecond, + (millis % kMillisPerSecond) * kNanosPerMillisecond); +} + +Duration TimeUtil::SecondsToDuration(int64_t seconds) { + return CreateNormalized<Duration>(seconds, 0); +} + +Duration TimeUtil::MinutesToDuration(int64_t minutes) { + return CreateNormalized<Duration>(minutes * kSecondsPerMinute, 0); +} + +Duration TimeUtil::HoursToDuration(int64_t hours) { + return CreateNormalized<Duration>(hours * kSecondsPerHour, 0); +} + +int64_t TimeUtil::DurationToNanoseconds(const Duration& duration) { + return duration.seconds() * kNanosPerSecond + duration.nanos(); +} + +int64_t TimeUtil::DurationToMicroseconds(const Duration& duration) { + return duration.seconds() * kMicrosPerSecond + + RoundTowardZero(duration.nanos(), kNanosPerMicrosecond); +} + +int64_t TimeUtil::DurationToMilliseconds(const Duration& duration) { + return duration.seconds() * kMillisPerSecond + + RoundTowardZero(duration.nanos(), kNanosPerMillisecond); +} + +int64_t TimeUtil::DurationToSeconds(const Duration& duration) { + return duration.seconds(); +} + +int64_t TimeUtil::DurationToMinutes(const Duration& duration) { + return RoundTowardZero(duration.seconds(), kSecondsPerMinute); +} + +int64_t TimeUtil::DurationToHours(const Duration& duration) { + return RoundTowardZero(duration.seconds(), kSecondsPerHour); +} + +Timestamp TimeUtil::NanosecondsToTimestamp(int64_t nanos) { + return CreateNormalized<Timestamp>(nanos / kNanosPerSecond, + nanos % kNanosPerSecond); +} + +Timestamp TimeUtil::MicrosecondsToTimestamp(int64_t micros) { + return CreateNormalized<Timestamp>( + micros / kMicrosPerSecond, + micros % kMicrosPerSecond * kNanosPerMicrosecond); +} + +Timestamp TimeUtil::MillisecondsToTimestamp(int64_t millis) { + return CreateNormalized<Timestamp>( + millis / kMillisPerSecond, + millis % kMillisPerSecond * kNanosPerMillisecond); +} + +Timestamp TimeUtil::SecondsToTimestamp(int64_t seconds) { + return CreateNormalized<Timestamp>(seconds, 0); +} + +int64_t TimeUtil::TimestampToNanoseconds(const Timestamp& timestamp) { + return timestamp.seconds() * kNanosPerSecond + timestamp.nanos(); +} + +int64_t TimeUtil::TimestampToMicroseconds(const Timestamp& timestamp) { + return timestamp.seconds() * kMicrosPerSecond + + RoundTowardZero(timestamp.nanos(), kNanosPerMicrosecond); +} + +int64_t TimeUtil::TimestampToMilliseconds(const Timestamp& timestamp) { + return timestamp.seconds() * kMillisPerSecond + + RoundTowardZero(timestamp.nanos(), kNanosPerMillisecond); +} + +int64_t TimeUtil::TimestampToSeconds(const Timestamp& timestamp) { + return timestamp.seconds(); +} + +Timestamp TimeUtil::TimeTToTimestamp(time_t value) { + return CreateNormalized<Timestamp>(static_cast<int64_t>(value), 0); +} + +time_t TimeUtil::TimestampToTimeT(const Timestamp& value) { + return static_cast<time_t>(value.seconds()); +} + +Timestamp TimeUtil::TimevalToTimestamp(const timeval& value) { + return CreateNormalized<Timestamp>(value.tv_sec, + value.tv_usec * kNanosPerMicrosecond); +} + +timeval TimeUtil::TimestampToTimeval(const Timestamp& value) { + timeval result; + result.tv_sec = value.seconds(); + result.tv_usec = RoundTowardZero(value.nanos(), kNanosPerMicrosecond); + return result; +} + +Duration TimeUtil::TimevalToDuration(const timeval& value) { + return CreateNormalized<Duration>(value.tv_sec, + value.tv_usec * kNanosPerMicrosecond); +} + +timeval TimeUtil::DurationToTimeval(const Duration& value) { + timeval result; + result.tv_sec = value.seconds(); + result.tv_usec = RoundTowardZero(value.nanos(), kNanosPerMicrosecond); + // timeval.tv_usec's range is [0, 1000000) + if (result.tv_usec < 0) { + result.tv_sec -= 1; + result.tv_usec += kMicrosPerSecond; + } + return result; +} + +} // namespace util +} // namespace protobuf +} // namespace google + +namespace google { +namespace protobuf { +namespace { +using ::PROTOBUF_NAMESPACE_ID::util::CreateNormalized; +using ::PROTOBUF_NAMESPACE_ID::util::kNanosPerSecond; + +// Convert a Duration to uint128. +void ToUint128(const Duration& value, uint128* result, bool* negative) { + if (value.seconds() < 0 || value.nanos() < 0) { + *negative = true; + *result = static_cast<uint64_t>(-value.seconds()); + *result = *result * kNanosPerSecond + static_cast<uint32_t>(-value.nanos()); + } else { + *negative = false; + *result = static_cast<uint64_t>(value.seconds()); + *result = *result * kNanosPerSecond + static_cast<uint32_t>(value.nanos()); + } +} + +void ToDuration(const uint128& value, bool negative, Duration* duration) { + int64_t seconds = + static_cast<int64_t>(Uint128Low64(value / kNanosPerSecond)); + int32_t nanos = + static_cast<int32_t>(Uint128Low64(value % kNanosPerSecond)); + if (negative) { + seconds = -seconds; + nanos = -nanos; + } + duration->set_seconds(seconds); + duration->set_nanos(nanos); +} +} // namespace + +Duration& operator+=(Duration& d1, const Duration& d2) { + d1 = CreateNormalized<Duration>(d1.seconds() + d2.seconds(), + d1.nanos() + d2.nanos()); + return d1; +} + +Duration& operator-=(Duration& d1, const Duration& d2) { // NOLINT + d1 = CreateNormalized<Duration>(d1.seconds() - d2.seconds(), + d1.nanos() - d2.nanos()); + return d1; +} + +Duration& operator*=(Duration& d, int64_t r) { // NOLINT + bool negative; + uint128 value; + ToUint128(d, &value, &negative); + if (r > 0) { + value *= static_cast<uint64_t>(r); + } else { + negative = !negative; + value *= static_cast<uint64_t>(-r); + } + ToDuration(value, negative, &d); + return d; +} + +Duration& operator*=(Duration& d, double r) { // NOLINT + double result = + (static_cast<double>(d.seconds()) + d.nanos() * (1.0 / kNanosPerSecond)) * + r; + int64_t seconds = static_cast<int64_t>(result); + int32_t nanos = static_cast<int32_t>((result - static_cast<double>(seconds)) * + kNanosPerSecond); + // Note that we normalize here not just because nanos can have a different + // sign from seconds but also that nanos can be any arbitrary value when + // overflow happens (i.e., the result is a much larger value than what + // int64 can represent). + d = CreateNormalized<Duration>(seconds, nanos); + return d; +} + +Duration& operator/=(Duration& d, int64_t r) { // NOLINT + bool negative; + uint128 value; + ToUint128(d, &value, &negative); + if (r > 0) { + value /= static_cast<uint64_t>(r); + } else { + negative = !negative; + value /= static_cast<uint64_t>(-r); + } + ToDuration(value, negative, &d); + return d; +} + +Duration& operator/=(Duration& d, double r) { // NOLINT + return d *= 1.0 / r; +} + +Duration& operator%=(Duration& d1, const Duration& d2) { // NOLINT + bool negative1, negative2; + uint128 value1, value2; + ToUint128(d1, &value1, &negative1); + ToUint128(d2, &value2, &negative2); + uint128 result = value1 % value2; + // When negative values are involved in division, we round the division + // result towards zero. With this semantics, sign of the remainder is the + // same as the dividend. For example: + // -5 / 10 = 0, -5 % 10 = -5 + // -5 / (-10) = 0, -5 % (-10) = -5 + // 5 / (-10) = 0, 5 % (-10) = 5 + ToDuration(result, negative1, &d1); + return d1; +} + +int64_t operator/(const Duration& d1, const Duration& d2) { + bool negative1, negative2; + uint128 value1, value2; + ToUint128(d1, &value1, &negative1); + ToUint128(d2, &value2, &negative2); + int64_t result = Uint128Low64(value1 / value2); + if (negative1 != negative2) { + result = -result; + } + return result; +} + +Timestamp& operator+=(Timestamp& t, const Duration& d) { // NOLINT + t = CreateNormalized<Timestamp>(t.seconds() + d.seconds(), + t.nanos() + d.nanos()); + return t; +} + +Timestamp& operator-=(Timestamp& t, const Duration& d) { // NOLINT + t = CreateNormalized<Timestamp>(t.seconds() - d.seconds(), + t.nanos() - d.nanos()); + return t; +} + +Duration operator-(const Timestamp& t1, const Timestamp& t2) { + return CreateNormalized<Duration>(t1.seconds() - t2.seconds(), + t1.nanos() - t2.nanos()); +} +} // namespace protobuf +} // namespace google diff --git a/toolkit/components/protobuf/src/google/protobuf/util/time_util.h b/toolkit/components/protobuf/src/google/protobuf/util/time_util.h new file mode 100644 index 0000000000..709527ea27 --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/util/time_util.h @@ -0,0 +1,314 @@ +// 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. + +// Defines utilities for the Timestamp and Duration well known types. + +#ifndef GOOGLE_PROTOBUF_UTIL_TIME_UTIL_H__ +#define GOOGLE_PROTOBUF_UTIL_TIME_UTIL_H__ + +#include <cstdint> +#include <ctime> +#include <ostream> +#include <string> +#ifdef _MSC_VER +#ifdef _XBOX_ONE +struct timeval { + int64_t tv_sec; /* seconds */ + int64_t tv_usec; /* and microseconds */ +}; +#else +#include <winsock2.h> +#endif // _XBOX_ONE +#else +#include <sys/time.h> +#endif + +#include <google/protobuf/duration.pb.h> +#include <google/protobuf/timestamp.pb.h> + +// Must be included last. +#include <google/protobuf/port_def.inc> + +namespace google { +namespace protobuf { +namespace util { + +// Utility functions for Timestamp and Duration. +class PROTOBUF_EXPORT TimeUtil { + typedef google::protobuf::Timestamp Timestamp; + typedef google::protobuf::Duration Duration; + + public: + // The min/max Timestamp/Duration values we support. + // + // For "0001-01-01T00:00:00Z". + static const int64_t kTimestampMinSeconds = -62135596800LL; + // For "9999-12-31T23:59:59.999999999Z". + static const int64_t kTimestampMaxSeconds = 253402300799LL; + static const int64_t kDurationMinSeconds = -315576000000LL; + static const int64_t kDurationMaxSeconds = 315576000000LL; + + // Converts Timestamp to/from RFC 3339 date string format. + // Generated output will always be Z-normalized and uses 3, 6 or 9 + // fractional digits as required to represent the exact time. When + // parsing, any fractional digits (or none) and any offset are + // accepted as long as they fit into nano-seconds precision. + // Note that Timestamp can only represent time from + // 0001-01-01T00:00:00Z to 9999-12-31T23:59:59.999999999Z. Converting + // a Timestamp outside of this range is undefined behavior. + // See https://www.ietf.org/rfc/rfc3339.txt + // + // Example of generated format: + // "1972-01-01T10:00:20.021Z" + // + // Example of accepted format: + // "1972-01-01T10:00:20.021-05:00" + static std::string ToString(const Timestamp& timestamp); + static bool FromString(const std::string& value, Timestamp* timestamp); + + // Converts Duration to/from string format. The string format will contains + // 3, 6, or 9 fractional digits depending on the precision required to + // represent the exact Duration value. For example: + // "1s", "1.010s", "1.000000100s", "-3.100s" + // The range that can be represented by Duration is from -315,576,000,000 + // to +315,576,000,000 inclusive (in seconds). + static std::string ToString(const Duration& duration); + static bool FromString(const std::string& value, Duration* timestamp); + +#ifdef GetCurrentTime +#undef GetCurrentTime // Visual Studio has macro GetCurrentTime +#endif + // Gets the current UTC time. + static Timestamp GetCurrentTime(); + // Returns the Time representing "1970-01-01 00:00:00". + static Timestamp GetEpoch(); + + // Converts between Duration and integer types. The behavior is undefined if + // the input value is not in the valid range of Duration. + static Duration NanosecondsToDuration(int64_t nanos); + static Duration MicrosecondsToDuration(int64_t micros); + static Duration MillisecondsToDuration(int64_t millis); + static Duration SecondsToDuration(int64_t seconds); + static Duration MinutesToDuration(int64_t minutes); + static Duration HoursToDuration(int64_t hours); + // Result will be truncated towards zero. For example, "-1.5s" will be + // truncated to "-1s", and "1.5s" to "1s" when converting to seconds. + // It's undefined behavior if the input duration is not valid or the result + // exceeds the range of int64. A duration is not valid if it's not in the + // valid range of Duration, or have an invalid nanos value (i.e., larger + // than 999999999, less than -999999999, or have a different sign from the + // seconds part). + static int64_t DurationToNanoseconds(const Duration& duration); + static int64_t DurationToMicroseconds(const Duration& duration); + static int64_t DurationToMilliseconds(const Duration& duration); + static int64_t DurationToSeconds(const Duration& duration); + static int64_t DurationToMinutes(const Duration& duration); + static int64_t DurationToHours(const Duration& duration); + // Creates Timestamp from integer types. The integer value indicates the + // time elapsed from Epoch time. The behavior is undefined if the input + // value is not in the valid range of Timestamp. + static Timestamp NanosecondsToTimestamp(int64_t nanos); + static Timestamp MicrosecondsToTimestamp(int64_t micros); + static Timestamp MillisecondsToTimestamp(int64_t millis); + static Timestamp SecondsToTimestamp(int64_t seconds); + // Result will be truncated down to the nearest integer value. For example, + // with "1969-12-31T23:59:59.9Z", TimestampToMilliseconds() returns -100 + // and TimestampToSeconds() returns -1. It's undefined behavior if the input + // Timestamp is not valid (i.e., its seconds part or nanos part does not fall + // in the valid range) or the return value doesn't fit into int64. + static int64_t TimestampToNanoseconds(const Timestamp& timestamp); + static int64_t TimestampToMicroseconds(const Timestamp& timestamp); + static int64_t TimestampToMilliseconds(const Timestamp& timestamp); + static int64_t TimestampToSeconds(const Timestamp& timestamp); + + // Conversion to/from other time/date types. Note that these types may + // have a different precision and time range from Timestamp/Duration. + // When converting to a lower precision type, the value will be truncated + // to the nearest value that can be represented. If the value is + // out of the range of the result type, the return value is undefined. + // + // Conversion to/from time_t + static Timestamp TimeTToTimestamp(time_t value); + static time_t TimestampToTimeT(const Timestamp& value); + + // Conversion to/from timeval + static Timestamp TimevalToTimestamp(const timeval& value); + static timeval TimestampToTimeval(const Timestamp& value); + static Duration TimevalToDuration(const timeval& value); + static timeval DurationToTimeval(const Duration& value); +}; + +} // namespace util +} // namespace protobuf +} // namespace google + +namespace google { +namespace protobuf { +// Overloaded operators for Duration. +// +// Assignment operators. +PROTOBUF_EXPORT Duration& operator+=(Duration& d1, + const Duration& d2); // NOLINT +PROTOBUF_EXPORT Duration& operator-=(Duration& d1, + const Duration& d2); // NOLINT +PROTOBUF_EXPORT Duration& operator*=(Duration& d, int64_t r); // NOLINT +PROTOBUF_EXPORT Duration& operator*=(Duration& d, double r); // NOLINT +PROTOBUF_EXPORT Duration& operator/=(Duration& d, int64_t r); // NOLINT +PROTOBUF_EXPORT Duration& operator/=(Duration& d, double r); // NOLINT +// Overload for other integer types. +template <typename T> +Duration& operator*=(Duration& d, T r) { // NOLINT + int64_t x = r; + return d *= x; +} +template <typename T> +Duration& operator/=(Duration& d, T r) { // NOLINT + int64_t x = r; + return d /= x; +} +PROTOBUF_EXPORT Duration& operator%=(Duration& d1, + const Duration& d2); // NOLINT +// Relational operators. +inline bool operator<(const Duration& d1, const Duration& d2) { + if (d1.seconds() == d2.seconds()) { + return d1.nanos() < d2.nanos(); + } + return d1.seconds() < d2.seconds(); +} +inline bool operator>(const Duration& d1, const Duration& d2) { + return d2 < d1; +} +inline bool operator>=(const Duration& d1, const Duration& d2) { + return !(d1 < d2); +} +inline bool operator<=(const Duration& d1, const Duration& d2) { + return !(d2 < d1); +} +inline bool operator==(const Duration& d1, const Duration& d2) { + return d1.seconds() == d2.seconds() && d1.nanos() == d2.nanos(); +} +inline bool operator!=(const Duration& d1, const Duration& d2) { + return !(d1 == d2); +} +// Additive operators +inline Duration operator-(const Duration& d) { + Duration result; + result.set_seconds(-d.seconds()); + result.set_nanos(-d.nanos()); + return result; +} +inline Duration operator+(const Duration& d1, const Duration& d2) { + Duration result = d1; + return result += d2; +} +inline Duration operator-(const Duration& d1, const Duration& d2) { + Duration result = d1; + return result -= d2; +} +// Multiplicative operators +template <typename T> +inline Duration operator*(Duration d, T r) { + return d *= r; +} +template <typename T> +inline Duration operator*(T r, Duration d) { + return d *= r; +} +template <typename T> +inline Duration operator/(Duration d, T r) { + return d /= r; +} +PROTOBUF_EXPORT int64_t operator/(const Duration& d1, const Duration& d2); + +inline Duration operator%(const Duration& d1, const Duration& d2) { + Duration result = d1; + return result %= d2; +} + +inline std::ostream& operator<<(std::ostream& out, const Duration& d) { + out << ::PROTOBUF_NAMESPACE_ID::util::TimeUtil::ToString(d); + return out; +} + +// Overloaded operators for Timestamp +// +// Assignment operators. +PROTOBUF_EXPORT Timestamp& operator+=(Timestamp& t, + const Duration& d); // NOLINT +PROTOBUF_EXPORT Timestamp& operator-=(Timestamp& t, + const Duration& d); // NOLINT +// Relational operators. +inline bool operator<(const Timestamp& t1, const Timestamp& t2) { + if (t1.seconds() == t2.seconds()) { + return t1.nanos() < t2.nanos(); + } + return t1.seconds() < t2.seconds(); +} +inline bool operator>(const Timestamp& t1, const Timestamp& t2) { + return t2 < t1; +} +inline bool operator>=(const Timestamp& t1, const Timestamp& t2) { + return !(t1 < t2); +} +inline bool operator<=(const Timestamp& t1, const Timestamp& t2) { + return !(t2 < t1); +} +inline bool operator==(const Timestamp& t1, const Timestamp& t2) { + return t1.seconds() == t2.seconds() && t1.nanos() == t2.nanos(); +} +inline bool operator!=(const Timestamp& t1, const Timestamp& t2) { + return !(t1 == t2); +} +// Additive operators. +inline Timestamp operator+(const Timestamp& t, const Duration& d) { + Timestamp result = t; + return result += d; +} +inline Timestamp operator+(const Duration& d, const Timestamp& t) { + Timestamp result = t; + return result += d; +} +inline Timestamp operator-(const Timestamp& t, const Duration& d) { + Timestamp result = t; + return result -= d; +} +PROTOBUF_EXPORT Duration operator-(const Timestamp& t1, const Timestamp& t2); + +inline std::ostream& operator<<(std::ostream& out, const Timestamp& t) { + out << ::PROTOBUF_NAMESPACE_ID::util::TimeUtil::ToString(t); + return out; +} + +} // namespace protobuf +} // namespace google + +#include <google/protobuf/port_undef.inc> + +#endif // GOOGLE_PROTOBUF_UTIL_TIME_UTIL_H__ diff --git a/toolkit/components/protobuf/src/google/protobuf/util/type_resolver.h b/toolkit/components/protobuf/src/google/protobuf/util/type_resolver.h new file mode 100644 index 0000000000..b2e7b43d76 --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/util/type_resolver.h @@ -0,0 +1,77 @@ +// 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. + +// Defines a TypeResolver for the Any message. + +#ifndef GOOGLE_PROTOBUF_UTIL_TYPE_RESOLVER_H__ +#define GOOGLE_PROTOBUF_UTIL_TYPE_RESOLVER_H__ + +#include <string> + +#include <google/protobuf/stubs/common.h> +#include <google/protobuf/type.pb.h> +#include <google/protobuf/stubs/status.h> +#include <google/protobuf/stubs/status.h> + +// Must be included last. +#include <google/protobuf/port_def.inc> + +namespace google { +namespace protobuf { +class DescriptorPool; +namespace util { + +// Abstract interface for a type resolver. +// +// Implementations of this interface must be thread-safe. +class PROTOBUF_EXPORT TypeResolver { + public: + TypeResolver() {} + virtual ~TypeResolver() {} + + // Resolves a type url for a message type. + virtual util::Status ResolveMessageType( + const std::string& type_url, google::protobuf::Type* message_type) = 0; + + // Resolves a type url for an enum type. + virtual util::Status ResolveEnumType(const std::string& type_url, + google::protobuf::Enum* enum_type) = 0; + + private: + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(TypeResolver); +}; + +} // namespace util +} // namespace protobuf +} // namespace google + +#include <google/protobuf/port_undef.inc> + +#endif // GOOGLE_PROTOBUF_UTIL_TYPE_RESOLVER_H__ diff --git a/toolkit/components/protobuf/src/google/protobuf/util/type_resolver_util.cc b/toolkit/components/protobuf/src/google/protobuf/util/type_resolver_util.cc new file mode 100644 index 0000000000..8be0efbe7b --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/util/type_resolver_util.cc @@ -0,0 +1,370 @@ +// 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. + +#include <google/protobuf/util/type_resolver_util.h> + +#include <google/protobuf/type.pb.h> +#include <google/protobuf/wrappers.pb.h> +#include <google/protobuf/descriptor.pb.h> +#include <google/protobuf/descriptor.h> +#include <google/protobuf/stubs/strutil.h> +#include <google/protobuf/stubs/status.h> +#include <google/protobuf/util/internal/utility.h> +#include <google/protobuf/util/type_resolver.h> +#include <google/protobuf/stubs/status.h> + +// clang-format off +#include <google/protobuf/port_def.inc> +// clang-format on + +namespace google { +namespace protobuf { +namespace util { +namespace { +using google::protobuf::Any; +using google::protobuf::BoolValue; +using google::protobuf::BytesValue; +using google::protobuf::DoubleValue; +using google::protobuf::Enum; +using google::protobuf::EnumValue; +using google::protobuf::Field; +using google::protobuf::FloatValue; +using google::protobuf::Int32Value; +using google::protobuf::Int64Value; +using google::protobuf::Option; +using google::protobuf::StringValue; +using google::protobuf::Type; +using google::protobuf::UInt32Value; +using google::protobuf::UInt64Value; + +class DescriptorPoolTypeResolver : public TypeResolver { + public: + DescriptorPoolTypeResolver(const std::string& url_prefix, + const DescriptorPool* pool) + : url_prefix_(url_prefix), pool_(pool) {} + + util::Status ResolveMessageType(const std::string& type_url, + Type* type) override { + std::string type_name; + util::Status status = ParseTypeUrl(type_url, &type_name); + if (!status.ok()) { + return status; + } + + const Descriptor* descriptor = pool_->FindMessageTypeByName(type_name); + if (descriptor == NULL) { + return util::NotFoundError("Invalid type URL, unknown type: " + + type_name); + } + ConvertDescriptor(descriptor, type); + return util::Status(); + } + + util::Status ResolveEnumType(const std::string& type_url, + Enum* enum_type) override { + std::string type_name; + util::Status status = ParseTypeUrl(type_url, &type_name); + if (!status.ok()) { + return status; + } + + const EnumDescriptor* descriptor = pool_->FindEnumTypeByName(type_name); + if (descriptor == NULL) { + return util::InvalidArgumentError("Invalid type URL, unknown type: " + + type_name); + } + ConvertEnumDescriptor(descriptor, enum_type); + return util::Status(); + } + + private: + void ConvertDescriptor(const Descriptor* descriptor, Type* type) { + type->Clear(); + type->set_name(descriptor->full_name()); + for (int i = 0; i < descriptor->field_count(); ++i) { + ConvertFieldDescriptor(descriptor->field(i), type->add_fields()); + } + for (int i = 0; i < descriptor->oneof_decl_count(); ++i) { + type->add_oneofs(descriptor->oneof_decl(i)->name()); + } + type->mutable_source_context()->set_file_name(descriptor->file()->name()); + ConvertMessageOptions(descriptor->options(), type->mutable_options()); + } + + void ConvertMessageOptions(const MessageOptions& options, + RepeatedPtrField<Option>* output) { + return ConvertOptionsInternal(options, output); + } + + void ConvertFieldOptions(const FieldOptions& options, + RepeatedPtrField<Option>* output) { + return ConvertOptionsInternal(options, output); + } + + void ConvertEnumOptions(const EnumOptions& options, + RepeatedPtrField<Option>* output) { + return ConvertOptionsInternal(options, output); + } + + void ConvertEnumValueOptions(const EnumValueOptions& options, + RepeatedPtrField<Option>* output) { + return ConvertOptionsInternal(options, output); + } + + // Implementation details for Convert*Options. + void ConvertOptionsInternal(const Message& options, + RepeatedPtrField<Option>* output) { + const Reflection* reflection = options.GetReflection(); + std::vector<const FieldDescriptor*> fields; + reflection->ListFields(options, &fields); + for (const FieldDescriptor* field : fields) { + if (field->is_repeated()) { + const int size = reflection->FieldSize(options, field); + for (int i = 0; i < size; i++) { + ConvertOptionField(reflection, options, field, i, output->Add()); + } + } else { + ConvertOptionField(reflection, options, field, -1, output->Add()); + } + } + } + + static void ConvertOptionField(const Reflection* reflection, + const Message& options, + const FieldDescriptor* field, int index, + Option* out) { + out->set_name(field->is_extension() ? field->full_name() : field->name()); + Any* value = out->mutable_value(); + switch (field->cpp_type()) { + case FieldDescriptor::CPPTYPE_MESSAGE: + value->PackFrom( + field->is_repeated() + ? reflection->GetRepeatedMessage(options, field, index) + : reflection->GetMessage(options, field)); + return; + case FieldDescriptor::CPPTYPE_DOUBLE: + value->PackFrom(WrapValue<DoubleValue>( + field->is_repeated() + ? reflection->GetRepeatedDouble(options, field, index) + : reflection->GetDouble(options, field))); + return; + case FieldDescriptor::CPPTYPE_FLOAT: + value->PackFrom(WrapValue<FloatValue>( + field->is_repeated() + ? reflection->GetRepeatedFloat(options, field, index) + : reflection->GetFloat(options, field))); + return; + case FieldDescriptor::CPPTYPE_INT64: + value->PackFrom(WrapValue<Int64Value>( + field->is_repeated() + ? reflection->GetRepeatedInt64(options, field, index) + : reflection->GetInt64(options, field))); + return; + case FieldDescriptor::CPPTYPE_UINT64: + value->PackFrom(WrapValue<UInt64Value>( + field->is_repeated() + ? reflection->GetRepeatedUInt64(options, field, index) + : reflection->GetUInt64(options, field))); + return; + case FieldDescriptor::CPPTYPE_INT32: + value->PackFrom(WrapValue<Int32Value>( + field->is_repeated() + ? reflection->GetRepeatedInt32(options, field, index) + : reflection->GetInt32(options, field))); + return; + case FieldDescriptor::CPPTYPE_UINT32: + value->PackFrom(WrapValue<UInt32Value>( + field->is_repeated() + ? reflection->GetRepeatedUInt32(options, field, index) + : reflection->GetUInt32(options, field))); + return; + case FieldDescriptor::CPPTYPE_BOOL: + value->PackFrom(WrapValue<BoolValue>( + field->is_repeated() + ? reflection->GetRepeatedBool(options, field, index) + : reflection->GetBool(options, field))); + return; + case FieldDescriptor::CPPTYPE_STRING: { + const std::string& val = + field->is_repeated() + ? reflection->GetRepeatedString(options, field, index) + : reflection->GetString(options, field); + if (field->type() == FieldDescriptor::TYPE_STRING) { + value->PackFrom(WrapValue<StringValue>(val)); + } else { + value->PackFrom(WrapValue<BytesValue>(val)); + } + return; + } + case FieldDescriptor::CPPTYPE_ENUM: { + const EnumValueDescriptor* val = + field->is_repeated() + ? reflection->GetRepeatedEnum(options, field, index) + : reflection->GetEnum(options, field); + value->PackFrom(WrapValue<Int32Value>(val->number())); + return; + } + } + } + + template <typename WrapperT, typename T> + static WrapperT WrapValue(T value) { + WrapperT wrapper; + wrapper.set_value(value); + return wrapper; + } + + void ConvertFieldDescriptor(const FieldDescriptor* descriptor, Field* field) { + field->set_kind(static_cast<Field::Kind>(descriptor->type())); + switch (descriptor->label()) { + case FieldDescriptor::LABEL_OPTIONAL: + field->set_cardinality(Field::CARDINALITY_OPTIONAL); + break; + case FieldDescriptor::LABEL_REPEATED: + field->set_cardinality(Field::CARDINALITY_REPEATED); + break; + case FieldDescriptor::LABEL_REQUIRED: + field->set_cardinality(Field::CARDINALITY_REQUIRED); + break; + } + field->set_number(descriptor->number()); + field->set_name(descriptor->name()); + field->set_json_name(descriptor->json_name()); + if (descriptor->has_default_value()) { + field->set_default_value(DefaultValueAsString(descriptor)); + } + if (descriptor->type() == FieldDescriptor::TYPE_MESSAGE || + descriptor->type() == FieldDescriptor::TYPE_GROUP) { + field->set_type_url(GetTypeUrl(descriptor->message_type())); + } else if (descriptor->type() == FieldDescriptor::TYPE_ENUM) { + field->set_type_url(GetTypeUrl(descriptor->enum_type())); + } + if (descriptor->containing_oneof() != NULL) { + field->set_oneof_index(descriptor->containing_oneof()->index() + 1); + } + if (descriptor->is_packed()) { + field->set_packed(true); + } + + ConvertFieldOptions(descriptor->options(), field->mutable_options()); + } + + void ConvertEnumDescriptor(const EnumDescriptor* descriptor, + Enum* enum_type) { + enum_type->Clear(); + enum_type->set_name(descriptor->full_name()); + enum_type->mutable_source_context()->set_file_name( + descriptor->file()->name()); + for (int i = 0; i < descriptor->value_count(); ++i) { + const EnumValueDescriptor* value_descriptor = descriptor->value(i); + EnumValue* value = enum_type->mutable_enumvalue()->Add(); + value->set_name(value_descriptor->name()); + value->set_number(value_descriptor->number()); + + ConvertEnumValueOptions(value_descriptor->options(), + value->mutable_options()); + } + + ConvertEnumOptions(descriptor->options(), enum_type->mutable_options()); + } + + std::string GetTypeUrl(const Descriptor* descriptor) { + return url_prefix_ + "/" + descriptor->full_name(); + } + + std::string GetTypeUrl(const EnumDescriptor* descriptor) { + return url_prefix_ + "/" + descriptor->full_name(); + } + + util::Status ParseTypeUrl(const std::string& type_url, + std::string* type_name) { + if (type_url.substr(0, url_prefix_.size() + 1) != url_prefix_ + "/") { + return util::InvalidArgumentError( + StrCat("Invalid type URL, type URLs must be of the form '", + url_prefix_, "/<typename>', got: ", type_url)); + } + *type_name = type_url.substr(url_prefix_.size() + 1); + return util::Status(); + } + + std::string DefaultValueAsString(const FieldDescriptor* descriptor) { + switch (descriptor->cpp_type()) { + case FieldDescriptor::CPPTYPE_INT32: + return StrCat(descriptor->default_value_int32()); + break; + case FieldDescriptor::CPPTYPE_INT64: + return StrCat(descriptor->default_value_int64()); + break; + case FieldDescriptor::CPPTYPE_UINT32: + return StrCat(descriptor->default_value_uint32()); + break; + case FieldDescriptor::CPPTYPE_UINT64: + return StrCat(descriptor->default_value_uint64()); + break; + case FieldDescriptor::CPPTYPE_FLOAT: + return SimpleFtoa(descriptor->default_value_float()); + break; + case FieldDescriptor::CPPTYPE_DOUBLE: + return SimpleDtoa(descriptor->default_value_double()); + break; + case FieldDescriptor::CPPTYPE_BOOL: + return descriptor->default_value_bool() ? "true" : "false"; + break; + case FieldDescriptor::CPPTYPE_STRING: + if (descriptor->type() == FieldDescriptor::TYPE_BYTES) { + return CEscape(descriptor->default_value_string()); + } else { + return descriptor->default_value_string(); + } + break; + case FieldDescriptor::CPPTYPE_ENUM: + return descriptor->default_value_enum()->name(); + break; + case FieldDescriptor::CPPTYPE_MESSAGE: + GOOGLE_LOG(DFATAL) << "Messages can't have default values!"; + break; + } + return ""; + } + + std::string url_prefix_; + const DescriptorPool* pool_; +}; + +} // namespace + +TypeResolver* NewTypeResolverForDescriptorPool(const std::string& url_prefix, + const DescriptorPool* pool) { + return new DescriptorPoolTypeResolver(url_prefix, pool); +} + +} // namespace util +} // namespace protobuf +} // namespace google diff --git a/toolkit/components/protobuf/src/google/protobuf/util/type_resolver_util.h b/toolkit/components/protobuf/src/google/protobuf/util/type_resolver_util.h new file mode 100644 index 0000000000..7f6a4b9b11 --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/util/type_resolver_util.h @@ -0,0 +1,58 @@ +// 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. + +// Defines utilities for the TypeResolver. + +#ifndef GOOGLE_PROTOBUF_UTIL_TYPE_RESOLVER_UTIL_H__ +#define GOOGLE_PROTOBUF_UTIL_TYPE_RESOLVER_UTIL_H__ + +#include <string> + +namespace google { +namespace protobuf { +class DescriptorPool; +namespace util { +class TypeResolver; + +// Must be included last. +#include <google/protobuf/port_def.inc> + +// Creates a TypeResolver that serves type information in the given descriptor +// pool. Caller takes ownership of the returned TypeResolver. +PROTOBUF_EXPORT TypeResolver* NewTypeResolverForDescriptorPool( + const std::string& url_prefix, const DescriptorPool* pool); + +} // namespace util +} // namespace protobuf +} // namespace google + +#include <google/protobuf/port_undef.inc> + +#endif // GOOGLE_PROTOBUF_UTIL_TYPE_RESOLVER_UTIL_H__ diff --git a/toolkit/components/protobuf/src/google/protobuf/wire_format.cc b/toolkit/components/protobuf/src/google/protobuf/wire_format.cc new file mode 100644 index 0000000000..6fe63c86ce --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/wire_format.cc @@ -0,0 +1,1768 @@ +// 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. + +// Author: kenton@google.com (Kenton Varda) +// Based on original Protocol Buffers design by +// Sanjay Ghemawat, Jeff Dean, and others. + +#include <google/protobuf/wire_format.h> + +#include <stack> +#include <string> +#include <vector> + +#include <google/protobuf/stubs/logging.h> +#include <google/protobuf/stubs/common.h> +#include <google/protobuf/io/coded_stream.h> +#include <google/protobuf/io/zero_copy_stream.h> +#include <google/protobuf/io/zero_copy_stream_impl.h> +#include <google/protobuf/descriptor.h> +#include <google/protobuf/descriptor.pb.h> +#include <google/protobuf/dynamic_message.h> +#include <google/protobuf/map_field.h> +#include <google/protobuf/map_field_inl.h> +#include <google/protobuf/message.h> +#include <google/protobuf/message_lite.h> +#include <google/protobuf/parse_context.h> +#include <google/protobuf/unknown_field_set.h> + + +// Must be included last. +#include <google/protobuf/port_def.inc> + +const size_t kMapEntryTagByteSize = 2; + +namespace google { +namespace protobuf { +namespace internal { + +// Forward declare static functions +static size_t MapValueRefDataOnlyByteSize(const FieldDescriptor* field, + const MapValueConstRef& value); + +// =================================================================== + +bool UnknownFieldSetFieldSkipper::SkipField(io::CodedInputStream* input, + uint32_t tag) { + return WireFormat::SkipField(input, tag, unknown_fields_); +} + +bool UnknownFieldSetFieldSkipper::SkipMessage(io::CodedInputStream* input) { + return WireFormat::SkipMessage(input, unknown_fields_); +} + +void UnknownFieldSetFieldSkipper::SkipUnknownEnum(int field_number, int value) { + unknown_fields_->AddVarint(field_number, value); +} + +bool WireFormat::SkipField(io::CodedInputStream* input, uint32_t tag, + UnknownFieldSet* unknown_fields) { + int number = WireFormatLite::GetTagFieldNumber(tag); + // Field number 0 is illegal. + if (number == 0) return false; + + switch (WireFormatLite::GetTagWireType(tag)) { + case WireFormatLite::WIRETYPE_VARINT: { + uint64_t value; + if (!input->ReadVarint64(&value)) return false; + if (unknown_fields != nullptr) unknown_fields->AddVarint(number, value); + return true; + } + case WireFormatLite::WIRETYPE_FIXED64: { + uint64_t value; + if (!input->ReadLittleEndian64(&value)) return false; + if (unknown_fields != nullptr) unknown_fields->AddFixed64(number, value); + return true; + } + case WireFormatLite::WIRETYPE_LENGTH_DELIMITED: { + uint32_t length; + if (!input->ReadVarint32(&length)) return false; + if (unknown_fields == nullptr) { + if (!input->Skip(length)) return false; + } else { + if (!input->ReadString(unknown_fields->AddLengthDelimited(number), + length)) { + return false; + } + } + return true; + } + case WireFormatLite::WIRETYPE_START_GROUP: { + if (!input->IncrementRecursionDepth()) return false; + if (!SkipMessage(input, (unknown_fields == nullptr) + ? nullptr + : unknown_fields->AddGroup(number))) { + return false; + } + input->DecrementRecursionDepth(); + // Check that the ending tag matched the starting tag. + if (!input->LastTagWas( + WireFormatLite::MakeTag(WireFormatLite::GetTagFieldNumber(tag), + WireFormatLite::WIRETYPE_END_GROUP))) { + return false; + } + return true; + } + case WireFormatLite::WIRETYPE_END_GROUP: { + return false; + } + case WireFormatLite::WIRETYPE_FIXED32: { + uint32_t value; + if (!input->ReadLittleEndian32(&value)) return false; + if (unknown_fields != nullptr) unknown_fields->AddFixed32(number, value); + return true; + } + default: { + return false; + } + } +} + +bool WireFormat::SkipMessage(io::CodedInputStream* input, + UnknownFieldSet* unknown_fields) { + while (true) { + uint32_t tag = input->ReadTag(); + if (tag == 0) { + // End of input. This is a valid place to end, so return true. + return true; + } + + WireFormatLite::WireType wire_type = WireFormatLite::GetTagWireType(tag); + + if (wire_type == WireFormatLite::WIRETYPE_END_GROUP) { + // Must be the end of the message. + return true; + } + + if (!SkipField(input, tag, unknown_fields)) return false; + } +} + +bool WireFormat::ReadPackedEnumPreserveUnknowns(io::CodedInputStream* input, + uint32_t field_number, + bool (*is_valid)(int), + UnknownFieldSet* unknown_fields, + RepeatedField<int>* values) { + uint32_t length; + if (!input->ReadVarint32(&length)) return false; + io::CodedInputStream::Limit limit = input->PushLimit(length); + while (input->BytesUntilLimit() > 0) { + int value; + if (!WireFormatLite::ReadPrimitive<int, WireFormatLite::TYPE_ENUM>( + input, &value)) { + return false; + } + if (is_valid == nullptr || is_valid(value)) { + values->Add(value); + } else { + unknown_fields->AddVarint(field_number, value); + } + } + input->PopLimit(limit); + return true; +} + +uint8_t* WireFormat::InternalSerializeUnknownFieldsToArray( + const UnknownFieldSet& unknown_fields, uint8_t* target, + io::EpsCopyOutputStream* stream) { + for (int i = 0; i < unknown_fields.field_count(); i++) { + const UnknownField& field = unknown_fields.field(i); + + target = stream->EnsureSpace(target); + switch (field.type()) { + case UnknownField::TYPE_VARINT: + target = WireFormatLite::WriteUInt64ToArray(field.number(), + field.varint(), target); + break; + case UnknownField::TYPE_FIXED32: + target = WireFormatLite::WriteFixed32ToArray(field.number(), + field.fixed32(), target); + break; + case UnknownField::TYPE_FIXED64: + target = WireFormatLite::WriteFixed64ToArray(field.number(), + field.fixed64(), target); + break; + case UnknownField::TYPE_LENGTH_DELIMITED: + target = stream->WriteString(field.number(), field.length_delimited(), + target); + break; + case UnknownField::TYPE_GROUP: + target = WireFormatLite::WriteTagToArray( + field.number(), WireFormatLite::WIRETYPE_START_GROUP, target); + target = InternalSerializeUnknownFieldsToArray(field.group(), target, + stream); + target = stream->EnsureSpace(target); + target = WireFormatLite::WriteTagToArray( + field.number(), WireFormatLite::WIRETYPE_END_GROUP, target); + break; + } + } + return target; +} + +uint8_t* WireFormat::InternalSerializeUnknownMessageSetItemsToArray( + const UnknownFieldSet& unknown_fields, uint8_t* target, + io::EpsCopyOutputStream* stream) { + for (int i = 0; i < unknown_fields.field_count(); i++) { + const UnknownField& field = unknown_fields.field(i); + + // The only unknown fields that are allowed to exist in a MessageSet are + // messages, which are length-delimited. + if (field.type() == UnknownField::TYPE_LENGTH_DELIMITED) { + target = stream->EnsureSpace(target); + // Start group. + target = io::CodedOutputStream::WriteTagToArray( + WireFormatLite::kMessageSetItemStartTag, target); + + // Write type ID. + target = io::CodedOutputStream::WriteTagToArray( + WireFormatLite::kMessageSetTypeIdTag, target); + target = + io::CodedOutputStream::WriteVarint32ToArray(field.number(), target); + + // Write message. + target = io::CodedOutputStream::WriteTagToArray( + WireFormatLite::kMessageSetMessageTag, target); + + target = field.InternalSerializeLengthDelimitedNoTag(target, stream); + + target = stream->EnsureSpace(target); + // End group. + target = io::CodedOutputStream::WriteTagToArray( + WireFormatLite::kMessageSetItemEndTag, target); + } + } + + return target; +} + +size_t WireFormat::ComputeUnknownFieldsSize( + const UnknownFieldSet& unknown_fields) { + size_t size = 0; + for (int i = 0; i < unknown_fields.field_count(); i++) { + const UnknownField& field = unknown_fields.field(i); + + switch (field.type()) { + case UnknownField::TYPE_VARINT: + size += io::CodedOutputStream::VarintSize32(WireFormatLite::MakeTag( + field.number(), WireFormatLite::WIRETYPE_VARINT)); + size += io::CodedOutputStream::VarintSize64(field.varint()); + break; + case UnknownField::TYPE_FIXED32: + size += io::CodedOutputStream::VarintSize32(WireFormatLite::MakeTag( + field.number(), WireFormatLite::WIRETYPE_FIXED32)); + size += sizeof(int32_t); + break; + case UnknownField::TYPE_FIXED64: + size += io::CodedOutputStream::VarintSize32(WireFormatLite::MakeTag( + field.number(), WireFormatLite::WIRETYPE_FIXED64)); + size += sizeof(int64_t); + break; + case UnknownField::TYPE_LENGTH_DELIMITED: + size += io::CodedOutputStream::VarintSize32(WireFormatLite::MakeTag( + field.number(), WireFormatLite::WIRETYPE_LENGTH_DELIMITED)); + size += io::CodedOutputStream::VarintSize32( + field.length_delimited().size()); + size += field.length_delimited().size(); + break; + case UnknownField::TYPE_GROUP: + size += io::CodedOutputStream::VarintSize32(WireFormatLite::MakeTag( + field.number(), WireFormatLite::WIRETYPE_START_GROUP)); + size += ComputeUnknownFieldsSize(field.group()); + size += io::CodedOutputStream::VarintSize32(WireFormatLite::MakeTag( + field.number(), WireFormatLite::WIRETYPE_END_GROUP)); + break; + } + } + + return size; +} + +size_t WireFormat::ComputeUnknownMessageSetItemsSize( + const UnknownFieldSet& unknown_fields) { + size_t size = 0; + for (int i = 0; i < unknown_fields.field_count(); i++) { + const UnknownField& field = unknown_fields.field(i); + + // The only unknown fields that are allowed to exist in a MessageSet are + // messages, which are length-delimited. + if (field.type() == UnknownField::TYPE_LENGTH_DELIMITED) { + size += WireFormatLite::kMessageSetItemTagsSize; + size += io::CodedOutputStream::VarintSize32(field.number()); + + int field_size = field.GetLengthDelimitedSize(); + size += io::CodedOutputStream::VarintSize32(field_size); + size += field_size; + } + } + + return size; +} + +// =================================================================== + +bool WireFormat::ParseAndMergePartial(io::CodedInputStream* input, + Message* message) { + const Descriptor* descriptor = message->GetDescriptor(); + const Reflection* message_reflection = message->GetReflection(); + + while (true) { + uint32_t tag = input->ReadTag(); + if (tag == 0) { + // End of input. This is a valid place to end, so return true. + return true; + } + + if (WireFormatLite::GetTagWireType(tag) == + WireFormatLite::WIRETYPE_END_GROUP) { + // Must be the end of the message. + return true; + } + + const FieldDescriptor* field = nullptr; + + if (descriptor != nullptr) { + int field_number = WireFormatLite::GetTagFieldNumber(tag); + field = descriptor->FindFieldByNumber(field_number); + + // If that failed, check if the field is an extension. + if (field == nullptr && descriptor->IsExtensionNumber(field_number)) { + if (input->GetExtensionPool() == nullptr) { + field = message_reflection->FindKnownExtensionByNumber(field_number); + } else { + field = input->GetExtensionPool()->FindExtensionByNumber( + descriptor, field_number); + } + } + + // If that failed, but we're a MessageSet, and this is the tag for a + // MessageSet item, then parse that. + if (field == nullptr && descriptor->options().message_set_wire_format() && + tag == WireFormatLite::kMessageSetItemStartTag) { + if (!ParseAndMergeMessageSetItem(input, message)) { + return false; + } + continue; // Skip ParseAndMergeField(); already taken care of. + } + } + + if (!ParseAndMergeField(tag, field, message, input)) { + return false; + } + } +} + +bool WireFormat::SkipMessageSetField(io::CodedInputStream* input, + uint32_t field_number, + UnknownFieldSet* unknown_fields) { + uint32_t length; + if (!input->ReadVarint32(&length)) return false; + return input->ReadString(unknown_fields->AddLengthDelimited(field_number), + length); +} + +bool WireFormat::ParseAndMergeMessageSetField(uint32_t field_number, + const FieldDescriptor* field, + Message* message, + io::CodedInputStream* input) { + const Reflection* message_reflection = message->GetReflection(); + if (field == nullptr) { + // We store unknown MessageSet extensions as groups. + return SkipMessageSetField( + input, field_number, message_reflection->MutableUnknownFields(message)); + } else if (field->is_repeated() || + field->type() != FieldDescriptor::TYPE_MESSAGE) { + // This shouldn't happen as we only allow optional message extensions to + // MessageSet. + GOOGLE_LOG(ERROR) << "Extensions of MessageSets must be optional messages."; + return false; + } else { + Message* sub_message = message_reflection->MutableMessage( + message, field, input->GetExtensionFactory()); + return WireFormatLite::ReadMessage(input, sub_message); + } +} + +static bool StrictUtf8Check(const FieldDescriptor* field) { + return field->file()->syntax() == FileDescriptor::SYNTAX_PROTO3; +} + +bool WireFormat::ParseAndMergeField( + uint32_t tag, + const FieldDescriptor* field, // May be nullptr for unknown + Message* message, io::CodedInputStream* input) { + const Reflection* message_reflection = message->GetReflection(); + + enum { UNKNOWN, NORMAL_FORMAT, PACKED_FORMAT } value_format; + + if (field == nullptr) { + value_format = UNKNOWN; + } else if (WireFormatLite::GetTagWireType(tag) == + WireTypeForFieldType(field->type())) { + value_format = NORMAL_FORMAT; + } else if (field->is_packable() && + WireFormatLite::GetTagWireType(tag) == + WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + value_format = PACKED_FORMAT; + } else { + // We don't recognize this field. Either the field number is unknown + // or the wire type doesn't match. Put it in our unknown field set. + value_format = UNKNOWN; + } + + if (value_format == UNKNOWN) { + return SkipField(input, tag, + message_reflection->MutableUnknownFields(message)); + } else if (value_format == PACKED_FORMAT) { + uint32_t length; + if (!input->ReadVarint32(&length)) return false; + io::CodedInputStream::Limit limit = input->PushLimit(length); + + switch (field->type()) { +#define HANDLE_PACKED_TYPE(TYPE, CPPTYPE, CPPTYPE_METHOD) \ + case FieldDescriptor::TYPE_##TYPE: { \ + while (input->BytesUntilLimit() > 0) { \ + CPPTYPE value; \ + if (!WireFormatLite::ReadPrimitive<CPPTYPE, \ + WireFormatLite::TYPE_##TYPE>(input, \ + &value)) \ + return false; \ + message_reflection->Add##CPPTYPE_METHOD(message, field, value); \ + } \ + break; \ + } + + HANDLE_PACKED_TYPE(INT32, int32_t, Int32) + HANDLE_PACKED_TYPE(INT64, int64_t, Int64) + HANDLE_PACKED_TYPE(SINT32, int32_t, Int32) + HANDLE_PACKED_TYPE(SINT64, int64_t, Int64) + HANDLE_PACKED_TYPE(UINT32, uint32_t, UInt32) + HANDLE_PACKED_TYPE(UINT64, uint64_t, UInt64) + + HANDLE_PACKED_TYPE(FIXED32, uint32_t, UInt32) + HANDLE_PACKED_TYPE(FIXED64, uint64_t, UInt64) + HANDLE_PACKED_TYPE(SFIXED32, int32_t, Int32) + HANDLE_PACKED_TYPE(SFIXED64, int64_t, Int64) + + HANDLE_PACKED_TYPE(FLOAT, float, Float) + HANDLE_PACKED_TYPE(DOUBLE, double, Double) + + HANDLE_PACKED_TYPE(BOOL, bool, Bool) +#undef HANDLE_PACKED_TYPE + + case FieldDescriptor::TYPE_ENUM: { + while (input->BytesUntilLimit() > 0) { + int value; + if (!WireFormatLite::ReadPrimitive<int, WireFormatLite::TYPE_ENUM>( + input, &value)) + return false; + if (message->GetDescriptor()->file()->syntax() == + FileDescriptor::SYNTAX_PROTO3) { + message_reflection->AddEnumValue(message, field, value); + } else { + const EnumValueDescriptor* enum_value = + field->enum_type()->FindValueByNumber(value); + if (enum_value != nullptr) { + message_reflection->AddEnum(message, field, enum_value); + } else { + // The enum value is not one of the known values. Add it to the + // UnknownFieldSet. + int64_t sign_extended_value = static_cast<int64_t>(value); + message_reflection->MutableUnknownFields(message)->AddVarint( + WireFormatLite::GetTagFieldNumber(tag), sign_extended_value); + } + } + } + + break; + } + + case FieldDescriptor::TYPE_STRING: + case FieldDescriptor::TYPE_GROUP: + case FieldDescriptor::TYPE_MESSAGE: + case FieldDescriptor::TYPE_BYTES: + // Can't have packed fields of these types: these should be caught by + // the protocol compiler. + return false; + break; + } + + input->PopLimit(limit); + } else { + // Non-packed value (value_format == NORMAL_FORMAT) + switch (field->type()) { +#define HANDLE_TYPE(TYPE, CPPTYPE, CPPTYPE_METHOD) \ + case FieldDescriptor::TYPE_##TYPE: { \ + CPPTYPE value; \ + if (!WireFormatLite::ReadPrimitive<CPPTYPE, WireFormatLite::TYPE_##TYPE>( \ + input, &value)) \ + return false; \ + if (field->is_repeated()) { \ + message_reflection->Add##CPPTYPE_METHOD(message, field, value); \ + } else { \ + message_reflection->Set##CPPTYPE_METHOD(message, field, value); \ + } \ + break; \ + } + + HANDLE_TYPE(INT32, int32_t, Int32) + HANDLE_TYPE(INT64, int64_t, Int64) + HANDLE_TYPE(SINT32, int32_t, Int32) + HANDLE_TYPE(SINT64, int64_t, Int64) + HANDLE_TYPE(UINT32, uint32_t, UInt32) + HANDLE_TYPE(UINT64, uint64_t, UInt64) + + HANDLE_TYPE(FIXED32, uint32_t, UInt32) + HANDLE_TYPE(FIXED64, uint64_t, UInt64) + HANDLE_TYPE(SFIXED32, int32_t, Int32) + HANDLE_TYPE(SFIXED64, int64_t, Int64) + + HANDLE_TYPE(FLOAT, float, Float) + HANDLE_TYPE(DOUBLE, double, Double) + + HANDLE_TYPE(BOOL, bool, Bool) +#undef HANDLE_TYPE + + case FieldDescriptor::TYPE_ENUM: { + int value; + if (!WireFormatLite::ReadPrimitive<int, WireFormatLite::TYPE_ENUM>( + input, &value)) + return false; + if (field->is_repeated()) { + message_reflection->AddEnumValue(message, field, value); + } else { + message_reflection->SetEnumValue(message, field, value); + } + break; + } + + // Handle strings separately so that we can optimize the ctype=CORD case. + case FieldDescriptor::TYPE_STRING: { + bool strict_utf8_check = StrictUtf8Check(field); + std::string value; + if (!WireFormatLite::ReadString(input, &value)) return false; + if (strict_utf8_check) { + if (!WireFormatLite::VerifyUtf8String(value.data(), value.length(), + WireFormatLite::PARSE, + field->full_name().c_str())) { + return false; + } + } else { + VerifyUTF8StringNamedField(value.data(), value.length(), PARSE, + field->full_name().c_str()); + } + if (field->is_repeated()) { + message_reflection->AddString(message, field, value); + } else { + message_reflection->SetString(message, field, value); + } + break; + } + + case FieldDescriptor::TYPE_BYTES: { + std::string value; + if (!WireFormatLite::ReadBytes(input, &value)) return false; + if (field->is_repeated()) { + message_reflection->AddString(message, field, value); + } else { + message_reflection->SetString(message, field, value); + } + break; + } + + case FieldDescriptor::TYPE_GROUP: { + Message* sub_message; + if (field->is_repeated()) { + sub_message = message_reflection->AddMessage( + message, field, input->GetExtensionFactory()); + } else { + sub_message = message_reflection->MutableMessage( + message, field, input->GetExtensionFactory()); + } + + if (!WireFormatLite::ReadGroup(WireFormatLite::GetTagFieldNumber(tag), + input, sub_message)) + return false; + break; + } + + case FieldDescriptor::TYPE_MESSAGE: { + Message* sub_message; + if (field->is_repeated()) { + sub_message = message_reflection->AddMessage( + message, field, input->GetExtensionFactory()); + } else { + sub_message = message_reflection->MutableMessage( + message, field, input->GetExtensionFactory()); + } + + if (!WireFormatLite::ReadMessage(input, sub_message)) return false; + break; + } + } + } + + return true; +} + +bool WireFormat::ParseAndMergeMessageSetItem(io::CodedInputStream* input, + Message* message) { + struct MSReflective { + bool ParseField(int type_id, io::CodedInputStream* input) { + const FieldDescriptor* field = + message_reflection->FindKnownExtensionByNumber(type_id); + return ParseAndMergeMessageSetField(type_id, field, message, input); + } + + bool SkipField(uint32_t tag, io::CodedInputStream* input) { + return WireFormat::SkipField(input, tag, nullptr); + } + + const Reflection* message_reflection; + Message* message; + }; + + return ParseMessageSetItemImpl( + input, MSReflective{message->GetReflection(), message}); +} + +struct WireFormat::MessageSetParser { + const char* _InternalParse(const char* ptr, internal::ParseContext* ctx) { + // Parse a MessageSetItem + auto metadata = reflection->MutableInternalMetadata(msg); + enum class State { kNoTag, kHasType, kHasPayload, kDone }; + State state = State::kNoTag; + + std::string payload; + uint32_t type_id = 0; + while (!ctx->Done(&ptr)) { + // We use 64 bit tags in order to allow typeid's that span the whole + // range of 32 bit numbers. + uint32_t tag = static_cast<uint8_t>(*ptr++); + if (tag == WireFormatLite::kMessageSetTypeIdTag) { + uint64_t tmp; + ptr = ParseBigVarint(ptr, &tmp); + GOOGLE_PROTOBUF_PARSER_ASSERT(ptr); + if (state == State::kNoTag) { + type_id = tmp; + state = State::kHasType; + } else if (state == State::kHasPayload) { + type_id = tmp; + const FieldDescriptor* field; + if (ctx->data().pool == nullptr) { + field = reflection->FindKnownExtensionByNumber(type_id); + } else { + field = + ctx->data().pool->FindExtensionByNumber(descriptor, type_id); + } + if (field == nullptr || field->message_type() == nullptr) { + WriteLengthDelimited( + type_id, payload, + metadata->mutable_unknown_fields<UnknownFieldSet>()); + } else { + Message* value = + field->is_repeated() + ? reflection->AddMessage(msg, field, ctx->data().factory) + : reflection->MutableMessage(msg, field, + ctx->data().factory); + const char* p; + // We can't use regular parse from string as we have to track + // proper recursion depth and descriptor pools. + ParseContext tmp_ctx(ctx->depth(), false, &p, payload); + tmp_ctx.data().pool = ctx->data().pool; + tmp_ctx.data().factory = ctx->data().factory; + GOOGLE_PROTOBUF_PARSER_ASSERT(value->_InternalParse(p, &tmp_ctx) && + tmp_ctx.EndedAtLimit()); + } + state = State::kDone; + } + continue; + } else if (tag == WireFormatLite::kMessageSetMessageTag) { + if (state == State::kNoTag) { + int32_t size = ReadSize(&ptr); + GOOGLE_PROTOBUF_PARSER_ASSERT(ptr); + ptr = ctx->ReadString(ptr, size, &payload); + GOOGLE_PROTOBUF_PARSER_ASSERT(ptr); + state = State::kHasPayload; + } else if (state == State::kHasType) { + // We're now parsing the payload + const FieldDescriptor* field = nullptr; + if (descriptor->IsExtensionNumber(type_id)) { + if (ctx->data().pool == nullptr) { + field = reflection->FindKnownExtensionByNumber(type_id); + } else { + field = + ctx->data().pool->FindExtensionByNumber(descriptor, type_id); + } + } + ptr = WireFormat::_InternalParseAndMergeField( + msg, ptr, ctx, static_cast<uint64_t>(type_id) * 8 + 2, reflection, + field); + state = State::kDone; + } else { + int32_t size = ReadSize(&ptr); + GOOGLE_PROTOBUF_PARSER_ASSERT(ptr); + ptr = ctx->Skip(ptr, size); + GOOGLE_PROTOBUF_PARSER_ASSERT(ptr); + } + } else { + // An unknown field in MessageSetItem. + ptr = ReadTag(ptr - 1, &tag); + if (tag == 0 || (tag & 7) == WireFormatLite::WIRETYPE_END_GROUP) { + ctx->SetLastTag(tag); + return ptr; + } + // Skip field. + ptr = internal::UnknownFieldParse( + tag, static_cast<std::string*>(nullptr), ptr, ctx); + } + GOOGLE_PROTOBUF_PARSER_ASSERT(ptr); + } + return ptr; + } + + const char* ParseMessageSet(const char* ptr, internal::ParseContext* ctx) { + while (!ctx->Done(&ptr)) { + uint32_t tag; + ptr = ReadTag(ptr, &tag); + if (PROTOBUF_PREDICT_FALSE(ptr == nullptr)) return nullptr; + if (tag == 0 || (tag & 7) == WireFormatLite::WIRETYPE_END_GROUP) { + ctx->SetLastTag(tag); + break; + } + if (tag == WireFormatLite::kMessageSetItemStartTag) { + // A message set item starts + ptr = ctx->ParseGroup(this, ptr, tag); + } else { + // Parse other fields as normal extensions. + int field_number = WireFormatLite::GetTagFieldNumber(tag); + const FieldDescriptor* field = nullptr; + if (descriptor->IsExtensionNumber(field_number)) { + if (ctx->data().pool == nullptr) { + field = reflection->FindKnownExtensionByNumber(field_number); + } else { + field = ctx->data().pool->FindExtensionByNumber(descriptor, + field_number); + } + } + ptr = WireFormat::_InternalParseAndMergeField(msg, ptr, ctx, tag, + reflection, field); + } + if (PROTOBUF_PREDICT_FALSE(ptr == nullptr)) return nullptr; + } + return ptr; + } + + Message* msg; + const Descriptor* descriptor; + const Reflection* reflection; +}; + +const char* WireFormat::_InternalParse(Message* msg, const char* ptr, + internal::ParseContext* ctx) { + const Descriptor* descriptor = msg->GetDescriptor(); + const Reflection* reflection = msg->GetReflection(); + GOOGLE_DCHECK(descriptor); + GOOGLE_DCHECK(reflection); + if (descriptor->options().message_set_wire_format()) { + MessageSetParser message_set{msg, descriptor, reflection}; + return message_set.ParseMessageSet(ptr, ctx); + } + while (!ctx->Done(&ptr)) { + uint32_t tag; + ptr = ReadTag(ptr, &tag); + if (PROTOBUF_PREDICT_FALSE(ptr == nullptr)) return nullptr; + if (tag == 0 || (tag & 7) == WireFormatLite::WIRETYPE_END_GROUP) { + ctx->SetLastTag(tag); + break; + } + const FieldDescriptor* field = nullptr; + + int field_number = WireFormatLite::GetTagFieldNumber(tag); + field = descriptor->FindFieldByNumber(field_number); + + // If that failed, check if the field is an extension. + if (field == nullptr && descriptor->IsExtensionNumber(field_number)) { + if (ctx->data().pool == nullptr) { + field = reflection->FindKnownExtensionByNumber(field_number); + } else { + field = + ctx->data().pool->FindExtensionByNumber(descriptor, field_number); + } + } + + ptr = _InternalParseAndMergeField(msg, ptr, ctx, tag, reflection, field); + if (PROTOBUF_PREDICT_FALSE(ptr == nullptr)) return nullptr; + } + return ptr; +} + +const char* WireFormat::_InternalParseAndMergeField( + Message* msg, const char* ptr, internal::ParseContext* ctx, uint64_t tag, + const Reflection* reflection, const FieldDescriptor* field) { + if (field == nullptr) { + // unknown field set parser takes 64bit tags, because message set type ids + // span the full 32 bit range making the tag span [0, 2^35) range. + return internal::UnknownFieldParse( + tag, reflection->MutableUnknownFields(msg), ptr, ctx); + } + if (WireFormatLite::GetTagWireType(tag) != + WireTypeForFieldType(field->type())) { + if (field->is_packable() && WireFormatLite::GetTagWireType(tag) == + WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + switch (field->type()) { +#define HANDLE_PACKED_TYPE(TYPE, CPPTYPE, CPPTYPE_METHOD) \ + case FieldDescriptor::TYPE_##TYPE: { \ + ptr = internal::Packed##CPPTYPE_METHOD##Parser( \ + reflection->MutableRepeatedFieldInternal<CPPTYPE>(msg, field), ptr, \ + ctx); \ + return ptr; \ + } + + HANDLE_PACKED_TYPE(INT32, int32_t, Int32) + HANDLE_PACKED_TYPE(INT64, int64_t, Int64) + HANDLE_PACKED_TYPE(SINT32, int32_t, SInt32) + HANDLE_PACKED_TYPE(SINT64, int64_t, SInt64) + HANDLE_PACKED_TYPE(UINT32, uint32_t, UInt32) + HANDLE_PACKED_TYPE(UINT64, uint64_t, UInt64) + + HANDLE_PACKED_TYPE(FIXED32, uint32_t, Fixed32) + HANDLE_PACKED_TYPE(FIXED64, uint64_t, Fixed64) + HANDLE_PACKED_TYPE(SFIXED32, int32_t, SFixed32) + HANDLE_PACKED_TYPE(SFIXED64, int64_t, SFixed64) + + HANDLE_PACKED_TYPE(FLOAT, float, Float) + HANDLE_PACKED_TYPE(DOUBLE, double, Double) + + HANDLE_PACKED_TYPE(BOOL, bool, Bool) +#undef HANDLE_PACKED_TYPE + + case FieldDescriptor::TYPE_ENUM: { + auto rep_enum = + reflection->MutableRepeatedFieldInternal<int>(msg, field); + bool open_enum = false; + if (field->file()->syntax() == FileDescriptor::SYNTAX_PROTO3 || + open_enum) { + ptr = internal::PackedEnumParser(rep_enum, ptr, ctx); + } else { + return ctx->ReadPackedVarint( + ptr, [rep_enum, field, reflection, msg](uint64_t val) { + if (field->enum_type()->FindValueByNumber(val) != nullptr) { + rep_enum->Add(val); + } else { + WriteVarint(field->number(), val, + reflection->MutableUnknownFields(msg)); + } + }); + } + return ptr; + } + + case FieldDescriptor::TYPE_STRING: + case FieldDescriptor::TYPE_GROUP: + case FieldDescriptor::TYPE_MESSAGE: + case FieldDescriptor::TYPE_BYTES: + GOOGLE_LOG(FATAL) << "Can't reach"; + return nullptr; + } + } else { + // mismatched wiretype; + return internal::UnknownFieldParse( + tag, reflection->MutableUnknownFields(msg), ptr, ctx); + } + } + + // Non-packed value + bool utf8_check = false; + bool strict_utf8_check = false; + switch (field->type()) { +#define HANDLE_TYPE(TYPE, CPPTYPE, CPPTYPE_METHOD) \ + case FieldDescriptor::TYPE_##TYPE: { \ + CPPTYPE value; \ + ptr = VarintParse(ptr, &value); \ + if (ptr == nullptr) return nullptr; \ + if (field->is_repeated()) { \ + reflection->Add##CPPTYPE_METHOD(msg, field, value); \ + } else { \ + reflection->Set##CPPTYPE_METHOD(msg, field, value); \ + } \ + return ptr; \ + } + + HANDLE_TYPE(BOOL, uint64_t, Bool) + HANDLE_TYPE(INT32, uint32_t, Int32) + HANDLE_TYPE(INT64, uint64_t, Int64) + HANDLE_TYPE(UINT32, uint32_t, UInt32) + HANDLE_TYPE(UINT64, uint64_t, UInt64) + + case FieldDescriptor::TYPE_SINT32: { + int32_t value = ReadVarintZigZag32(&ptr); + if (ptr == nullptr) return nullptr; + if (field->is_repeated()) { + reflection->AddInt32(msg, field, value); + } else { + reflection->SetInt32(msg, field, value); + } + return ptr; + } + case FieldDescriptor::TYPE_SINT64: { + int64_t value = ReadVarintZigZag64(&ptr); + if (ptr == nullptr) return nullptr; + if (field->is_repeated()) { + reflection->AddInt64(msg, field, value); + } else { + reflection->SetInt64(msg, field, value); + } + return ptr; + } +#undef HANDLE_TYPE +#define HANDLE_TYPE(TYPE, CPPTYPE, CPPTYPE_METHOD) \ + case FieldDescriptor::TYPE_##TYPE: { \ + CPPTYPE value; \ + value = UnalignedLoad<CPPTYPE>(ptr); \ + ptr += sizeof(CPPTYPE); \ + if (field->is_repeated()) { \ + reflection->Add##CPPTYPE_METHOD(msg, field, value); \ + } else { \ + reflection->Set##CPPTYPE_METHOD(msg, field, value); \ + } \ + return ptr; \ + } + + HANDLE_TYPE(FIXED32, uint32_t, UInt32) + HANDLE_TYPE(FIXED64, uint64_t, UInt64) + HANDLE_TYPE(SFIXED32, int32_t, Int32) + HANDLE_TYPE(SFIXED64, int64_t, Int64) + + HANDLE_TYPE(FLOAT, float, Float) + HANDLE_TYPE(DOUBLE, double, Double) + +#undef HANDLE_TYPE + + case FieldDescriptor::TYPE_ENUM: { + uint32_t value; + ptr = VarintParse(ptr, &value); + if (ptr == nullptr) return nullptr; + if (field->is_repeated()) { + reflection->AddEnumValue(msg, field, value); + } else { + reflection->SetEnumValue(msg, field, value); + } + return ptr; + } + + // Handle strings separately so that we can optimize the ctype=CORD case. + case FieldDescriptor::TYPE_STRING: + utf8_check = true; + strict_utf8_check = StrictUtf8Check(field); + PROTOBUF_FALLTHROUGH_INTENDED; + case FieldDescriptor::TYPE_BYTES: { + int size = ReadSize(&ptr); + if (ptr == nullptr) return nullptr; + std::string value; + ptr = ctx->ReadString(ptr, size, &value); + if (ptr == nullptr) return nullptr; + if (utf8_check) { + if (strict_utf8_check) { + if (!WireFormatLite::VerifyUtf8String(value.data(), value.length(), + WireFormatLite::PARSE, + field->full_name().c_str())) { + return nullptr; + } + } else { + VerifyUTF8StringNamedField(value.data(), value.length(), PARSE, + field->full_name().c_str()); + } + } + if (field->is_repeated()) { + reflection->AddString(msg, field, std::move(value)); + } else { + reflection->SetString(msg, field, std::move(value)); + } + return ptr; + } + + case FieldDescriptor::TYPE_GROUP: { + Message* sub_message; + if (field->is_repeated()) { + sub_message = reflection->AddMessage(msg, field, ctx->data().factory); + } else { + sub_message = + reflection->MutableMessage(msg, field, ctx->data().factory); + } + + return ctx->ParseGroup(sub_message, ptr, tag); + } + + case FieldDescriptor::TYPE_MESSAGE: { + Message* sub_message; + if (field->is_repeated()) { + sub_message = reflection->AddMessage(msg, field, ctx->data().factory); + } else { + sub_message = + reflection->MutableMessage(msg, field, ctx->data().factory); + } + return ctx->ParseMessage(sub_message, ptr); + } + } + + // GCC 8 complains about control reaching end of non-void function here. + // Let's keep it happy by returning a nullptr. + return nullptr; +} + +// =================================================================== + +uint8_t* WireFormat::_InternalSerialize(const Message& message, uint8_t* target, + io::EpsCopyOutputStream* stream) { + const Descriptor* descriptor = message.GetDescriptor(); + const Reflection* message_reflection = message.GetReflection(); + + std::vector<const FieldDescriptor*> fields; + + // Fields of map entry should always be serialized. + if (descriptor->options().map_entry()) { + for (int i = 0; i < descriptor->field_count(); i++) { + fields.push_back(descriptor->field(i)); + } + } else { + message_reflection->ListFields(message, &fields); + } + + for (auto field : fields) { + target = InternalSerializeField(field, message, target, stream); + } + + if (descriptor->options().message_set_wire_format()) { + return InternalSerializeUnknownMessageSetItemsToArray( + message_reflection->GetUnknownFields(message), target, stream); + } else { + return InternalSerializeUnknownFieldsToArray( + message_reflection->GetUnknownFields(message), target, stream); + } +} + +uint8_t* SerializeMapKeyWithCachedSizes(const FieldDescriptor* field, + const MapKey& value, uint8_t* target, + io::EpsCopyOutputStream* stream) { + target = stream->EnsureSpace(target); + switch (field->type()) { + case FieldDescriptor::TYPE_DOUBLE: + case FieldDescriptor::TYPE_FLOAT: + case FieldDescriptor::TYPE_GROUP: + case FieldDescriptor::TYPE_MESSAGE: + case FieldDescriptor::TYPE_BYTES: + case FieldDescriptor::TYPE_ENUM: + GOOGLE_LOG(FATAL) << "Unsupported"; + break; +#define CASE_TYPE(FieldType, CamelFieldType, CamelCppType) \ + case FieldDescriptor::TYPE_##FieldType: \ + target = WireFormatLite::Write##CamelFieldType##ToArray( \ + 1, value.Get##CamelCppType##Value(), target); \ + break; + CASE_TYPE(INT64, Int64, Int64) + CASE_TYPE(UINT64, UInt64, UInt64) + CASE_TYPE(INT32, Int32, Int32) + CASE_TYPE(FIXED64, Fixed64, UInt64) + CASE_TYPE(FIXED32, Fixed32, UInt32) + CASE_TYPE(BOOL, Bool, Bool) + CASE_TYPE(UINT32, UInt32, UInt32) + CASE_TYPE(SFIXED32, SFixed32, Int32) + CASE_TYPE(SFIXED64, SFixed64, Int64) + CASE_TYPE(SINT32, SInt32, Int32) + CASE_TYPE(SINT64, SInt64, Int64) +#undef CASE_TYPE + case FieldDescriptor::TYPE_STRING: + target = stream->WriteString(1, value.GetStringValue(), target); + break; + } + return target; +} + +static uint8_t* SerializeMapValueRefWithCachedSizes( + const FieldDescriptor* field, const MapValueConstRef& value, + uint8_t* target, io::EpsCopyOutputStream* stream) { + target = stream->EnsureSpace(target); + switch (field->type()) { +#define CASE_TYPE(FieldType, CamelFieldType, CamelCppType) \ + case FieldDescriptor::TYPE_##FieldType: \ + target = WireFormatLite::Write##CamelFieldType##ToArray( \ + 2, value.Get##CamelCppType##Value(), target); \ + break; + CASE_TYPE(INT64, Int64, Int64) + CASE_TYPE(UINT64, UInt64, UInt64) + CASE_TYPE(INT32, Int32, Int32) + CASE_TYPE(FIXED64, Fixed64, UInt64) + CASE_TYPE(FIXED32, Fixed32, UInt32) + CASE_TYPE(BOOL, Bool, Bool) + CASE_TYPE(UINT32, UInt32, UInt32) + CASE_TYPE(SFIXED32, SFixed32, Int32) + CASE_TYPE(SFIXED64, SFixed64, Int64) + CASE_TYPE(SINT32, SInt32, Int32) + CASE_TYPE(SINT64, SInt64, Int64) + CASE_TYPE(ENUM, Enum, Enum) + CASE_TYPE(DOUBLE, Double, Double) + CASE_TYPE(FLOAT, Float, Float) +#undef CASE_TYPE + case FieldDescriptor::TYPE_STRING: + case FieldDescriptor::TYPE_BYTES: + target = stream->WriteString(2, value.GetStringValue(), target); + break; + case FieldDescriptor::TYPE_MESSAGE: { + auto& msg = value.GetMessageValue(); + target = WireFormatLite::InternalWriteMessage(2, msg, msg.GetCachedSize(), + target, stream); + } break; + case FieldDescriptor::TYPE_GROUP: + target = WireFormatLite::InternalWriteGroup(2, value.GetMessageValue(), + target, stream); + break; + } + return target; +} + +class MapKeySorter { + public: + static std::vector<MapKey> SortKey(const Message& message, + const Reflection* reflection, + const FieldDescriptor* field) { + std::vector<MapKey> sorted_key_list; + for (MapIterator it = + reflection->MapBegin(const_cast<Message*>(&message), field); + it != reflection->MapEnd(const_cast<Message*>(&message), field); + ++it) { + sorted_key_list.push_back(it.GetKey()); + } + MapKeyComparator comparator; + std::sort(sorted_key_list.begin(), sorted_key_list.end(), comparator); + return sorted_key_list; + } + + private: + class MapKeyComparator { + public: + bool operator()(const MapKey& a, const MapKey& b) const { + GOOGLE_DCHECK(a.type() == b.type()); + switch (a.type()) { +#define CASE_TYPE(CppType, CamelCppType) \ + case FieldDescriptor::CPPTYPE_##CppType: { \ + return a.Get##CamelCppType##Value() < b.Get##CamelCppType##Value(); \ + } + CASE_TYPE(STRING, String) + CASE_TYPE(INT64, Int64) + CASE_TYPE(INT32, Int32) + CASE_TYPE(UINT64, UInt64) + CASE_TYPE(UINT32, UInt32) + CASE_TYPE(BOOL, Bool) +#undef CASE_TYPE + + default: + GOOGLE_LOG(DFATAL) << "Invalid key for map field."; + return true; + } + } + }; +}; + +static uint8_t* InternalSerializeMapEntry(const FieldDescriptor* field, + const MapKey& key, + const MapValueConstRef& value, + uint8_t* target, + io::EpsCopyOutputStream* stream) { + const FieldDescriptor* key_field = field->message_type()->field(0); + const FieldDescriptor* value_field = field->message_type()->field(1); + + size_t size = kMapEntryTagByteSize; + size += MapKeyDataOnlyByteSize(key_field, key); + size += MapValueRefDataOnlyByteSize(value_field, value); + target = stream->EnsureSpace(target); + target = WireFormatLite::WriteTagToArray( + field->number(), WireFormatLite::WIRETYPE_LENGTH_DELIMITED, target); + target = io::CodedOutputStream::WriteVarint32ToArray(size, target); + target = SerializeMapKeyWithCachedSizes(key_field, key, target, stream); + target = + SerializeMapValueRefWithCachedSizes(value_field, value, target, stream); + return target; +} + +uint8_t* WireFormat::InternalSerializeField(const FieldDescriptor* field, + const Message& message, + uint8_t* target, + io::EpsCopyOutputStream* stream) { + const Reflection* message_reflection = message.GetReflection(); + + if (field->is_extension() && + field->containing_type()->options().message_set_wire_format() && + field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE && + !field->is_repeated()) { + return InternalSerializeMessageSetItem(field, message, target, stream); + } + + // For map fields, we can use either repeated field reflection or map + // reflection. Our choice has some subtle effects. If we use repeated field + // reflection here, then the repeated field representation becomes + // authoritative for this field: any existing references that came from map + // reflection remain valid for reading, but mutations to them are lost and + // will be overwritten next time we call map reflection! + // + // So far this mainly affects Python, which keeps long-term references to map + // values around, and always uses map reflection. See: b/35918691 + // + // Here we choose to use map reflection API as long as the internal + // map is valid. In this way, the serialization doesn't change map field's + // internal state and existing references that came from map reflection remain + // valid for both reading and writing. + if (field->is_map()) { + const MapFieldBase* map_field = + message_reflection->GetMapData(message, field); + if (map_field->IsMapValid()) { + if (stream->IsSerializationDeterministic()) { + std::vector<MapKey> sorted_key_list = + MapKeySorter::SortKey(message, message_reflection, field); + for (std::vector<MapKey>::iterator it = sorted_key_list.begin(); + it != sorted_key_list.end(); ++it) { + MapValueConstRef map_value; + message_reflection->LookupMapValue(message, field, *it, &map_value); + target = + InternalSerializeMapEntry(field, *it, map_value, target, stream); + } + } else { + for (MapIterator it = message_reflection->MapBegin( + const_cast<Message*>(&message), field); + it != + message_reflection->MapEnd(const_cast<Message*>(&message), field); + ++it) { + target = InternalSerializeMapEntry(field, it.GetKey(), + it.GetValueRef(), target, stream); + } + } + + return target; + } + } + int count = 0; + + if (field->is_repeated()) { + count = message_reflection->FieldSize(message, field); + } else if (field->containing_type()->options().map_entry()) { + // Map entry fields always need to be serialized. + count = 1; + } else if (message_reflection->HasField(message, field)) { + count = 1; + } + + // map_entries is for maps that'll be deterministically serialized. + std::vector<const Message*> map_entries; + if (count > 1 && field->is_map() && stream->IsSerializationDeterministic()) { + map_entries = + DynamicMapSorter::Sort(message, count, message_reflection, field); + } + + if (field->is_packed()) { + if (count == 0) return target; + target = stream->EnsureSpace(target); + switch (field->type()) { +#define HANDLE_PRIMITIVE_TYPE(TYPE, CPPTYPE, TYPE_METHOD, CPPTYPE_METHOD) \ + case FieldDescriptor::TYPE_##TYPE: { \ + auto r = \ + message_reflection->GetRepeatedFieldInternal<CPPTYPE>(message, field); \ + target = stream->Write##TYPE_METHOD##Packed( \ + field->number(), r, FieldDataOnlyByteSize(field, message), target); \ + break; \ + } + + HANDLE_PRIMITIVE_TYPE(INT32, int32_t, Int32, Int32) + HANDLE_PRIMITIVE_TYPE(INT64, int64_t, Int64, Int64) + HANDLE_PRIMITIVE_TYPE(SINT32, int32_t, SInt32, Int32) + HANDLE_PRIMITIVE_TYPE(SINT64, int64_t, SInt64, Int64) + HANDLE_PRIMITIVE_TYPE(UINT32, uint32_t, UInt32, UInt32) + HANDLE_PRIMITIVE_TYPE(UINT64, uint64_t, UInt64, UInt64) + HANDLE_PRIMITIVE_TYPE(ENUM, int, Enum, Enum) + +#undef HANDLE_PRIMITIVE_TYPE +#define HANDLE_PRIMITIVE_TYPE(TYPE, CPPTYPE, TYPE_METHOD, CPPTYPE_METHOD) \ + case FieldDescriptor::TYPE_##TYPE: { \ + auto r = \ + message_reflection->GetRepeatedFieldInternal<CPPTYPE>(message, field); \ + target = stream->WriteFixedPacked(field->number(), r, target); \ + break; \ + } + + HANDLE_PRIMITIVE_TYPE(FIXED32, uint32_t, Fixed32, UInt32) + HANDLE_PRIMITIVE_TYPE(FIXED64, uint64_t, Fixed64, UInt64) + HANDLE_PRIMITIVE_TYPE(SFIXED32, int32_t, SFixed32, Int32) + HANDLE_PRIMITIVE_TYPE(SFIXED64, int64_t, SFixed64, Int64) + + HANDLE_PRIMITIVE_TYPE(FLOAT, float, Float, Float) + HANDLE_PRIMITIVE_TYPE(DOUBLE, double, Double, Double) + + HANDLE_PRIMITIVE_TYPE(BOOL, bool, Bool, Bool) +#undef HANDLE_PRIMITIVE_TYPE + default: + GOOGLE_LOG(FATAL) << "Invalid descriptor"; + } + return target; + } + + auto get_message_from_field = [&message, &map_entries, message_reflection]( + const FieldDescriptor* field, int j) { + if (!field->is_repeated()) { + return &message_reflection->GetMessage(message, field); + } + if (!map_entries.empty()) { + return map_entries[j]; + } + return &message_reflection->GetRepeatedMessage(message, field, j); + }; + for (int j = 0; j < count; j++) { + target = stream->EnsureSpace(target); + switch (field->type()) { +#define HANDLE_PRIMITIVE_TYPE(TYPE, CPPTYPE, TYPE_METHOD, CPPTYPE_METHOD) \ + case FieldDescriptor::TYPE_##TYPE: { \ + const CPPTYPE value = \ + field->is_repeated() \ + ? message_reflection->GetRepeated##CPPTYPE_METHOD(message, field, \ + j) \ + : message_reflection->Get##CPPTYPE_METHOD(message, field); \ + target = WireFormatLite::Write##TYPE_METHOD##ToArray(field->number(), \ + value, target); \ + break; \ + } + + HANDLE_PRIMITIVE_TYPE(INT32, int32_t, Int32, Int32) + HANDLE_PRIMITIVE_TYPE(INT64, int64_t, Int64, Int64) + HANDLE_PRIMITIVE_TYPE(SINT32, int32_t, SInt32, Int32) + HANDLE_PRIMITIVE_TYPE(SINT64, int64_t, SInt64, Int64) + HANDLE_PRIMITIVE_TYPE(UINT32, uint32_t, UInt32, UInt32) + HANDLE_PRIMITIVE_TYPE(UINT64, uint64_t, UInt64, UInt64) + + HANDLE_PRIMITIVE_TYPE(FIXED32, uint32_t, Fixed32, UInt32) + HANDLE_PRIMITIVE_TYPE(FIXED64, uint64_t, Fixed64, UInt64) + HANDLE_PRIMITIVE_TYPE(SFIXED32, int32_t, SFixed32, Int32) + HANDLE_PRIMITIVE_TYPE(SFIXED64, int64_t, SFixed64, Int64) + + HANDLE_PRIMITIVE_TYPE(FLOAT, float, Float, Float) + HANDLE_PRIMITIVE_TYPE(DOUBLE, double, Double, Double) + + HANDLE_PRIMITIVE_TYPE(BOOL, bool, Bool, Bool) +#undef HANDLE_PRIMITIVE_TYPE + + case FieldDescriptor::TYPE_GROUP: { + auto* msg = get_message_from_field(field, j); + target = WireFormatLite::InternalWriteGroup(field->number(), *msg, + target, stream); + } break; + + case FieldDescriptor::TYPE_MESSAGE: { + auto* msg = get_message_from_field(field, j); + target = WireFormatLite::InternalWriteMessage( + field->number(), *msg, msg->GetCachedSize(), target, stream); + } break; + + case FieldDescriptor::TYPE_ENUM: { + const EnumValueDescriptor* value = + field->is_repeated() + ? message_reflection->GetRepeatedEnum(message, field, j) + : message_reflection->GetEnum(message, field); + target = WireFormatLite::WriteEnumToArray(field->number(), + value->number(), target); + break; + } + + // Handle strings separately so that we can get string references + // instead of copying. + case FieldDescriptor::TYPE_STRING: { + bool strict_utf8_check = StrictUtf8Check(field); + std::string scratch; + const std::string& value = + field->is_repeated() + ? message_reflection->GetRepeatedStringReference(message, field, + j, &scratch) + : message_reflection->GetStringReference(message, field, + &scratch); + if (strict_utf8_check) { + WireFormatLite::VerifyUtf8String(value.data(), value.length(), + WireFormatLite::SERIALIZE, + field->full_name().c_str()); + } else { + VerifyUTF8StringNamedField(value.data(), value.length(), SERIALIZE, + field->full_name().c_str()); + } + target = stream->WriteString(field->number(), value, target); + break; + } + + case FieldDescriptor::TYPE_BYTES: { + std::string scratch; + const std::string& value = + field->is_repeated() + ? message_reflection->GetRepeatedStringReference(message, field, + j, &scratch) + : message_reflection->GetStringReference(message, field, + &scratch); + target = stream->WriteString(field->number(), value, target); + break; + } + } + } + return target; +} + +uint8_t* WireFormat::InternalSerializeMessageSetItem( + const FieldDescriptor* field, const Message& message, uint8_t* target, + io::EpsCopyOutputStream* stream) { + const Reflection* message_reflection = message.GetReflection(); + + target = stream->EnsureSpace(target); + // Start group. + target = io::CodedOutputStream::WriteTagToArray( + WireFormatLite::kMessageSetItemStartTag, target); + // Write type ID. + target = WireFormatLite::WriteUInt32ToArray( + WireFormatLite::kMessageSetTypeIdNumber, field->number(), target); + // Write message. + auto& msg = message_reflection->GetMessage(message, field); + target = WireFormatLite::InternalWriteMessage( + WireFormatLite::kMessageSetMessageNumber, msg, msg.GetCachedSize(), + target, stream); + // End group. + target = stream->EnsureSpace(target); + target = io::CodedOutputStream::WriteTagToArray( + WireFormatLite::kMessageSetItemEndTag, target); + return target; +} + +// =================================================================== + +size_t WireFormat::ByteSize(const Message& message) { + const Descriptor* descriptor = message.GetDescriptor(); + const Reflection* message_reflection = message.GetReflection(); + + size_t our_size = 0; + + std::vector<const FieldDescriptor*> fields; + + // Fields of map entry should always be serialized. + if (descriptor->options().map_entry()) { + for (int i = 0; i < descriptor->field_count(); i++) { + fields.push_back(descriptor->field(i)); + } + } else { + message_reflection->ListFields(message, &fields); + } + + for (const FieldDescriptor* field : fields) { + our_size += FieldByteSize(field, message); + } + + if (descriptor->options().message_set_wire_format()) { + our_size += ComputeUnknownMessageSetItemsSize( + message_reflection->GetUnknownFields(message)); + } else { + our_size += + ComputeUnknownFieldsSize(message_reflection->GetUnknownFields(message)); + } + + return our_size; +} + +size_t WireFormat::FieldByteSize(const FieldDescriptor* field, + const Message& message) { + const Reflection* message_reflection = message.GetReflection(); + + if (field->is_extension() && + field->containing_type()->options().message_set_wire_format() && + field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE && + !field->is_repeated()) { + return MessageSetItemByteSize(field, message); + } + + size_t count = 0; + if (field->is_repeated()) { + if (field->is_map()) { + const MapFieldBase* map_field = + message_reflection->GetMapData(message, field); + if (map_field->IsMapValid()) { + count = FromIntSize(map_field->size()); + } else { + count = FromIntSize(message_reflection->FieldSize(message, field)); + } + } else { + count = FromIntSize(message_reflection->FieldSize(message, field)); + } + } else if (field->containing_type()->options().map_entry()) { + // Map entry fields always need to be serialized. + count = 1; + } else if (message_reflection->HasField(message, field)) { + count = 1; + } + + const size_t data_size = FieldDataOnlyByteSize(field, message); + size_t our_size = data_size; + if (field->is_packed()) { + if (data_size > 0) { + // Packed fields get serialized like a string, not their native type. + // Technically this doesn't really matter; the size only changes if it's + // a GROUP + our_size += TagSize(field->number(), FieldDescriptor::TYPE_STRING); + our_size += io::CodedOutputStream::VarintSize32(data_size); + } + } else { + our_size += count * TagSize(field->number(), field->type()); + } + return our_size; +} + +size_t MapKeyDataOnlyByteSize(const FieldDescriptor* field, + const MapKey& value) { + GOOGLE_DCHECK_EQ(FieldDescriptor::TypeToCppType(field->type()), value.type()); + switch (field->type()) { + case FieldDescriptor::TYPE_DOUBLE: + case FieldDescriptor::TYPE_FLOAT: + case FieldDescriptor::TYPE_GROUP: + case FieldDescriptor::TYPE_MESSAGE: + case FieldDescriptor::TYPE_BYTES: + case FieldDescriptor::TYPE_ENUM: + GOOGLE_LOG(FATAL) << "Unsupported"; + return 0; +#define CASE_TYPE(FieldType, CamelFieldType, CamelCppType) \ + case FieldDescriptor::TYPE_##FieldType: \ + return WireFormatLite::CamelFieldType##Size( \ + value.Get##CamelCppType##Value()); + +#define FIXED_CASE_TYPE(FieldType, CamelFieldType) \ + case FieldDescriptor::TYPE_##FieldType: \ + return WireFormatLite::k##CamelFieldType##Size; + + CASE_TYPE(INT32, Int32, Int32); + CASE_TYPE(INT64, Int64, Int64); + CASE_TYPE(UINT32, UInt32, UInt32); + CASE_TYPE(UINT64, UInt64, UInt64); + CASE_TYPE(SINT32, SInt32, Int32); + CASE_TYPE(SINT64, SInt64, Int64); + CASE_TYPE(STRING, String, String); + FIXED_CASE_TYPE(FIXED32, Fixed32); + FIXED_CASE_TYPE(FIXED64, Fixed64); + FIXED_CASE_TYPE(SFIXED32, SFixed32); + FIXED_CASE_TYPE(SFIXED64, SFixed64); + FIXED_CASE_TYPE(BOOL, Bool); + +#undef CASE_TYPE +#undef FIXED_CASE_TYPE + } + GOOGLE_LOG(FATAL) << "Cannot get here"; + return 0; +} + +static size_t MapValueRefDataOnlyByteSize(const FieldDescriptor* field, + const MapValueConstRef& value) { + switch (field->type()) { + case FieldDescriptor::TYPE_GROUP: + GOOGLE_LOG(FATAL) << "Unsupported"; + return 0; +#define CASE_TYPE(FieldType, CamelFieldType, CamelCppType) \ + case FieldDescriptor::TYPE_##FieldType: \ + return WireFormatLite::CamelFieldType##Size( \ + value.Get##CamelCppType##Value()); + +#define FIXED_CASE_TYPE(FieldType, CamelFieldType) \ + case FieldDescriptor::TYPE_##FieldType: \ + return WireFormatLite::k##CamelFieldType##Size; + + CASE_TYPE(INT32, Int32, Int32); + CASE_TYPE(INT64, Int64, Int64); + CASE_TYPE(UINT32, UInt32, UInt32); + CASE_TYPE(UINT64, UInt64, UInt64); + CASE_TYPE(SINT32, SInt32, Int32); + CASE_TYPE(SINT64, SInt64, Int64); + CASE_TYPE(STRING, String, String); + CASE_TYPE(BYTES, Bytes, String); + CASE_TYPE(ENUM, Enum, Enum); + CASE_TYPE(MESSAGE, Message, Message); + FIXED_CASE_TYPE(FIXED32, Fixed32); + FIXED_CASE_TYPE(FIXED64, Fixed64); + FIXED_CASE_TYPE(SFIXED32, SFixed32); + FIXED_CASE_TYPE(SFIXED64, SFixed64); + FIXED_CASE_TYPE(DOUBLE, Double); + FIXED_CASE_TYPE(FLOAT, Float); + FIXED_CASE_TYPE(BOOL, Bool); + +#undef CASE_TYPE +#undef FIXED_CASE_TYPE + } + GOOGLE_LOG(FATAL) << "Cannot get here"; + return 0; +} + +size_t WireFormat::FieldDataOnlyByteSize(const FieldDescriptor* field, + const Message& message) { + const Reflection* message_reflection = message.GetReflection(); + + size_t data_size = 0; + + if (field->is_map()) { + const MapFieldBase* map_field = + message_reflection->GetMapData(message, field); + if (map_field->IsMapValid()) { + MapIterator iter(const_cast<Message*>(&message), field); + MapIterator end(const_cast<Message*>(&message), field); + const FieldDescriptor* key_field = field->message_type()->field(0); + const FieldDescriptor* value_field = field->message_type()->field(1); + for (map_field->MapBegin(&iter), map_field->MapEnd(&end); iter != end; + ++iter) { + size_t size = kMapEntryTagByteSize; + size += MapKeyDataOnlyByteSize(key_field, iter.GetKey()); + size += MapValueRefDataOnlyByteSize(value_field, iter.GetValueRef()); + data_size += WireFormatLite::LengthDelimitedSize(size); + } + return data_size; + } + } + + size_t count = 0; + if (field->is_repeated()) { + count = + internal::FromIntSize(message_reflection->FieldSize(message, field)); + } else if (field->containing_type()->options().map_entry()) { + // Map entry fields always need to be serialized. + count = 1; + } else if (message_reflection->HasField(message, field)) { + count = 1; + } + + switch (field->type()) { +#define HANDLE_TYPE(TYPE, TYPE_METHOD, CPPTYPE_METHOD) \ + case FieldDescriptor::TYPE_##TYPE: \ + if (field->is_repeated()) { \ + for (size_t j = 0; j < count; j++) { \ + data_size += WireFormatLite::TYPE_METHOD##Size( \ + message_reflection->GetRepeated##CPPTYPE_METHOD(message, field, \ + j)); \ + } \ + } else { \ + data_size += WireFormatLite::TYPE_METHOD##Size( \ + message_reflection->Get##CPPTYPE_METHOD(message, field)); \ + } \ + break; + +#define HANDLE_FIXED_TYPE(TYPE, TYPE_METHOD) \ + case FieldDescriptor::TYPE_##TYPE: \ + data_size += count * WireFormatLite::k##TYPE_METHOD##Size; \ + break; + + HANDLE_TYPE(INT32, Int32, Int32) + HANDLE_TYPE(INT64, Int64, Int64) + HANDLE_TYPE(SINT32, SInt32, Int32) + HANDLE_TYPE(SINT64, SInt64, Int64) + HANDLE_TYPE(UINT32, UInt32, UInt32) + HANDLE_TYPE(UINT64, UInt64, UInt64) + + HANDLE_FIXED_TYPE(FIXED32, Fixed32) + HANDLE_FIXED_TYPE(FIXED64, Fixed64) + HANDLE_FIXED_TYPE(SFIXED32, SFixed32) + HANDLE_FIXED_TYPE(SFIXED64, SFixed64) + + HANDLE_FIXED_TYPE(FLOAT, Float) + HANDLE_FIXED_TYPE(DOUBLE, Double) + + HANDLE_FIXED_TYPE(BOOL, Bool) + + HANDLE_TYPE(GROUP, Group, Message) + HANDLE_TYPE(MESSAGE, Message, Message) +#undef HANDLE_TYPE +#undef HANDLE_FIXED_TYPE + + case FieldDescriptor::TYPE_ENUM: { + if (field->is_repeated()) { + for (size_t j = 0; j < count; j++) { + data_size += WireFormatLite::EnumSize( + message_reflection->GetRepeatedEnum(message, field, j)->number()); + } + } else { + data_size += WireFormatLite::EnumSize( + message_reflection->GetEnum(message, field)->number()); + } + break; + } + + // Handle strings separately so that we can get string references + // instead of copying. + case FieldDescriptor::TYPE_STRING: + case FieldDescriptor::TYPE_BYTES: { + for (size_t j = 0; j < count; j++) { + std::string scratch; + const std::string& value = + field->is_repeated() + ? message_reflection->GetRepeatedStringReference(message, field, + j, &scratch) + : message_reflection->GetStringReference(message, field, + &scratch); + data_size += WireFormatLite::StringSize(value); + } + break; + } + } + return data_size; +} + +size_t WireFormat::MessageSetItemByteSize(const FieldDescriptor* field, + const Message& message) { + const Reflection* message_reflection = message.GetReflection(); + + size_t our_size = WireFormatLite::kMessageSetItemTagsSize; + + // type_id + our_size += io::CodedOutputStream::VarintSize32(field->number()); + + // message + const Message& sub_message = message_reflection->GetMessage(message, field); + size_t message_size = sub_message.ByteSizeLong(); + + our_size += io::CodedOutputStream::VarintSize32(message_size); + our_size += message_size; + + return our_size; +} + +// Compute the size of the UnknownFieldSet on the wire. +size_t ComputeUnknownFieldsSize(const InternalMetadata& metadata, + size_t total_size, CachedSize* cached_size) { + total_size += WireFormat::ComputeUnknownFieldsSize( + metadata.unknown_fields<UnknownFieldSet>( + UnknownFieldSet::default_instance)); + cached_size->Set(ToCachedSize(total_size)); + return total_size; +} + +} // namespace internal +} // namespace protobuf +} // namespace google + +#include <google/protobuf/port_undef.inc> diff --git a/toolkit/components/protobuf/src/google/protobuf/wire_format.h b/toolkit/components/protobuf/src/google/protobuf/wire_format.h new file mode 100644 index 0000000000..1acbf9e1f0 --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/wire_format.h @@ -0,0 +1,414 @@ +// 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. + +// Author: kenton@google.com (Kenton Varda) +// atenasio@google.com (Chris Atenasio) (ZigZag transform) +// Based on original Protocol Buffers design by +// Sanjay Ghemawat, Jeff Dean, and others. +// +// This header is logically internal, but is made public because it is used +// from protocol-compiler-generated code, which may reside in other components. + +#ifndef GOOGLE_PROTOBUF_WIRE_FORMAT_H__ +#define GOOGLE_PROTOBUF_WIRE_FORMAT_H__ + + +#include <google/protobuf/stubs/common.h> +#include <google/protobuf/io/coded_stream.h> +#include <google/protobuf/stubs/casts.h> +#include <google/protobuf/descriptor.h> +#include <google/protobuf/generated_message_util.h> +#include <google/protobuf/message.h> +#include <google/protobuf/metadata_lite.h> +#include <google/protobuf/parse_context.h> +#include <google/protobuf/wire_format_lite.h> + +#ifdef SWIG +#error "You cannot SWIG proto headers" +#endif + +// Must be included last. +#include <google/protobuf/port_def.inc> + +namespace google { +namespace protobuf { +class MapKey; // map_field.h +class UnknownFieldSet; // unknown_field_set.h +} // namespace protobuf +} // namespace google + +namespace google { +namespace protobuf { +namespace internal { + +// This class is for internal use by the protocol buffer library and by +// protocol-compiler-generated message classes. It must not be called +// directly by clients. +// +// This class contains code for implementing the binary protocol buffer +// wire format via reflection. The WireFormatLite class implements the +// non-reflection based routines. +// +// This class is really a namespace that contains only static methods +class PROTOBUF_EXPORT WireFormat { + public: + // Given a field return its WireType + static inline WireFormatLite::WireType WireTypeForField( + const FieldDescriptor* field); + + // Given a FieldDescriptor::Type return its WireType + static inline WireFormatLite::WireType WireTypeForFieldType( + FieldDescriptor::Type type); + + // Compute the byte size of a tag. For groups, this includes both the start + // and end tags. + static inline size_t TagSize(int field_number, FieldDescriptor::Type type); + + // These procedures can be used to implement the methods of Message which + // handle parsing and serialization of the protocol buffer wire format + // using only the Reflection interface. When you ask the protocol + // compiler to optimize for code size rather than speed, it will implement + // those methods in terms of these procedures. Of course, these are much + // slower than the specialized implementations which the protocol compiler + // generates when told to optimize for speed. + + // Read a message in protocol buffer wire format. + // + // This procedure reads either to the end of the input stream or through + // a WIRETYPE_END_GROUP tag ending the message, whichever comes first. + // It returns false if the input is invalid. + // + // Required fields are NOT checked by this method. You must call + // IsInitialized() on the resulting message yourself. + static bool ParseAndMergePartial(io::CodedInputStream* input, + Message* message); + + // This is meant for internal protobuf use (WireFormat is an internal class). + // This is the reflective implementation of the _InternalParse functionality. + static const char* _InternalParse(Message* msg, const char* ptr, + internal::ParseContext* ctx); + + // Serialize a message in protocol buffer wire format. + // + // Any embedded messages within the message must have their correct sizes + // cached. However, the top-level message need not; its size is passed as + // a parameter to this procedure. + // + // These return false iff the underlying stream returns a write error. + static void SerializeWithCachedSizes(const Message& message, int size, + io::CodedOutputStream* output) { + int expected_endpoint = output->ByteCount() + size; + output->SetCur( + _InternalSerialize(message, output->Cur(), output->EpsCopy())); + GOOGLE_CHECK_EQ(output->ByteCount(), expected_endpoint) + << ": Protocol message serialized to a size different from what was " + "originally expected. Perhaps it was modified by another thread " + "during serialization?"; + } + static uint8_t* _InternalSerialize(const Message& message, uint8_t* target, + io::EpsCopyOutputStream* stream); + + // Implements Message::ByteSize() via reflection. WARNING: The result + // of this method is *not* cached anywhere. However, all embedded messages + // will have their ByteSize() methods called, so their sizes will be cached. + // Therefore, calling this method is sufficient to allow you to call + // WireFormat::SerializeWithCachedSizes() on the same object. + static size_t ByteSize(const Message& message); + + // ----------------------------------------------------------------- + // Helpers for dealing with unknown fields + + // Skips a field value of the given WireType. The input should start + // positioned immediately after the tag. If unknown_fields is non-nullptr, + // the contents of the field will be added to it. + static bool SkipField(io::CodedInputStream* input, uint32_t tag, + UnknownFieldSet* unknown_fields); + + // Reads and ignores a message from the input. If unknown_fields is + // non-nullptr, the contents will be added to it. + static bool SkipMessage(io::CodedInputStream* input, + UnknownFieldSet* unknown_fields); + + // Read a packed enum field. If the is_valid function is not nullptr, values + // for which is_valid(value) returns false are appended to + // unknown_fields_stream. + static bool ReadPackedEnumPreserveUnknowns(io::CodedInputStream* input, + uint32_t field_number, + bool (*is_valid)(int), + UnknownFieldSet* unknown_fields, + RepeatedField<int>* values); + + // Write the contents of an UnknownFieldSet to the output. + static void SerializeUnknownFields(const UnknownFieldSet& unknown_fields, + io::CodedOutputStream* output) { + output->SetCur(InternalSerializeUnknownFieldsToArray( + unknown_fields, output->Cur(), output->EpsCopy())); + } + // Same as above, except writing directly to the provided buffer. + // Requires that the buffer have sufficient capacity for + // ComputeUnknownFieldsSize(unknown_fields). + // + // Returns a pointer past the last written byte. + static uint8_t* SerializeUnknownFieldsToArray( + const UnknownFieldSet& unknown_fields, uint8_t* target) { + io::EpsCopyOutputStream stream( + target, static_cast<int>(ComputeUnknownFieldsSize(unknown_fields)), + io::CodedOutputStream::IsDefaultSerializationDeterministic()); + return InternalSerializeUnknownFieldsToArray(unknown_fields, target, + &stream); + } + static uint8_t* InternalSerializeUnknownFieldsToArray( + const UnknownFieldSet& unknown_fields, uint8_t* target, + io::EpsCopyOutputStream* stream); + + // Same thing except for messages that have the message_set_wire_format + // option. + static void SerializeUnknownMessageSetItems( + const UnknownFieldSet& unknown_fields, io::CodedOutputStream* output) { + output->SetCur(InternalSerializeUnknownMessageSetItemsToArray( + unknown_fields, output->Cur(), output->EpsCopy())); + } + // Same as above, except writing directly to the provided buffer. + // Requires that the buffer have sufficient capacity for + // ComputeUnknownMessageSetItemsSize(unknown_fields). + // + // Returns a pointer past the last written byte. + static uint8_t* SerializeUnknownMessageSetItemsToArray( + const UnknownFieldSet& unknown_fields, uint8_t* target); + static uint8_t* InternalSerializeUnknownMessageSetItemsToArray( + const UnknownFieldSet& unknown_fields, uint8_t* target, + io::EpsCopyOutputStream* stream); + + // Compute the size of the UnknownFieldSet on the wire. + static size_t ComputeUnknownFieldsSize(const UnknownFieldSet& unknown_fields); + + // Same thing except for messages that have the message_set_wire_format + // option. + static size_t ComputeUnknownMessageSetItemsSize( + const UnknownFieldSet& unknown_fields); + + // Helper functions for encoding and decoding tags. (Inlined below and in + // _inl.h) + // + // This is different from MakeTag(field->number(), field->type()) in the + // case of packed repeated fields. + static uint32_t MakeTag(const FieldDescriptor* field); + + // Parse a single field. The input should start out positioned immediately + // after the tag. + static bool ParseAndMergeField( + uint32_t tag, + const FieldDescriptor* field, // May be nullptr for unknown + Message* message, io::CodedInputStream* input); + + // Serialize a single field. + static void SerializeFieldWithCachedSizes( + const FieldDescriptor* field, // Cannot be nullptr + const Message& message, io::CodedOutputStream* output) { + output->SetCur(InternalSerializeField(field, message, output->Cur(), + output->EpsCopy())); + } + static uint8_t* InternalSerializeField( + const FieldDescriptor* field, // Cannot be nullptr + const Message& message, uint8_t* target, io::EpsCopyOutputStream* stream); + + // Compute size of a single field. If the field is a message type, this + // will call ByteSize() for the embedded message, insuring that it caches + // its size. + static size_t FieldByteSize(const FieldDescriptor* field, // Can't be nullptr + const Message& message); + + // Parse/serialize a MessageSet::Item group. Used with messages that use + // option message_set_wire_format = true. + static bool ParseAndMergeMessageSetItem(io::CodedInputStream* input, + Message* message); + static void SerializeMessageSetItemWithCachedSizes( + const FieldDescriptor* field, const Message& message, + io::CodedOutputStream* output) { + output->SetCur(InternalSerializeMessageSetItem( + field, message, output->Cur(), output->EpsCopy())); + } + static uint8_t* InternalSerializeMessageSetItem( + const FieldDescriptor* field, const Message& message, uint8_t* target, + io::EpsCopyOutputStream* stream); + static size_t MessageSetItemByteSize(const FieldDescriptor* field, + const Message& message); + + // Computes the byte size of a field, excluding tags. For packed fields, it + // only includes the size of the raw data, and not the size of the total + // length, but for other length-delimited types, the size of the length is + // included. + static size_t FieldDataOnlyByteSize( + const FieldDescriptor* field, // Cannot be nullptr + const Message& message); + + enum Operation { + PARSE = 0, + SERIALIZE = 1, + }; + + // Verifies that a string field is valid UTF8, logging an error if not. + // This function will not be called by newly generated protobuf code + // but remains present to support existing code. + static void VerifyUTF8String(const char* data, int size, Operation op); + // The NamedField variant takes a field name in order to produce an + // informative error message if verification fails. + static void VerifyUTF8StringNamedField(const char* data, int size, + Operation op, const char* field_name); + + private: + struct MessageSetParser; + // Skip a MessageSet field. + static bool SkipMessageSetField(io::CodedInputStream* input, + uint32_t field_number, + UnknownFieldSet* unknown_fields); + + // Parse a MessageSet field. + static bool ParseAndMergeMessageSetField(uint32_t field_number, + const FieldDescriptor* field, + Message* message, + io::CodedInputStream* input); + // Parses the value from the wire that belongs to tag. + static const char* _InternalParseAndMergeField(Message* msg, const char* ptr, + internal::ParseContext* ctx, + uint64_t tag, + const Reflection* reflection, + const FieldDescriptor* field); + + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(WireFormat); +}; + +// Subclass of FieldSkipper which saves skipped fields to an UnknownFieldSet. +class PROTOBUF_EXPORT UnknownFieldSetFieldSkipper : public FieldSkipper { + public: + UnknownFieldSetFieldSkipper(UnknownFieldSet* unknown_fields) + : unknown_fields_(unknown_fields) {} + ~UnknownFieldSetFieldSkipper() override {} + + // implements FieldSkipper ----------------------------------------- + bool SkipField(io::CodedInputStream* input, uint32_t tag) override; + bool SkipMessage(io::CodedInputStream* input) override; + void SkipUnknownEnum(int field_number, int value) override; + + protected: + UnknownFieldSet* unknown_fields_; +}; + +// inline methods ==================================================== + +inline WireFormatLite::WireType WireFormat::WireTypeForField( + const FieldDescriptor* field) { + if (field->is_packed()) { + return WireFormatLite::WIRETYPE_LENGTH_DELIMITED; + } else { + return WireTypeForFieldType(field->type()); + } +} + +inline WireFormatLite::WireType WireFormat::WireTypeForFieldType( + FieldDescriptor::Type type) { + // Some compilers don't like enum -> enum casts, so we implicit_cast to + // int first. + return WireFormatLite::WireTypeForFieldType( + static_cast<WireFormatLite::FieldType>(implicit_cast<int>(type))); +} + +inline uint32_t WireFormat::MakeTag(const FieldDescriptor* field) { + return WireFormatLite::MakeTag(field->number(), WireTypeForField(field)); +} + +inline size_t WireFormat::TagSize(int field_number, + FieldDescriptor::Type type) { + // Some compilers don't like enum -> enum casts, so we implicit_cast to + // int first. + return WireFormatLite::TagSize( + field_number, + static_cast<WireFormatLite::FieldType>(implicit_cast<int>(type))); +} + +inline void WireFormat::VerifyUTF8String(const char* data, int size, + WireFormat::Operation op) { +#ifdef GOOGLE_PROTOBUF_UTF8_VALIDATION_ENABLED + WireFormatLite::VerifyUtf8String( + data, size, static_cast<WireFormatLite::Operation>(op), nullptr); +#else + // Avoid the compiler warning about unused variables. + (void)data; + (void)size; + (void)op; +#endif +} + +inline void WireFormat::VerifyUTF8StringNamedField(const char* data, int size, + WireFormat::Operation op, + const char* field_name) { +#ifdef GOOGLE_PROTOBUF_UTF8_VALIDATION_ENABLED + WireFormatLite::VerifyUtf8String( + data, size, static_cast<WireFormatLite::Operation>(op), field_name); +#else + // Avoid the compiler warning about unused variables. + (void)data; + (void)size; + (void)op; + (void)field_name; +#endif +} + + +inline uint8_t* InternalSerializeUnknownMessageSetItemsToArray( + const UnknownFieldSet& unknown_fields, uint8_t* target, + io::EpsCopyOutputStream* stream) { + return WireFormat::InternalSerializeUnknownMessageSetItemsToArray( + unknown_fields, target, stream); +} + +inline size_t ComputeUnknownMessageSetItemsSize( + const UnknownFieldSet& unknown_fields) { + return WireFormat::ComputeUnknownMessageSetItemsSize(unknown_fields); +} + +// Compute the size of the UnknownFieldSet on the wire. +PROTOBUF_EXPORT +size_t ComputeUnknownFieldsSize(const InternalMetadata& metadata, size_t size, + CachedSize* cached_size); + +size_t MapKeyDataOnlyByteSize(const FieldDescriptor* field, + const MapKey& value); + +uint8_t* SerializeMapKeyWithCachedSizes(const FieldDescriptor* field, + const MapKey& value, uint8_t* target, + io::EpsCopyOutputStream* stream); +} // namespace internal +} // namespace protobuf +} // namespace google + +#include <google/protobuf/port_undef.inc> + +#endif // GOOGLE_PROTOBUF_WIRE_FORMAT_H__ diff --git a/toolkit/components/protobuf/src/google/protobuf/wire_format_lite.cc b/toolkit/components/protobuf/src/google/protobuf/wire_format_lite.cc new file mode 100644 index 0000000000..5ab1ca16c6 --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/wire_format_lite.cc @@ -0,0 +1,818 @@ +// 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. + +// Author: kenton@google.com (Kenton Varda) +// Based on original Protocol Buffers design by +// Sanjay Ghemawat, Jeff Dean, and others. + +#include <google/protobuf/wire_format_lite.h> + +#include <limits> +#include <stack> +#include <string> +#include <vector> + +#include <google/protobuf/stubs/logging.h> +#include <google/protobuf/stubs/common.h> +#include <google/protobuf/io/coded_stream.h> +#include <google/protobuf/io/zero_copy_stream.h> +#include <google/protobuf/io/zero_copy_stream_impl_lite.h> +#include <google/protobuf/stubs/stringprintf.h> + + +// Must be included last. +#include <google/protobuf/port_def.inc> + +namespace google { +namespace protobuf { +namespace internal { + +#if !defined(_MSC_VER) || (_MSC_VER >= 1900 && _MSC_VER < 1912) +// Old version of MSVC doesn't like definitions of inline constants, GCC +// requires them. +const int WireFormatLite::kMessageSetItemStartTag; +const int WireFormatLite::kMessageSetItemEndTag; +const int WireFormatLite::kMessageSetTypeIdTag; +const int WireFormatLite::kMessageSetMessageTag; + +#endif + +// IBM xlC requires prefixing constants with WireFormatLite:: +const size_t WireFormatLite::kMessageSetItemTagsSize = + io::CodedOutputStream::StaticVarintSize32< + WireFormatLite::kMessageSetItemStartTag>::value + + io::CodedOutputStream::StaticVarintSize32< + WireFormatLite::kMessageSetItemEndTag>::value + + io::CodedOutputStream::StaticVarintSize32< + WireFormatLite::kMessageSetTypeIdTag>::value + + io::CodedOutputStream::StaticVarintSize32< + WireFormatLite::kMessageSetMessageTag>::value; + +const WireFormatLite::CppType + WireFormatLite::kFieldTypeToCppTypeMap[MAX_FIELD_TYPE + 1] = { + static_cast<CppType>(0), // 0 is reserved for errors + + CPPTYPE_DOUBLE, // TYPE_DOUBLE + CPPTYPE_FLOAT, // TYPE_FLOAT + CPPTYPE_INT64, // TYPE_INT64 + CPPTYPE_UINT64, // TYPE_UINT64 + CPPTYPE_INT32, // TYPE_INT32 + CPPTYPE_UINT64, // TYPE_FIXED64 + CPPTYPE_UINT32, // TYPE_FIXED32 + CPPTYPE_BOOL, // TYPE_BOOL + CPPTYPE_STRING, // TYPE_STRING + CPPTYPE_MESSAGE, // TYPE_GROUP + CPPTYPE_MESSAGE, // TYPE_MESSAGE + CPPTYPE_STRING, // TYPE_BYTES + CPPTYPE_UINT32, // TYPE_UINT32 + CPPTYPE_ENUM, // TYPE_ENUM + CPPTYPE_INT32, // TYPE_SFIXED32 + CPPTYPE_INT64, // TYPE_SFIXED64 + CPPTYPE_INT32, // TYPE_SINT32 + CPPTYPE_INT64, // TYPE_SINT64 +}; + +const WireFormatLite::WireType + WireFormatLite::kWireTypeForFieldType[MAX_FIELD_TYPE + 1] = { + static_cast<WireFormatLite::WireType>(-1), // invalid + WireFormatLite::WIRETYPE_FIXED64, // TYPE_DOUBLE + WireFormatLite::WIRETYPE_FIXED32, // TYPE_FLOAT + WireFormatLite::WIRETYPE_VARINT, // TYPE_INT64 + WireFormatLite::WIRETYPE_VARINT, // TYPE_UINT64 + WireFormatLite::WIRETYPE_VARINT, // TYPE_INT32 + WireFormatLite::WIRETYPE_FIXED64, // TYPE_FIXED64 + WireFormatLite::WIRETYPE_FIXED32, // TYPE_FIXED32 + WireFormatLite::WIRETYPE_VARINT, // TYPE_BOOL + WireFormatLite::WIRETYPE_LENGTH_DELIMITED, // TYPE_STRING + WireFormatLite::WIRETYPE_START_GROUP, // TYPE_GROUP + WireFormatLite::WIRETYPE_LENGTH_DELIMITED, // TYPE_MESSAGE + WireFormatLite::WIRETYPE_LENGTH_DELIMITED, // TYPE_BYTES + WireFormatLite::WIRETYPE_VARINT, // TYPE_UINT32 + WireFormatLite::WIRETYPE_VARINT, // TYPE_ENUM + WireFormatLite::WIRETYPE_FIXED32, // TYPE_SFIXED32 + WireFormatLite::WIRETYPE_FIXED64, // TYPE_SFIXED64 + WireFormatLite::WIRETYPE_VARINT, // TYPE_SINT32 + WireFormatLite::WIRETYPE_VARINT, // TYPE_SINT64 +}; + +bool WireFormatLite::SkipField(io::CodedInputStream* input, uint32_t tag) { + // Field number 0 is illegal. + if (WireFormatLite::GetTagFieldNumber(tag) == 0) return false; + switch (WireFormatLite::GetTagWireType(tag)) { + case WireFormatLite::WIRETYPE_VARINT: { + uint64_t value; + if (!input->ReadVarint64(&value)) return false; + return true; + } + case WireFormatLite::WIRETYPE_FIXED64: { + uint64_t value; + if (!input->ReadLittleEndian64(&value)) return false; + return true; + } + case WireFormatLite::WIRETYPE_LENGTH_DELIMITED: { + uint32_t length; + if (!input->ReadVarint32(&length)) return false; + if (!input->Skip(length)) return false; + return true; + } + case WireFormatLite::WIRETYPE_START_GROUP: { + if (!input->IncrementRecursionDepth()) return false; + if (!SkipMessage(input)) return false; + input->DecrementRecursionDepth(); + // Check that the ending tag matched the starting tag. + if (!input->LastTagWas( + WireFormatLite::MakeTag(WireFormatLite::GetTagFieldNumber(tag), + WireFormatLite::WIRETYPE_END_GROUP))) { + return false; + } + return true; + } + case WireFormatLite::WIRETYPE_END_GROUP: { + return false; + } + case WireFormatLite::WIRETYPE_FIXED32: { + uint32_t value; + if (!input->ReadLittleEndian32(&value)) return false; + return true; + } + default: { + return false; + } + } +} + +bool WireFormatLite::SkipField(io::CodedInputStream* input, uint32_t tag, + io::CodedOutputStream* output) { + // Field number 0 is illegal. + if (WireFormatLite::GetTagFieldNumber(tag) == 0) return false; + switch (WireFormatLite::GetTagWireType(tag)) { + case WireFormatLite::WIRETYPE_VARINT: { + uint64_t value; + if (!input->ReadVarint64(&value)) return false; + output->WriteVarint32(tag); + output->WriteVarint64(value); + return true; + } + case WireFormatLite::WIRETYPE_FIXED64: { + uint64_t value; + if (!input->ReadLittleEndian64(&value)) return false; + output->WriteVarint32(tag); + output->WriteLittleEndian64(value); + return true; + } + case WireFormatLite::WIRETYPE_LENGTH_DELIMITED: { + uint32_t length; + if (!input->ReadVarint32(&length)) return false; + output->WriteVarint32(tag); + output->WriteVarint32(length); + // TODO(mkilavuz): Provide API to prevent extra string copying. + std::string temp; + if (!input->ReadString(&temp, length)) return false; + output->WriteString(temp); + return true; + } + case WireFormatLite::WIRETYPE_START_GROUP: { + output->WriteVarint32(tag); + if (!input->IncrementRecursionDepth()) return false; + if (!SkipMessage(input, output)) return false; + input->DecrementRecursionDepth(); + // Check that the ending tag matched the starting tag. + if (!input->LastTagWas( + WireFormatLite::MakeTag(WireFormatLite::GetTagFieldNumber(tag), + WireFormatLite::WIRETYPE_END_GROUP))) { + return false; + } + return true; + } + case WireFormatLite::WIRETYPE_END_GROUP: { + return false; + } + case WireFormatLite::WIRETYPE_FIXED32: { + uint32_t value; + if (!input->ReadLittleEndian32(&value)) return false; + output->WriteVarint32(tag); + output->WriteLittleEndian32(value); + return true; + } + default: { + return false; + } + } +} + +bool WireFormatLite::SkipMessage(io::CodedInputStream* input) { + while (true) { + uint32_t tag = input->ReadTag(); + if (tag == 0) { + // End of input. This is a valid place to end, so return true. + return true; + } + + WireFormatLite::WireType wire_type = WireFormatLite::GetTagWireType(tag); + + if (wire_type == WireFormatLite::WIRETYPE_END_GROUP) { + // Must be the end of the message. + return true; + } + + if (!SkipField(input, tag)) return false; + } +} + +bool WireFormatLite::SkipMessage(io::CodedInputStream* input, + io::CodedOutputStream* output) { + while (true) { + uint32_t tag = input->ReadTag(); + if (tag == 0) { + // End of input. This is a valid place to end, so return true. + return true; + } + + WireFormatLite::WireType wire_type = WireFormatLite::GetTagWireType(tag); + + if (wire_type == WireFormatLite::WIRETYPE_END_GROUP) { + output->WriteVarint32(tag); + // Must be the end of the message. + return true; + } + + if (!SkipField(input, tag, output)) return false; + } +} + +bool FieldSkipper::SkipField(io::CodedInputStream* input, uint32_t tag) { + return WireFormatLite::SkipField(input, tag); +} + +bool FieldSkipper::SkipMessage(io::CodedInputStream* input) { + return WireFormatLite::SkipMessage(input); +} + +void FieldSkipper::SkipUnknownEnum(int /* field_number */, int /* value */) { + // Nothing. +} + +bool CodedOutputStreamFieldSkipper::SkipField(io::CodedInputStream* input, + uint32_t tag) { + return WireFormatLite::SkipField(input, tag, unknown_fields_); +} + +bool CodedOutputStreamFieldSkipper::SkipMessage(io::CodedInputStream* input) { + return WireFormatLite::SkipMessage(input, unknown_fields_); +} + +void CodedOutputStreamFieldSkipper::SkipUnknownEnum(int field_number, + int value) { + unknown_fields_->WriteVarint32(field_number); + unknown_fields_->WriteVarint64(value); +} + +bool WireFormatLite::ReadPackedEnumPreserveUnknowns( + io::CodedInputStream* input, int field_number, bool (*is_valid)(int), + io::CodedOutputStream* unknown_fields_stream, RepeatedField<int>* values) { + uint32_t length; + if (!input->ReadVarint32(&length)) return false; + io::CodedInputStream::Limit limit = input->PushLimit(length); + while (input->BytesUntilLimit() > 0) { + int value; + if (!ReadPrimitive<int, WireFormatLite::TYPE_ENUM>(input, &value)) { + return false; + } + if (is_valid == nullptr || is_valid(value)) { + values->Add(value); + } else { + uint32_t tag = WireFormatLite::MakeTag(field_number, + WireFormatLite::WIRETYPE_VARINT); + unknown_fields_stream->WriteVarint32(tag); + unknown_fields_stream->WriteVarint32(value); + } + } + input->PopLimit(limit); + return true; +} + +#if !defined(PROTOBUF_LITTLE_ENDIAN) + +namespace { +void EncodeFixedSizeValue(float v, uint8_t* dest) { + WireFormatLite::WriteFloatNoTagToArray(v, dest); +} + +void EncodeFixedSizeValue(double v, uint8_t* dest) { + WireFormatLite::WriteDoubleNoTagToArray(v, dest); +} + +void EncodeFixedSizeValue(uint32_t v, uint8_t* dest) { + WireFormatLite::WriteFixed32NoTagToArray(v, dest); +} + +void EncodeFixedSizeValue(uint64_t v, uint8_t* dest) { + WireFormatLite::WriteFixed64NoTagToArray(v, dest); +} + +void EncodeFixedSizeValue(int32_t v, uint8_t* dest) { + WireFormatLite::WriteSFixed32NoTagToArray(v, dest); +} + +void EncodeFixedSizeValue(int64_t v, uint8_t* dest) { + WireFormatLite::WriteSFixed64NoTagToArray(v, dest); +} + +void EncodeFixedSizeValue(bool v, uint8_t* dest) { + WireFormatLite::WriteBoolNoTagToArray(v, dest); +} +} // anonymous namespace + +#endif // !defined(PROTOBUF_LITTLE_ENDIAN) + +template <typename CType> +static void WriteArray(const CType* a, int n, io::CodedOutputStream* output) { +#if defined(PROTOBUF_LITTLE_ENDIAN) + output->WriteRaw(reinterpret_cast<const char*>(a), n * sizeof(a[0])); +#else + const int kAtATime = 128; + uint8_t buf[sizeof(CType) * kAtATime]; + for (int i = 0; i < n; i += kAtATime) { + int to_do = std::min(kAtATime, n - i); + uint8_t* ptr = buf; + for (int j = 0; j < to_do; j++) { + EncodeFixedSizeValue(a[i + j], ptr); + ptr += sizeof(a[0]); + } + output->WriteRaw(buf, to_do * sizeof(a[0])); + } +#endif +} + +void WireFormatLite::WriteFloatArray(const float* a, int n, + io::CodedOutputStream* output) { + WriteArray<float>(a, n, output); +} + +void WireFormatLite::WriteDoubleArray(const double* a, int n, + io::CodedOutputStream* output) { + WriteArray<double>(a, n, output); +} + +void WireFormatLite::WriteFixed32Array(const uint32_t* a, int n, + io::CodedOutputStream* output) { + WriteArray<uint32_t>(a, n, output); +} + +void WireFormatLite::WriteFixed64Array(const uint64_t* a, int n, + io::CodedOutputStream* output) { + WriteArray<uint64_t>(a, n, output); +} + +void WireFormatLite::WriteSFixed32Array(const int32_t* a, int n, + io::CodedOutputStream* output) { + WriteArray<int32_t>(a, n, output); +} + +void WireFormatLite::WriteSFixed64Array(const int64_t* a, int n, + io::CodedOutputStream* output) { + WriteArray<int64_t>(a, n, output); +} + +void WireFormatLite::WriteBoolArray(const bool* a, int n, + io::CodedOutputStream* output) { + WriteArray<bool>(a, n, output); +} + +void WireFormatLite::WriteInt32(int field_number, int32_t value, + io::CodedOutputStream* output) { + WriteTag(field_number, WIRETYPE_VARINT, output); + WriteInt32NoTag(value, output); +} +void WireFormatLite::WriteInt64(int field_number, int64_t value, + io::CodedOutputStream* output) { + WriteTag(field_number, WIRETYPE_VARINT, output); + WriteInt64NoTag(value, output); +} +void WireFormatLite::WriteUInt32(int field_number, uint32_t value, + io::CodedOutputStream* output) { + WriteTag(field_number, WIRETYPE_VARINT, output); + WriteUInt32NoTag(value, output); +} +void WireFormatLite::WriteUInt64(int field_number, uint64_t value, + io::CodedOutputStream* output) { + WriteTag(field_number, WIRETYPE_VARINT, output); + WriteUInt64NoTag(value, output); +} +void WireFormatLite::WriteSInt32(int field_number, int32_t value, + io::CodedOutputStream* output) { + WriteTag(field_number, WIRETYPE_VARINT, output); + WriteSInt32NoTag(value, output); +} +void WireFormatLite::WriteSInt64(int field_number, int64_t value, + io::CodedOutputStream* output) { + WriteTag(field_number, WIRETYPE_VARINT, output); + WriteSInt64NoTag(value, output); +} +void WireFormatLite::WriteFixed32(int field_number, uint32_t value, + io::CodedOutputStream* output) { + WriteTag(field_number, WIRETYPE_FIXED32, output); + WriteFixed32NoTag(value, output); +} +void WireFormatLite::WriteFixed64(int field_number, uint64_t value, + io::CodedOutputStream* output) { + WriteTag(field_number, WIRETYPE_FIXED64, output); + WriteFixed64NoTag(value, output); +} +void WireFormatLite::WriteSFixed32(int field_number, int32_t value, + io::CodedOutputStream* output) { + WriteTag(field_number, WIRETYPE_FIXED32, output); + WriteSFixed32NoTag(value, output); +} +void WireFormatLite::WriteSFixed64(int field_number, int64_t value, + io::CodedOutputStream* output) { + WriteTag(field_number, WIRETYPE_FIXED64, output); + WriteSFixed64NoTag(value, output); +} +void WireFormatLite::WriteFloat(int field_number, float value, + io::CodedOutputStream* output) { + WriteTag(field_number, WIRETYPE_FIXED32, output); + WriteFloatNoTag(value, output); +} +void WireFormatLite::WriteDouble(int field_number, double value, + io::CodedOutputStream* output) { + WriteTag(field_number, WIRETYPE_FIXED64, output); + WriteDoubleNoTag(value, output); +} +void WireFormatLite::WriteBool(int field_number, bool value, + io::CodedOutputStream* output) { + WriteTag(field_number, WIRETYPE_VARINT, output); + WriteBoolNoTag(value, output); +} +void WireFormatLite::WriteEnum(int field_number, int value, + io::CodedOutputStream* output) { + WriteTag(field_number, WIRETYPE_VARINT, output); + WriteEnumNoTag(value, output); +} + +constexpr size_t kInt32MaxSize = std::numeric_limits<int32_t>::max(); + +void WireFormatLite::WriteString(int field_number, const std::string& value, + io::CodedOutputStream* output) { + // String is for UTF-8 text only + WriteTag(field_number, WIRETYPE_LENGTH_DELIMITED, output); + GOOGLE_CHECK_LE(value.size(), kInt32MaxSize); + output->WriteVarint32(value.size()); + output->WriteString(value); +} +void WireFormatLite::WriteStringMaybeAliased(int field_number, + const std::string& value, + io::CodedOutputStream* output) { + // String is for UTF-8 text only + WriteTag(field_number, WIRETYPE_LENGTH_DELIMITED, output); + GOOGLE_CHECK_LE(value.size(), kInt32MaxSize); + output->WriteVarint32(value.size()); + output->WriteRawMaybeAliased(value.data(), value.size()); +} +void WireFormatLite::WriteBytes(int field_number, const std::string& value, + io::CodedOutputStream* output) { + WriteTag(field_number, WIRETYPE_LENGTH_DELIMITED, output); + GOOGLE_CHECK_LE(value.size(), kInt32MaxSize); + output->WriteVarint32(value.size()); + output->WriteString(value); +} +void WireFormatLite::WriteBytesMaybeAliased(int field_number, + const std::string& value, + io::CodedOutputStream* output) { + WriteTag(field_number, WIRETYPE_LENGTH_DELIMITED, output); + GOOGLE_CHECK_LE(value.size(), kInt32MaxSize); + output->WriteVarint32(value.size()); + output->WriteRawMaybeAliased(value.data(), value.size()); +} + + +void WireFormatLite::WriteGroup(int field_number, const MessageLite& value, + io::CodedOutputStream* output) { + WriteTag(field_number, WIRETYPE_START_GROUP, output); + value.SerializeWithCachedSizes(output); + WriteTag(field_number, WIRETYPE_END_GROUP, output); +} + +void WireFormatLite::WriteMessage(int field_number, const MessageLite& value, + io::CodedOutputStream* output) { + WriteTag(field_number, WIRETYPE_LENGTH_DELIMITED, output); + const int size = value.GetCachedSize(); + output->WriteVarint32(size); + value.SerializeWithCachedSizes(output); +} + +uint8_t* WireFormatLite::InternalWriteGroup(int field_number, + const MessageLite& value, + uint8_t* target, + io::EpsCopyOutputStream* stream) { + target = stream->EnsureSpace(target); + target = WriteTagToArray(field_number, WIRETYPE_START_GROUP, target); + target = value._InternalSerialize(target, stream); + target = stream->EnsureSpace(target); + return WriteTagToArray(field_number, WIRETYPE_END_GROUP, target); +} + +uint8_t* WireFormatLite::InternalWriteMessage(int field_number, + const MessageLite& value, + int cached_size, uint8_t* target, + io::EpsCopyOutputStream* stream) { + target = stream->EnsureSpace(target); + target = WriteTagToArray(field_number, WIRETYPE_LENGTH_DELIMITED, target); + target = io::CodedOutputStream::WriteVarint32ToArray( + static_cast<uint32_t>(cached_size), target); + return value._InternalSerialize(target, stream); +} + +void WireFormatLite::WriteSubMessageMaybeToArray( + int /*size*/, const MessageLite& value, io::CodedOutputStream* output) { + output->SetCur(value._InternalSerialize(output->Cur(), output->EpsCopy())); +} + +void WireFormatLite::WriteGroupMaybeToArray(int field_number, + const MessageLite& value, + io::CodedOutputStream* output) { + WriteTag(field_number, WIRETYPE_START_GROUP, output); + const int size = value.GetCachedSize(); + WriteSubMessageMaybeToArray(size, value, output); + WriteTag(field_number, WIRETYPE_END_GROUP, output); +} + +void WireFormatLite::WriteMessageMaybeToArray(int field_number, + const MessageLite& value, + io::CodedOutputStream* output) { + WriteTag(field_number, WIRETYPE_LENGTH_DELIMITED, output); + const int size = value.GetCachedSize(); + output->WriteVarint32(size); + WriteSubMessageMaybeToArray(size, value, output); +} + +PROTOBUF_NDEBUG_INLINE static bool ReadBytesToString( + io::CodedInputStream* input, std::string* value); +inline static bool ReadBytesToString(io::CodedInputStream* input, + std::string* value) { + uint32_t length; + return input->ReadVarint32(&length) && input->ReadString(value, length); +} + +bool WireFormatLite::ReadBytes(io::CodedInputStream* input, + std::string* value) { + return ReadBytesToString(input, value); +} + +bool WireFormatLite::ReadBytes(io::CodedInputStream* input, std::string** p) { + if (*p == &GetEmptyStringAlreadyInited()) { + *p = new std::string(); + } + return ReadBytesToString(input, *p); +} + +void PrintUTF8ErrorLog(StringPiece message_name, + StringPiece field_name, const char* operation_str, + bool emit_stacktrace) { + std::string stacktrace; + (void)emit_stacktrace; // Parameter is used by Google-internal code. + std::string quoted_field_name = ""; + if (!field_name.empty()) { + if (!message_name.empty()) { + quoted_field_name = + StrCat(" '", message_name, ".", field_name, "'"); + } else { + quoted_field_name = StrCat(" '", field_name, "'"); + } + } + std::string error_message = + StrCat("String field", quoted_field_name, + " contains invalid UTF-8 data " + "when ", + operation_str, + " a protocol buffer. Use the 'bytes' type if you intend to " + "send raw bytes. ", + stacktrace); + GOOGLE_LOG(ERROR) << error_message; +} + +bool WireFormatLite::VerifyUtf8String(const char* data, int size, Operation op, + const char* field_name) { + if (!IsStructurallyValidUTF8(data, size)) { + const char* operation_str = nullptr; + switch (op) { + case PARSE: + operation_str = "parsing"; + break; + case SERIALIZE: + operation_str = "serializing"; + break; + // no default case: have the compiler warn if a case is not covered. + } + PrintUTF8ErrorLog("", field_name, operation_str, false); + return false; + } + return true; +} + +// this code is deliberately written such that clang makes it into really +// efficient SSE code. +template <bool ZigZag, bool SignExtended, typename T> +static size_t VarintSize(const T* data, const int n) { + static_assert(sizeof(T) == 4, "This routine only works for 32 bit integers"); + // is_unsigned<T> => !ZigZag + static_assert( + (std::is_unsigned<T>::value ^ ZigZag) || std::is_signed<T>::value, + "Cannot ZigZag encode unsigned types"); + // is_unsigned<T> => !SignExtended + static_assert( + (std::is_unsigned<T>::value ^ SignExtended) || std::is_signed<T>::value, + "Cannot SignExtended unsigned types"); + static_assert(!(SignExtended && ZigZag), + "Cannot SignExtended and ZigZag on the same type"); + uint32_t sum = n; + uint32_t msb_sum = 0; + for (int i = 0; i < n; i++) { + uint32_t x = data[i]; + if (ZigZag) { + x = WireFormatLite::ZigZagEncode32(x); + } else if (SignExtended) { + msb_sum += x >> 31; + } + // clang is so smart that it produces optimal SSE sequence unrolling + // the loop 8 ints at a time. With a sequence of 4 + // cmpres = cmpgt x, sizeclass ( -1 or 0) + // sum = sum - cmpres + if (x > 0x7F) sum++; + if (x > 0x3FFF) sum++; + if (x > 0x1FFFFF) sum++; + if (x > 0xFFFFFFF) sum++; + } + if (SignExtended) sum += msb_sum * 5; + return sum; +} + +template <bool ZigZag, typename T> +static size_t VarintSize64(const T* data, const int n) { + static_assert(sizeof(T) == 8, "This routine only works for 64 bit integers"); + // is_unsigned<T> => !ZigZag + static_assert(!ZigZag || !std::is_unsigned<T>::value, + "Cannot ZigZag encode unsigned types"); + uint64_t sum = n; + for (int i = 0; i < n; i++) { + uint64_t x = data[i]; + if (ZigZag) { + x = WireFormatLite::ZigZagEncode64(x); + } + // First step is a binary search, we can't branch in sse so we use the + // result of the compare to adjust sum and appropriately. This code is + // written to make clang recognize the vectorization. + uint64_t tmp = x >= (static_cast<uint64_t>(1) << 35) ? -1 : 0; + sum += 5 & tmp; + x >>= 35 & tmp; + if (x > 0x7F) sum++; + if (x > 0x3FFF) sum++; + if (x > 0x1FFFFF) sum++; + if (x > 0xFFFFFFF) sum++; + } + return sum; +} + +// GCC does not recognize the vectorization opportunity +// and other platforms are untested, in those cases using the optimized +// varint size routine for each element is faster. +// Hence we enable it only for clang +#if defined(__SSE__) && defined(__clang__) +size_t WireFormatLite::Int32Size(const RepeatedField<int32_t>& value) { + return VarintSize<false, true>(value.data(), value.size()); +} + +size_t WireFormatLite::UInt32Size(const RepeatedField<uint32_t>& value) { + return VarintSize<false, false>(value.data(), value.size()); +} + +size_t WireFormatLite::SInt32Size(const RepeatedField<int32_t>& value) { + return VarintSize<true, false>(value.data(), value.size()); +} + +size_t WireFormatLite::EnumSize(const RepeatedField<int>& value) { + // On ILP64, sizeof(int) == 8, which would require a different template. + return VarintSize<false, true>(value.data(), value.size()); +} + +#else // !(defined(__SSE4_1__) && defined(__clang__)) + +size_t WireFormatLite::Int32Size(const RepeatedField<int32_t>& value) { + size_t out = 0; + const int n = value.size(); + for (int i = 0; i < n; i++) { + out += Int32Size(value.Get(i)); + } + return out; +} + +size_t WireFormatLite::UInt32Size(const RepeatedField<uint32_t>& value) { + size_t out = 0; + const int n = value.size(); + for (int i = 0; i < n; i++) { + out += UInt32Size(value.Get(i)); + } + return out; +} + +size_t WireFormatLite::SInt32Size(const RepeatedField<int32_t>& value) { + size_t out = 0; + const int n = value.size(); + for (int i = 0; i < n; i++) { + out += SInt32Size(value.Get(i)); + } + return out; +} + +size_t WireFormatLite::EnumSize(const RepeatedField<int>& value) { + size_t out = 0; + const int n = value.size(); + for (int i = 0; i < n; i++) { + out += EnumSize(value.Get(i)); + } + return out; +} + +#endif + +// Micro benchmarks show that the SSE improved loop only starts beating +// the normal loop on Haswell platforms and then only for >32 ints. We +// disable this for now. Some specialized users might find it worthwhile to +// enable this. +#define USE_SSE_FOR_64_BIT_INTEGER_ARRAYS 0 +#if USE_SSE_FOR_64_BIT_INTEGER_ARRAYS +size_t WireFormatLite::Int64Size(const RepeatedField<int64_t>& value) { + return VarintSize64<false>(value.data(), value.size()); +} + +size_t WireFormatLite::UInt64Size(const RepeatedField<uint64_t>& value) { + return VarintSize64<false>(value.data(), value.size()); +} + +size_t WireFormatLite::SInt64Size(const RepeatedField<int64_t>& value) { + return VarintSize64<true>(value.data(), value.size()); +} + +#else + +size_t WireFormatLite::Int64Size(const RepeatedField<int64_t>& value) { + size_t out = 0; + const int n = value.size(); + for (int i = 0; i < n; i++) { + out += Int64Size(value.Get(i)); + } + return out; +} + +size_t WireFormatLite::UInt64Size(const RepeatedField<uint64_t>& value) { + size_t out = 0; + const int n = value.size(); + for (int i = 0; i < n; i++) { + out += UInt64Size(value.Get(i)); + } + return out; +} + +size_t WireFormatLite::SInt64Size(const RepeatedField<int64_t>& value) { + size_t out = 0; + const int n = value.size(); + for (int i = 0; i < n; i++) { + out += SInt64Size(value.Get(i)); + } + return out; +} + +#endif + +} // namespace internal +} // namespace protobuf +} // namespace google + +#include <google/protobuf/port_undef.inc> diff --git a/toolkit/components/protobuf/src/google/protobuf/wire_format_lite.h b/toolkit/components/protobuf/src/google/protobuf/wire_format_lite.h new file mode 100644 index 0000000000..80d396156f --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/wire_format_lite.h @@ -0,0 +1,1908 @@ +// 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. + +// Author: kenton@google.com (Kenton Varda) +// atenasio@google.com (Chris Atenasio) (ZigZag transform) +// wink@google.com (Wink Saville) (refactored from wire_format.h) +// Based on original Protocol Buffers design by +// Sanjay Ghemawat, Jeff Dean, and others. +// +// This header is logically internal, but is made public because it is used +// from protocol-compiler-generated code, which may reside in other components. + +#ifndef GOOGLE_PROTOBUF_WIRE_FORMAT_LITE_H__ +#define GOOGLE_PROTOBUF_WIRE_FORMAT_LITE_H__ + + +#include <limits> +#include <string> + +#include <google/protobuf/stubs/common.h> +#include <google/protobuf/stubs/logging.h> +#include <google/protobuf/io/coded_stream.h> +#include <google/protobuf/port.h> +#include <google/protobuf/stubs/casts.h> +#include <google/protobuf/arenastring.h> +#include <google/protobuf/message_lite.h> +#include <google/protobuf/repeated_field.h> + +// Do UTF-8 validation on string type in Debug build only +#ifndef NDEBUG +#define GOOGLE_PROTOBUF_UTF8_VALIDATION_ENABLED +#endif + +// Avoid conflict with iOS where <ConditionalMacros.h> #defines TYPE_BOOL. +// +// If some one needs the macro TYPE_BOOL in a file that includes this header, +// it's possible to bring it back using push/pop_macro as follows. +// +// #pragma push_macro("TYPE_BOOL") +// #include this header and/or all headers that need the macro to be undefined. +// #pragma pop_macro("TYPE_BOOL") +#undef TYPE_BOOL + + +// Must be included last. +#include <google/protobuf/port_def.inc> + +namespace google { +namespace protobuf { +namespace internal { + +// This class is for internal use by the protocol buffer library and by +// protocol-compiler-generated message classes. It must not be called +// directly by clients. +// +// This class contains helpers for implementing the binary protocol buffer +// wire format without the need for reflection. Use WireFormat when using +// reflection. +// +// This class is really a namespace that contains only static methods. +class PROTOBUF_EXPORT WireFormatLite { + public: + // ----------------------------------------------------------------- + // Helper constants and functions related to the format. These are + // mostly meant for internal and generated code to use. + + // The wire format is composed of a sequence of tag/value pairs, each + // of which contains the value of one field (or one element of a repeated + // field). Each tag is encoded as a varint. The lower bits of the tag + // identify its wire type, which specifies the format of the data to follow. + // The rest of the bits contain the field number. Each type of field (as + // declared by FieldDescriptor::Type, in descriptor.h) maps to one of + // these wire types. Immediately following each tag is the field's value, + // encoded in the format specified by the wire type. Because the tag + // identifies the encoding of this data, it is possible to skip + // unrecognized fields for forwards compatibility. + + enum WireType { + WIRETYPE_VARINT = 0, + WIRETYPE_FIXED64 = 1, + WIRETYPE_LENGTH_DELIMITED = 2, + WIRETYPE_START_GROUP = 3, + WIRETYPE_END_GROUP = 4, + WIRETYPE_FIXED32 = 5, + }; + + // Lite alternative to FieldDescriptor::Type. Must be kept in sync. + enum FieldType { + TYPE_DOUBLE = 1, + TYPE_FLOAT = 2, + TYPE_INT64 = 3, + TYPE_UINT64 = 4, + TYPE_INT32 = 5, + TYPE_FIXED64 = 6, + TYPE_FIXED32 = 7, + TYPE_BOOL = 8, + TYPE_STRING = 9, + TYPE_GROUP = 10, + TYPE_MESSAGE = 11, + TYPE_BYTES = 12, + TYPE_UINT32 = 13, + TYPE_ENUM = 14, + TYPE_SFIXED32 = 15, + TYPE_SFIXED64 = 16, + TYPE_SINT32 = 17, + TYPE_SINT64 = 18, + MAX_FIELD_TYPE = 18, + }; + + // Lite alternative to FieldDescriptor::CppType. Must be kept in sync. + enum CppType { + CPPTYPE_INT32 = 1, + CPPTYPE_INT64 = 2, + CPPTYPE_UINT32 = 3, + CPPTYPE_UINT64 = 4, + CPPTYPE_DOUBLE = 5, + CPPTYPE_FLOAT = 6, + CPPTYPE_BOOL = 7, + CPPTYPE_ENUM = 8, + CPPTYPE_STRING = 9, + CPPTYPE_MESSAGE = 10, + MAX_CPPTYPE = 10, + }; + + // Helper method to get the CppType for a particular Type. + static CppType FieldTypeToCppType(FieldType type); + + // Given a FieldDescriptor::Type return its WireType + static inline WireFormatLite::WireType WireTypeForFieldType( + WireFormatLite::FieldType type) { + return kWireTypeForFieldType[type]; + } + + // Number of bits in a tag which identify the wire type. + static constexpr int kTagTypeBits = 3; + // Mask for those bits. + static constexpr uint32_t kTagTypeMask = (1 << kTagTypeBits) - 1; + + // Helper functions for encoding and decoding tags. (Inlined below and in + // _inl.h) + // + // This is different from MakeTag(field->number(), field->type()) in the + // case of packed repeated fields. + constexpr static uint32_t MakeTag(int field_number, WireType type); + static WireType GetTagWireType(uint32_t tag); + static int GetTagFieldNumber(uint32_t tag); + + // Compute the byte size of a tag. For groups, this includes both the start + // and end tags. + static inline size_t TagSize(int field_number, + WireFormatLite::FieldType type); + + // Skips a field value with the given tag. The input should start + // positioned immediately after the tag. Skipped values are simply + // discarded, not recorded anywhere. See WireFormat::SkipField() for a + // version that records to an UnknownFieldSet. + static bool SkipField(io::CodedInputStream* input, uint32_t tag); + + // Skips a field value with the given tag. The input should start + // positioned immediately after the tag. Skipped values are recorded to a + // CodedOutputStream. + static bool SkipField(io::CodedInputStream* input, uint32_t tag, + io::CodedOutputStream* output); + + // Reads and ignores a message from the input. Skipped values are simply + // discarded, not recorded anywhere. See WireFormat::SkipMessage() for a + // version that records to an UnknownFieldSet. + static bool SkipMessage(io::CodedInputStream* input); + + // Reads and ignores a message from the input. Skipped values are recorded + // to a CodedOutputStream. + static bool SkipMessage(io::CodedInputStream* input, + io::CodedOutputStream* output); + + // This macro does the same thing as WireFormatLite::MakeTag(), but the + // result is usable as a compile-time constant, which makes it usable + // as a switch case or a template input. WireFormatLite::MakeTag() is more + // type-safe, though, so prefer it if possible. +#define GOOGLE_PROTOBUF_WIRE_FORMAT_MAKE_TAG(FIELD_NUMBER, TYPE) \ + static_cast<uint32_t>((static_cast<uint32_t>(FIELD_NUMBER) << 3) | (TYPE)) + + // These are the tags for the old MessageSet format, which was defined as: + // message MessageSet { + // repeated group Item = 1 { + // required int32 type_id = 2; + // required string message = 3; + // } + // } + static constexpr int kMessageSetItemNumber = 1; + static constexpr int kMessageSetTypeIdNumber = 2; + static constexpr int kMessageSetMessageNumber = 3; + static const int kMessageSetItemStartTag = GOOGLE_PROTOBUF_WIRE_FORMAT_MAKE_TAG( + kMessageSetItemNumber, WireFormatLite::WIRETYPE_START_GROUP); + static const int kMessageSetItemEndTag = GOOGLE_PROTOBUF_WIRE_FORMAT_MAKE_TAG( + kMessageSetItemNumber, WireFormatLite::WIRETYPE_END_GROUP); + static const int kMessageSetTypeIdTag = GOOGLE_PROTOBUF_WIRE_FORMAT_MAKE_TAG( + kMessageSetTypeIdNumber, WireFormatLite::WIRETYPE_VARINT); + static const int kMessageSetMessageTag = GOOGLE_PROTOBUF_WIRE_FORMAT_MAKE_TAG( + kMessageSetMessageNumber, WireFormatLite::WIRETYPE_LENGTH_DELIMITED); + + // Byte size of all tags of a MessageSet::Item combined. + static const size_t kMessageSetItemTagsSize; + + // Helper functions for converting between floats/doubles and IEEE-754 + // uint32s/uint64s so that they can be written. (Assumes your platform + // uses IEEE-754 floats.) + static uint32_t EncodeFloat(float value); + static float DecodeFloat(uint32_t value); + static uint64_t EncodeDouble(double value); + static double DecodeDouble(uint64_t value); + + // Helper functions for mapping signed integers to unsigned integers in + // such a way that numbers with small magnitudes will encode to smaller + // varints. If you simply static_cast a negative number to an unsigned + // number and varint-encode it, it will always take 10 bytes, defeating + // the purpose of varint. So, for the "sint32" and "sint64" field types, + // we ZigZag-encode the values. + static uint32_t ZigZagEncode32(int32_t n); + static int32_t ZigZagDecode32(uint32_t n); + static uint64_t ZigZagEncode64(int64_t n); + static int64_t ZigZagDecode64(uint64_t n); + + // ================================================================= + // Methods for reading/writing individual field. + + // Read fields, not including tags. The assumption is that you already + // read the tag to determine what field to read. + + // For primitive fields, we just use a templatized routine parameterized by + // the represented type and the FieldType. These are specialized with the + // appropriate definition for each declared type. + template <typename CType, enum FieldType DeclaredType> + PROTOBUF_NDEBUG_INLINE static bool ReadPrimitive(io::CodedInputStream* input, + CType* value); + + // Reads repeated primitive values, with optimizations for repeats. + // tag_size and tag should both be compile-time constants provided by the + // protocol compiler. + template <typename CType, enum FieldType DeclaredType> + PROTOBUF_NDEBUG_INLINE static bool ReadRepeatedPrimitive( + int tag_size, uint32_t tag, io::CodedInputStream* input, + RepeatedField<CType>* value); + + // Identical to ReadRepeatedPrimitive, except will not inline the + // implementation. + template <typename CType, enum FieldType DeclaredType> + static bool ReadRepeatedPrimitiveNoInline(int tag_size, uint32_t tag, + io::CodedInputStream* input, + RepeatedField<CType>* value); + + // Reads a primitive value directly from the provided buffer. It returns a + // pointer past the segment of data that was read. + // + // This is only implemented for the types with fixed wire size, e.g. + // float, double, and the (s)fixed* types. + template <typename CType, enum FieldType DeclaredType> + PROTOBUF_NDEBUG_INLINE static const uint8_t* ReadPrimitiveFromArray( + const uint8_t* buffer, CType* value); + + // Reads a primitive packed field. + // + // This is only implemented for packable types. + template <typename CType, enum FieldType DeclaredType> + PROTOBUF_NDEBUG_INLINE static bool ReadPackedPrimitive( + io::CodedInputStream* input, RepeatedField<CType>* value); + + // Identical to ReadPackedPrimitive, except will not inline the + // implementation. + template <typename CType, enum FieldType DeclaredType> + static bool ReadPackedPrimitiveNoInline(io::CodedInputStream* input, + RepeatedField<CType>* value); + + // Read a packed enum field. If the is_valid function is not nullptr, values + // for which is_valid(value) returns false are silently dropped. + static bool ReadPackedEnumNoInline(io::CodedInputStream* input, + bool (*is_valid)(int), + RepeatedField<int>* values); + + // Read a packed enum field. If the is_valid function is not nullptr, values + // for which is_valid(value) returns false are appended to + // unknown_fields_stream. + static bool ReadPackedEnumPreserveUnknowns( + io::CodedInputStream* input, int field_number, bool (*is_valid)(int), + io::CodedOutputStream* unknown_fields_stream, RepeatedField<int>* values); + + // Read a string. ReadString(..., std::string* value) requires an + // existing std::string. + static inline bool ReadString(io::CodedInputStream* input, + std::string* value); + // ReadString(..., std::string** p) is internal-only, and should only be + // called from generated code. It starts by setting *p to "new std::string" if + // *p == &GetEmptyStringAlreadyInited(). It then invokes + // ReadString(io::CodedInputStream* input, *p). This is useful for reducing + // code size. + static inline bool ReadString(io::CodedInputStream* input, std::string** p); + // Analogous to ReadString(). + static bool ReadBytes(io::CodedInputStream* input, std::string* value); + static bool ReadBytes(io::CodedInputStream* input, std::string** p); + + enum Operation { + PARSE = 0, + SERIALIZE = 1, + }; + + // Returns true if the data is valid UTF-8. + static bool VerifyUtf8String(const char* data, int size, Operation op, + const char* field_name); + + template <typename MessageType> + static inline bool ReadGroup(int field_number, io::CodedInputStream* input, + MessageType* value); + + template <typename MessageType> + static inline bool ReadMessage(io::CodedInputStream* input, + MessageType* value); + + template <typename MessageType> + static inline bool ReadMessageNoVirtual(io::CodedInputStream* input, + MessageType* value) { + return ReadMessage(input, value); + } + + // Write a tag. The Write*() functions typically include the tag, so + // normally there's no need to call this unless using the Write*NoTag() + // variants. + PROTOBUF_NDEBUG_INLINE static void WriteTag(int field_number, WireType type, + io::CodedOutputStream* output); + + // Write fields, without tags. + PROTOBUF_NDEBUG_INLINE static void WriteInt32NoTag( + int32_t value, io::CodedOutputStream* output); + PROTOBUF_NDEBUG_INLINE static void WriteInt64NoTag( + int64_t value, io::CodedOutputStream* output); + PROTOBUF_NDEBUG_INLINE static void WriteUInt32NoTag( + uint32_t value, io::CodedOutputStream* output); + PROTOBUF_NDEBUG_INLINE static void WriteUInt64NoTag( + uint64_t value, io::CodedOutputStream* output); + PROTOBUF_NDEBUG_INLINE static void WriteSInt32NoTag( + int32_t value, io::CodedOutputStream* output); + PROTOBUF_NDEBUG_INLINE static void WriteSInt64NoTag( + int64_t value, io::CodedOutputStream* output); + PROTOBUF_NDEBUG_INLINE static void WriteFixed32NoTag( + uint32_t value, io::CodedOutputStream* output); + PROTOBUF_NDEBUG_INLINE static void WriteFixed64NoTag( + uint64_t value, io::CodedOutputStream* output); + PROTOBUF_NDEBUG_INLINE static void WriteSFixed32NoTag( + int32_t value, io::CodedOutputStream* output); + PROTOBUF_NDEBUG_INLINE static void WriteSFixed64NoTag( + int64_t value, io::CodedOutputStream* output); + PROTOBUF_NDEBUG_INLINE static void WriteFloatNoTag( + float value, io::CodedOutputStream* output); + PROTOBUF_NDEBUG_INLINE static void WriteDoubleNoTag( + double value, io::CodedOutputStream* output); + PROTOBUF_NDEBUG_INLINE static void WriteBoolNoTag( + bool value, io::CodedOutputStream* output); + PROTOBUF_NDEBUG_INLINE static void WriteEnumNoTag( + int value, io::CodedOutputStream* output); + + // Write array of primitive fields, without tags + static void WriteFloatArray(const float* a, int n, + io::CodedOutputStream* output); + static void WriteDoubleArray(const double* a, int n, + io::CodedOutputStream* output); + static void WriteFixed32Array(const uint32_t* a, int n, + io::CodedOutputStream* output); + static void WriteFixed64Array(const uint64_t* a, int n, + io::CodedOutputStream* output); + static void WriteSFixed32Array(const int32_t* a, int n, + io::CodedOutputStream* output); + static void WriteSFixed64Array(const int64_t* a, int n, + io::CodedOutputStream* output); + static void WriteBoolArray(const bool* a, int n, + io::CodedOutputStream* output); + + // Write fields, including tags. + static void WriteInt32(int field_number, int32_t value, + io::CodedOutputStream* output); + static void WriteInt64(int field_number, int64_t value, + io::CodedOutputStream* output); + static void WriteUInt32(int field_number, uint32_t value, + io::CodedOutputStream* output); + static void WriteUInt64(int field_number, uint64_t value, + io::CodedOutputStream* output); + static void WriteSInt32(int field_number, int32_t value, + io::CodedOutputStream* output); + static void WriteSInt64(int field_number, int64_t value, + io::CodedOutputStream* output); + static void WriteFixed32(int field_number, uint32_t value, + io::CodedOutputStream* output); + static void WriteFixed64(int field_number, uint64_t value, + io::CodedOutputStream* output); + static void WriteSFixed32(int field_number, int32_t value, + io::CodedOutputStream* output); + static void WriteSFixed64(int field_number, int64_t value, + io::CodedOutputStream* output); + static void WriteFloat(int field_number, float value, + io::CodedOutputStream* output); + static void WriteDouble(int field_number, double value, + io::CodedOutputStream* output); + static void WriteBool(int field_number, bool value, + io::CodedOutputStream* output); + static void WriteEnum(int field_number, int value, + io::CodedOutputStream* output); + + static void WriteString(int field_number, const std::string& value, + io::CodedOutputStream* output); + static void WriteBytes(int field_number, const std::string& value, + io::CodedOutputStream* output); + static void WriteStringMaybeAliased(int field_number, + const std::string& value, + io::CodedOutputStream* output); + static void WriteBytesMaybeAliased(int field_number, const std::string& value, + io::CodedOutputStream* output); + + static void WriteGroup(int field_number, const MessageLite& value, + io::CodedOutputStream* output); + static void WriteMessage(int field_number, const MessageLite& value, + io::CodedOutputStream* output); + // Like above, but these will check if the output stream has enough + // space to write directly to a flat array. + static void WriteGroupMaybeToArray(int field_number, const MessageLite& value, + io::CodedOutputStream* output); + static void WriteMessageMaybeToArray(int field_number, + const MessageLite& value, + io::CodedOutputStream* output); + + // Like above, but de-virtualize the call to SerializeWithCachedSizes(). The + // pointer must point at an instance of MessageType, *not* a subclass (or + // the subclass must not override SerializeWithCachedSizes()). + template <typename MessageType> + static inline void WriteGroupNoVirtual(int field_number, + const MessageType& value, + io::CodedOutputStream* output); + template <typename MessageType> + static inline void WriteMessageNoVirtual(int field_number, + const MessageType& value, + io::CodedOutputStream* output); + + // Like above, but use only *ToArray methods of CodedOutputStream. + PROTOBUF_NDEBUG_INLINE static uint8_t* WriteTagToArray(int field_number, + WireType type, + uint8_t* target); + + // Write fields, without tags. + PROTOBUF_NDEBUG_INLINE static uint8_t* WriteInt32NoTagToArray( + int32_t value, uint8_t* target); + PROTOBUF_NDEBUG_INLINE static uint8_t* WriteInt64NoTagToArray( + int64_t value, uint8_t* target); + PROTOBUF_NDEBUG_INLINE static uint8_t* WriteUInt32NoTagToArray( + uint32_t value, uint8_t* target); + PROTOBUF_NDEBUG_INLINE static uint8_t* WriteUInt64NoTagToArray( + uint64_t value, uint8_t* target); + PROTOBUF_NDEBUG_INLINE static uint8_t* WriteSInt32NoTagToArray( + int32_t value, uint8_t* target); + PROTOBUF_NDEBUG_INLINE static uint8_t* WriteSInt64NoTagToArray( + int64_t value, uint8_t* target); + PROTOBUF_NDEBUG_INLINE static uint8_t* WriteFixed32NoTagToArray( + uint32_t value, uint8_t* target); + PROTOBUF_NDEBUG_INLINE static uint8_t* WriteFixed64NoTagToArray( + uint64_t value, uint8_t* target); + PROTOBUF_NDEBUG_INLINE static uint8_t* WriteSFixed32NoTagToArray( + int32_t value, uint8_t* target); + PROTOBUF_NDEBUG_INLINE static uint8_t* WriteSFixed64NoTagToArray( + int64_t value, uint8_t* target); + PROTOBUF_NDEBUG_INLINE static uint8_t* WriteFloatNoTagToArray( + float value, uint8_t* target); + PROTOBUF_NDEBUG_INLINE static uint8_t* WriteDoubleNoTagToArray( + double value, uint8_t* target); + PROTOBUF_NDEBUG_INLINE static uint8_t* WriteBoolNoTagToArray(bool value, + uint8_t* target); + PROTOBUF_NDEBUG_INLINE static uint8_t* WriteEnumNoTagToArray(int value, + uint8_t* target); + + // Write fields, without tags. These require that value.size() > 0. + template <typename T> + PROTOBUF_NDEBUG_INLINE static uint8_t* WritePrimitiveNoTagToArray( + const RepeatedField<T>& value, uint8_t* (*Writer)(T, uint8_t*), + uint8_t* target); + template <typename T> + PROTOBUF_NDEBUG_INLINE static uint8_t* WriteFixedNoTagToArray( + const RepeatedField<T>& value, uint8_t* (*Writer)(T, uint8_t*), + uint8_t* target); + + PROTOBUF_NDEBUG_INLINE static uint8_t* WriteInt32NoTagToArray( + const RepeatedField<int32_t>& value, uint8_t* output); + PROTOBUF_NDEBUG_INLINE static uint8_t* WriteInt64NoTagToArray( + const RepeatedField<int64_t>& value, uint8_t* output); + PROTOBUF_NDEBUG_INLINE static uint8_t* WriteUInt32NoTagToArray( + const RepeatedField<uint32_t>& value, uint8_t* output); + PROTOBUF_NDEBUG_INLINE static uint8_t* WriteUInt64NoTagToArray( + const RepeatedField<uint64_t>& value, uint8_t* output); + PROTOBUF_NDEBUG_INLINE static uint8_t* WriteSInt32NoTagToArray( + const RepeatedField<int32_t>& value, uint8_t* output); + PROTOBUF_NDEBUG_INLINE static uint8_t* WriteSInt64NoTagToArray( + const RepeatedField<int64_t>& value, uint8_t* output); + PROTOBUF_NDEBUG_INLINE static uint8_t* WriteFixed32NoTagToArray( + const RepeatedField<uint32_t>& value, uint8_t* output); + PROTOBUF_NDEBUG_INLINE static uint8_t* WriteFixed64NoTagToArray( + const RepeatedField<uint64_t>& value, uint8_t* output); + PROTOBUF_NDEBUG_INLINE static uint8_t* WriteSFixed32NoTagToArray( + const RepeatedField<int32_t>& value, uint8_t* output); + PROTOBUF_NDEBUG_INLINE static uint8_t* WriteSFixed64NoTagToArray( + const RepeatedField<int64_t>& value, uint8_t* output); + PROTOBUF_NDEBUG_INLINE static uint8_t* WriteFloatNoTagToArray( + const RepeatedField<float>& value, uint8_t* output); + PROTOBUF_NDEBUG_INLINE static uint8_t* WriteDoubleNoTagToArray( + const RepeatedField<double>& value, uint8_t* output); + PROTOBUF_NDEBUG_INLINE static uint8_t* WriteBoolNoTagToArray( + const RepeatedField<bool>& value, uint8_t* output); + PROTOBUF_NDEBUG_INLINE static uint8_t* WriteEnumNoTagToArray( + const RepeatedField<int>& value, uint8_t* output); + + // Write fields, including tags. + PROTOBUF_NDEBUG_INLINE static uint8_t* WriteInt32ToArray(int field_number, + int32_t value, + uint8_t* target); + PROTOBUF_NDEBUG_INLINE static uint8_t* WriteInt64ToArray(int field_number, + int64_t value, + uint8_t* target); + PROTOBUF_NDEBUG_INLINE static uint8_t* WriteUInt32ToArray(int field_number, + uint32_t value, + uint8_t* target); + PROTOBUF_NDEBUG_INLINE static uint8_t* WriteUInt64ToArray(int field_number, + uint64_t value, + uint8_t* target); + PROTOBUF_NDEBUG_INLINE static uint8_t* WriteSInt32ToArray(int field_number, + int32_t value, + uint8_t* target); + PROTOBUF_NDEBUG_INLINE static uint8_t* WriteSInt64ToArray(int field_number, + int64_t value, + uint8_t* target); + PROTOBUF_NDEBUG_INLINE static uint8_t* WriteFixed32ToArray(int field_number, + uint32_t value, + uint8_t* target); + PROTOBUF_NDEBUG_INLINE static uint8_t* WriteFixed64ToArray(int field_number, + uint64_t value, + uint8_t* target); + PROTOBUF_NDEBUG_INLINE static uint8_t* WriteSFixed32ToArray(int field_number, + int32_t value, + uint8_t* target); + PROTOBUF_NDEBUG_INLINE static uint8_t* WriteSFixed64ToArray(int field_number, + int64_t value, + uint8_t* target); + PROTOBUF_NDEBUG_INLINE static uint8_t* WriteFloatToArray(int field_number, + float value, + uint8_t* target); + PROTOBUF_NDEBUG_INLINE static uint8_t* WriteDoubleToArray(int field_number, + double value, + uint8_t* target); + PROTOBUF_NDEBUG_INLINE static uint8_t* WriteBoolToArray(int field_number, + bool value, + uint8_t* target); + PROTOBUF_NDEBUG_INLINE static uint8_t* WriteEnumToArray(int field_number, + int value, + uint8_t* target); + + template <typename T> + PROTOBUF_NDEBUG_INLINE static uint8_t* WritePrimitiveToArray( + int field_number, const RepeatedField<T>& value, + uint8_t* (*Writer)(int, T, uint8_t*), uint8_t* target); + + PROTOBUF_NDEBUG_INLINE static uint8_t* WriteInt32ToArray( + int field_number, const RepeatedField<int32_t>& value, uint8_t* output); + PROTOBUF_NDEBUG_INLINE static uint8_t* WriteInt64ToArray( + int field_number, const RepeatedField<int64_t>& value, uint8_t* output); + PROTOBUF_NDEBUG_INLINE static uint8_t* WriteUInt32ToArray( + int field_number, const RepeatedField<uint32_t>& value, uint8_t* output); + PROTOBUF_NDEBUG_INLINE static uint8_t* WriteUInt64ToArray( + int field_number, const RepeatedField<uint64_t>& value, uint8_t* output); + PROTOBUF_NDEBUG_INLINE static uint8_t* WriteSInt32ToArray( + int field_number, const RepeatedField<int32_t>& value, uint8_t* output); + PROTOBUF_NDEBUG_INLINE static uint8_t* WriteSInt64ToArray( + int field_number, const RepeatedField<int64_t>& value, uint8_t* output); + PROTOBUF_NDEBUG_INLINE static uint8_t* WriteFixed32ToArray( + int field_number, const RepeatedField<uint32_t>& value, uint8_t* output); + PROTOBUF_NDEBUG_INLINE static uint8_t* WriteFixed64ToArray( + int field_number, const RepeatedField<uint64_t>& value, uint8_t* output); + PROTOBUF_NDEBUG_INLINE static uint8_t* WriteSFixed32ToArray( + int field_number, const RepeatedField<int32_t>& value, uint8_t* output); + PROTOBUF_NDEBUG_INLINE static uint8_t* WriteSFixed64ToArray( + int field_number, const RepeatedField<int64_t>& value, uint8_t* output); + PROTOBUF_NDEBUG_INLINE static uint8_t* WriteFloatToArray( + int field_number, const RepeatedField<float>& value, uint8_t* output); + PROTOBUF_NDEBUG_INLINE static uint8_t* WriteDoubleToArray( + int field_number, const RepeatedField<double>& value, uint8_t* output); + PROTOBUF_NDEBUG_INLINE static uint8_t* WriteBoolToArray( + int field_number, const RepeatedField<bool>& value, uint8_t* output); + PROTOBUF_NDEBUG_INLINE static uint8_t* WriteEnumToArray( + int field_number, const RepeatedField<int>& value, uint8_t* output); + + PROTOBUF_NDEBUG_INLINE static uint8_t* WriteStringToArray( + int field_number, const std::string& value, uint8_t* target); + PROTOBUF_NDEBUG_INLINE static uint8_t* WriteBytesToArray( + int field_number, const std::string& value, uint8_t* target); + + // Whether to serialize deterministically (e.g., map keys are + // sorted) is a property of a CodedOutputStream, and in the process + // of serialization, the "ToArray" variants may be invoked. But they don't + // have a CodedOutputStream available, so they get an additional parameter + // telling them whether to serialize deterministically. + static uint8_t* InternalWriteGroup(int field_number, const MessageLite& value, + uint8_t* target, + io::EpsCopyOutputStream* stream); + static uint8_t* InternalWriteMessage(int field_number, + const MessageLite& value, + int cached_size, uint8_t* target, + io::EpsCopyOutputStream* stream); + + // Like above, but de-virtualize the call to SerializeWithCachedSizes(). The + // pointer must point at an instance of MessageType, *not* a subclass (or + // the subclass must not override SerializeWithCachedSizes()). + template <typename MessageType> + PROTOBUF_NDEBUG_INLINE static uint8_t* InternalWriteGroupNoVirtualToArray( + int field_number, const MessageType& value, uint8_t* target); + template <typename MessageType> + PROTOBUF_NDEBUG_INLINE static uint8_t* InternalWriteMessageNoVirtualToArray( + int field_number, const MessageType& value, uint8_t* target); + + // For backward-compatibility, the last four methods also have versions + // that are non-deterministic always. + PROTOBUF_NDEBUG_INLINE static uint8_t* WriteGroupToArray( + int field_number, const MessageLite& value, uint8_t* target) { + io::EpsCopyOutputStream stream( + target, + value.GetCachedSize() + + static_cast<int>(2 * io::CodedOutputStream::VarintSize32( + static_cast<uint32_t>(field_number) << 3)), + io::CodedOutputStream::IsDefaultSerializationDeterministic()); + return InternalWriteGroup(field_number, value, target, &stream); + } + PROTOBUF_NDEBUG_INLINE static uint8_t* WriteMessageToArray( + int field_number, const MessageLite& value, uint8_t* target) { + int size = value.GetCachedSize(); + io::EpsCopyOutputStream stream( + target, + size + static_cast<int>(io::CodedOutputStream::VarintSize32( + static_cast<uint32_t>(field_number) << 3) + + io::CodedOutputStream::VarintSize32(size)), + io::CodedOutputStream::IsDefaultSerializationDeterministic()); + return InternalWriteMessage(field_number, value, value.GetCachedSize(), + target, &stream); + } + + // Compute the byte size of a field. The XxSize() functions do NOT include + // the tag, so you must also call TagSize(). (This is because, for repeated + // fields, you should only call TagSize() once and multiply it by the element + // count, but you may have to call XxSize() for each individual element.) + static inline size_t Int32Size(int32_t value); + static inline size_t Int64Size(int64_t value); + static inline size_t UInt32Size(uint32_t value); + static inline size_t UInt64Size(uint64_t value); + static inline size_t SInt32Size(int32_t value); + static inline size_t SInt64Size(int64_t value); + static inline size_t EnumSize(int value); + static inline size_t Int32SizePlusOne(int32_t value); + static inline size_t Int64SizePlusOne(int64_t value); + static inline size_t UInt32SizePlusOne(uint32_t value); + static inline size_t UInt64SizePlusOne(uint64_t value); + static inline size_t SInt32SizePlusOne(int32_t value); + static inline size_t SInt64SizePlusOne(int64_t value); + static inline size_t EnumSizePlusOne(int value); + + static size_t Int32Size(const RepeatedField<int32_t>& value); + static size_t Int64Size(const RepeatedField<int64_t>& value); + static size_t UInt32Size(const RepeatedField<uint32_t>& value); + static size_t UInt64Size(const RepeatedField<uint64_t>& value); + static size_t SInt32Size(const RepeatedField<int32_t>& value); + static size_t SInt64Size(const RepeatedField<int64_t>& value); + static size_t EnumSize(const RepeatedField<int>& value); + + // These types always have the same size. + static constexpr size_t kFixed32Size = 4; + static constexpr size_t kFixed64Size = 8; + static constexpr size_t kSFixed32Size = 4; + static constexpr size_t kSFixed64Size = 8; + static constexpr size_t kFloatSize = 4; + static constexpr size_t kDoubleSize = 8; + static constexpr size_t kBoolSize = 1; + + static inline size_t StringSize(const std::string& value); + static inline size_t BytesSize(const std::string& value); + + template <typename MessageType> + static inline size_t GroupSize(const MessageType& value); + template <typename MessageType> + static inline size_t MessageSize(const MessageType& value); + + // Like above, but de-virtualize the call to ByteSize(). The + // pointer must point at an instance of MessageType, *not* a subclass (or + // the subclass must not override ByteSize()). + template <typename MessageType> + static inline size_t GroupSizeNoVirtual(const MessageType& value); + template <typename MessageType> + static inline size_t MessageSizeNoVirtual(const MessageType& value); + + // Given the length of data, calculate the byte size of the data on the + // wire if we encode the data as a length delimited field. + static inline size_t LengthDelimitedSize(size_t length); + + private: + // A helper method for the repeated primitive reader. This method has + // optimizations for primitive types that have fixed size on the wire, and + // can be read using potentially faster paths. + template <typename CType, enum FieldType DeclaredType> + PROTOBUF_NDEBUG_INLINE static bool ReadRepeatedFixedSizePrimitive( + int tag_size, uint32_t tag, io::CodedInputStream* input, + RepeatedField<CType>* value); + + // Like ReadRepeatedFixedSizePrimitive but for packed primitive fields. + template <typename CType, enum FieldType DeclaredType> + PROTOBUF_NDEBUG_INLINE static bool ReadPackedFixedSizePrimitive( + io::CodedInputStream* input, RepeatedField<CType>* value); + + static const CppType kFieldTypeToCppTypeMap[]; + static const WireFormatLite::WireType kWireTypeForFieldType[]; + static void WriteSubMessageMaybeToArray(int size, const MessageLite& value, + io::CodedOutputStream* output); + + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(WireFormatLite); +}; + +// A class which deals with unknown values. The default implementation just +// discards them. WireFormat defines a subclass which writes to an +// UnknownFieldSet. This class is used by ExtensionSet::ParseField(), since +// ExtensionSet is part of the lite library but UnknownFieldSet is not. +class PROTOBUF_EXPORT FieldSkipper { + public: + FieldSkipper() {} + virtual ~FieldSkipper() {} + + // Skip a field whose tag has already been consumed. + virtual bool SkipField(io::CodedInputStream* input, uint32_t tag); + + // Skip an entire message or group, up to an end-group tag (which is consumed) + // or end-of-stream. + virtual bool SkipMessage(io::CodedInputStream* input); + + // Deal with an already-parsed unrecognized enum value. The default + // implementation does nothing, but the UnknownFieldSet-based implementation + // saves it as an unknown varint. + virtual void SkipUnknownEnum(int field_number, int value); +}; + +// Subclass of FieldSkipper which saves skipped fields to a CodedOutputStream. + +class PROTOBUF_EXPORT CodedOutputStreamFieldSkipper : public FieldSkipper { + public: + explicit CodedOutputStreamFieldSkipper(io::CodedOutputStream* unknown_fields) + : unknown_fields_(unknown_fields) {} + ~CodedOutputStreamFieldSkipper() override {} + + // implements FieldSkipper ----------------------------------------- + bool SkipField(io::CodedInputStream* input, uint32_t tag) override; + bool SkipMessage(io::CodedInputStream* input) override; + void SkipUnknownEnum(int field_number, int value) override; + + protected: + io::CodedOutputStream* unknown_fields_; +}; + +// inline methods ==================================================== + +inline WireFormatLite::CppType WireFormatLite::FieldTypeToCppType( + FieldType type) { + return kFieldTypeToCppTypeMap[type]; +} + +constexpr inline uint32_t WireFormatLite::MakeTag(int field_number, + WireType type) { + return GOOGLE_PROTOBUF_WIRE_FORMAT_MAKE_TAG(field_number, type); +} + +inline WireFormatLite::WireType WireFormatLite::GetTagWireType(uint32_t tag) { + return static_cast<WireType>(tag & kTagTypeMask); +} + +inline int WireFormatLite::GetTagFieldNumber(uint32_t tag) { + return static_cast<int>(tag >> kTagTypeBits); +} + +inline size_t WireFormatLite::TagSize(int field_number, + WireFormatLite::FieldType type) { + size_t result = io::CodedOutputStream::VarintSize32( + static_cast<uint32_t>(field_number << kTagTypeBits)); + if (type == TYPE_GROUP) { + // Groups have both a start and an end tag. + return result * 2; + } else { + return result; + } +} + +inline uint32_t WireFormatLite::EncodeFloat(float value) { + return bit_cast<uint32_t>(value); +} + +inline float WireFormatLite::DecodeFloat(uint32_t value) { + return bit_cast<float>(value); +} + +inline uint64_t WireFormatLite::EncodeDouble(double value) { + return bit_cast<uint64_t>(value); +} + +inline double WireFormatLite::DecodeDouble(uint64_t value) { + return bit_cast<double>(value); +} + +// ZigZag Transform: Encodes signed integers so that they can be +// effectively used with varint encoding. +// +// varint operates on unsigned integers, encoding smaller numbers into +// fewer bytes. If you try to use it on a signed integer, it will treat +// this number as a very large unsigned integer, which means that even +// small signed numbers like -1 will take the maximum number of bytes +// (10) to encode. ZigZagEncode() maps signed integers to unsigned +// in such a way that those with a small absolute value will have smaller +// encoded values, making them appropriate for encoding using varint. +// +// int32_t -> uint32_t +// ------------------------- +// 0 -> 0 +// -1 -> 1 +// 1 -> 2 +// -2 -> 3 +// ... -> ... +// 2147483647 -> 4294967294 +// -2147483648 -> 4294967295 +// +// >> encode >> +// << decode << + +inline uint32_t WireFormatLite::ZigZagEncode32(int32_t n) { + // Note: the right-shift must be arithmetic + // Note: left shift must be unsigned because of overflow + return (static_cast<uint32_t>(n) << 1) ^ static_cast<uint32_t>(n >> 31); +} + +inline int32_t WireFormatLite::ZigZagDecode32(uint32_t n) { + // Note: Using unsigned types prevent undefined behavior + return static_cast<int32_t>((n >> 1) ^ (~(n & 1) + 1)); +} + +inline uint64_t WireFormatLite::ZigZagEncode64(int64_t n) { + // Note: the right-shift must be arithmetic + // Note: left shift must be unsigned because of overflow + return (static_cast<uint64_t>(n) << 1) ^ static_cast<uint64_t>(n >> 63); +} + +inline int64_t WireFormatLite::ZigZagDecode64(uint64_t n) { + // Note: Using unsigned types prevent undefined behavior + return static_cast<int64_t>((n >> 1) ^ (~(n & 1) + 1)); +} + +// String is for UTF-8 text only, but, even so, ReadString() can simply +// call ReadBytes(). + +inline bool WireFormatLite::ReadString(io::CodedInputStream* input, + std::string* value) { + return ReadBytes(input, value); +} + +inline bool WireFormatLite::ReadString(io::CodedInputStream* input, + std::string** p) { + return ReadBytes(input, p); +} + +inline uint8_t* InternalSerializeUnknownMessageSetItemsToArray( + const std::string& unknown_fields, uint8_t* target, + io::EpsCopyOutputStream* stream) { + return stream->WriteRaw(unknown_fields.data(), + static_cast<int>(unknown_fields.size()), target); +} + +inline size_t ComputeUnknownMessageSetItemsSize( + const std::string& unknown_fields) { + return unknown_fields.size(); +} + +// Implementation details of ReadPrimitive. + +template <> +inline bool WireFormatLite::ReadPrimitive<int32_t, WireFormatLite::TYPE_INT32>( + io::CodedInputStream* input, int32_t* value) { + uint32_t temp; + if (!input->ReadVarint32(&temp)) return false; + *value = static_cast<int32_t>(temp); + return true; +} +template <> +inline bool WireFormatLite::ReadPrimitive<int64_t, WireFormatLite::TYPE_INT64>( + io::CodedInputStream* input, int64_t* value) { + uint64_t temp; + if (!input->ReadVarint64(&temp)) return false; + *value = static_cast<int64_t>(temp); + return true; +} +template <> +inline bool +WireFormatLite::ReadPrimitive<uint32_t, WireFormatLite::TYPE_UINT32>( + io::CodedInputStream* input, uint32_t* value) { + return input->ReadVarint32(value); +} +template <> +inline bool +WireFormatLite::ReadPrimitive<uint64_t, WireFormatLite::TYPE_UINT64>( + io::CodedInputStream* input, uint64_t* value) { + return input->ReadVarint64(value); +} +template <> +inline bool WireFormatLite::ReadPrimitive<int32_t, WireFormatLite::TYPE_SINT32>( + io::CodedInputStream* input, int32_t* value) { + uint32_t temp; + if (!input->ReadVarint32(&temp)) return false; + *value = ZigZagDecode32(temp); + return true; +} +template <> +inline bool WireFormatLite::ReadPrimitive<int64_t, WireFormatLite::TYPE_SINT64>( + io::CodedInputStream* input, int64_t* value) { + uint64_t temp; + if (!input->ReadVarint64(&temp)) return false; + *value = ZigZagDecode64(temp); + return true; +} +template <> +inline bool +WireFormatLite::ReadPrimitive<uint32_t, WireFormatLite::TYPE_FIXED32>( + io::CodedInputStream* input, uint32_t* value) { + return input->ReadLittleEndian32(value); +} +template <> +inline bool +WireFormatLite::ReadPrimitive<uint64_t, WireFormatLite::TYPE_FIXED64>( + io::CodedInputStream* input, uint64_t* value) { + return input->ReadLittleEndian64(value); +} +template <> +inline bool +WireFormatLite::ReadPrimitive<int32_t, WireFormatLite::TYPE_SFIXED32>( + io::CodedInputStream* input, int32_t* value) { + uint32_t temp; + if (!input->ReadLittleEndian32(&temp)) return false; + *value = static_cast<int32_t>(temp); + return true; +} +template <> +inline bool +WireFormatLite::ReadPrimitive<int64_t, WireFormatLite::TYPE_SFIXED64>( + io::CodedInputStream* input, int64_t* value) { + uint64_t temp; + if (!input->ReadLittleEndian64(&temp)) return false; + *value = static_cast<int64_t>(temp); + return true; +} +template <> +inline bool WireFormatLite::ReadPrimitive<float, WireFormatLite::TYPE_FLOAT>( + io::CodedInputStream* input, float* value) { + uint32_t temp; + if (!input->ReadLittleEndian32(&temp)) return false; + *value = DecodeFloat(temp); + return true; +} +template <> +inline bool WireFormatLite::ReadPrimitive<double, WireFormatLite::TYPE_DOUBLE>( + io::CodedInputStream* input, double* value) { + uint64_t temp; + if (!input->ReadLittleEndian64(&temp)) return false; + *value = DecodeDouble(temp); + return true; +} +template <> +inline bool WireFormatLite::ReadPrimitive<bool, WireFormatLite::TYPE_BOOL>( + io::CodedInputStream* input, bool* value) { + uint64_t temp; + if (!input->ReadVarint64(&temp)) return false; + *value = temp != 0; + return true; +} +template <> +inline bool WireFormatLite::ReadPrimitive<int, WireFormatLite::TYPE_ENUM>( + io::CodedInputStream* input, int* value) { + uint32_t temp; + if (!input->ReadVarint32(&temp)) return false; + *value = static_cast<int>(temp); + return true; +} + +template <> +inline const uint8_t* +WireFormatLite::ReadPrimitiveFromArray<uint32_t, WireFormatLite::TYPE_FIXED32>( + const uint8_t* buffer, uint32_t* value) { + return io::CodedInputStream::ReadLittleEndian32FromArray(buffer, value); +} +template <> +inline const uint8_t* +WireFormatLite::ReadPrimitiveFromArray<uint64_t, WireFormatLite::TYPE_FIXED64>( + const uint8_t* buffer, uint64_t* value) { + return io::CodedInputStream::ReadLittleEndian64FromArray(buffer, value); +} +template <> +inline const uint8_t* +WireFormatLite::ReadPrimitiveFromArray<int32_t, WireFormatLite::TYPE_SFIXED32>( + const uint8_t* buffer, int32_t* value) { + uint32_t temp; + buffer = io::CodedInputStream::ReadLittleEndian32FromArray(buffer, &temp); + *value = static_cast<int32_t>(temp); + return buffer; +} +template <> +inline const uint8_t* +WireFormatLite::ReadPrimitiveFromArray<int64_t, WireFormatLite::TYPE_SFIXED64>( + const uint8_t* buffer, int64_t* value) { + uint64_t temp; + buffer = io::CodedInputStream::ReadLittleEndian64FromArray(buffer, &temp); + *value = static_cast<int64_t>(temp); + return buffer; +} +template <> +inline const uint8_t* +WireFormatLite::ReadPrimitiveFromArray<float, WireFormatLite::TYPE_FLOAT>( + const uint8_t* buffer, float* value) { + uint32_t temp; + buffer = io::CodedInputStream::ReadLittleEndian32FromArray(buffer, &temp); + *value = DecodeFloat(temp); + return buffer; +} +template <> +inline const uint8_t* +WireFormatLite::ReadPrimitiveFromArray<double, WireFormatLite::TYPE_DOUBLE>( + const uint8_t* buffer, double* value) { + uint64_t temp; + buffer = io::CodedInputStream::ReadLittleEndian64FromArray(buffer, &temp); + *value = DecodeDouble(temp); + return buffer; +} + +template <typename CType, enum WireFormatLite::FieldType DeclaredType> +inline bool WireFormatLite::ReadRepeatedPrimitive( + int, // tag_size, unused. + uint32_t tag, io::CodedInputStream* input, RepeatedField<CType>* values) { + CType value; + if (!ReadPrimitive<CType, DeclaredType>(input, &value)) return false; + values->Add(value); + int elements_already_reserved = values->Capacity() - values->size(); + while (elements_already_reserved > 0 && input->ExpectTag(tag)) { + if (!ReadPrimitive<CType, DeclaredType>(input, &value)) return false; + values->AddAlreadyReserved(value); + elements_already_reserved--; + } + return true; +} + +template <typename CType, enum WireFormatLite::FieldType DeclaredType> +inline bool WireFormatLite::ReadRepeatedFixedSizePrimitive( + int tag_size, uint32_t tag, io::CodedInputStream* input, + RepeatedField<CType>* values) { + GOOGLE_DCHECK_EQ(UInt32Size(tag), static_cast<size_t>(tag_size)); + CType value; + if (!ReadPrimitive<CType, DeclaredType>(input, &value)) return false; + values->Add(value); + + // For fixed size values, repeated values can be read more quickly by + // reading directly from a raw array. + // + // We can get a tight loop by only reading as many elements as can be + // added to the RepeatedField without having to do any resizing. Additionally, + // we only try to read as many elements as are available from the current + // buffer space. Doing so avoids having to perform boundary checks when + // reading the value: the maximum number of elements that can be read is + // known outside of the loop. + const void* void_pointer; + int size; + input->GetDirectBufferPointerInline(&void_pointer, &size); + if (size > 0) { + const uint8_t* buffer = reinterpret_cast<const uint8_t*>(void_pointer); + // The number of bytes each type occupies on the wire. + const int per_value_size = tag_size + static_cast<int>(sizeof(value)); + + // parentheses around (std::min) prevents macro expansion of min(...) + int elements_available = + (std::min)(values->Capacity() - values->size(), size / per_value_size); + int num_read = 0; + while (num_read < elements_available && + (buffer = io::CodedInputStream::ExpectTagFromArray(buffer, tag)) != + nullptr) { + buffer = ReadPrimitiveFromArray<CType, DeclaredType>(buffer, &value); + values->AddAlreadyReserved(value); + ++num_read; + } + const int read_bytes = num_read * per_value_size; + if (read_bytes > 0) { + input->Skip(read_bytes); + } + } + return true; +} + +// Specializations of ReadRepeatedPrimitive for the fixed size types, which use +// the optimized code path. +#define READ_REPEATED_FIXED_SIZE_PRIMITIVE(CPPTYPE, DECLARED_TYPE) \ + template <> \ + inline bool WireFormatLite::ReadRepeatedPrimitive< \ + CPPTYPE, WireFormatLite::DECLARED_TYPE>( \ + int tag_size, uint32_t tag, io::CodedInputStream* input, \ + RepeatedField<CPPTYPE>* values) { \ + return ReadRepeatedFixedSizePrimitive<CPPTYPE, \ + WireFormatLite::DECLARED_TYPE>( \ + tag_size, tag, input, values); \ + } + +READ_REPEATED_FIXED_SIZE_PRIMITIVE(uint32_t, TYPE_FIXED32) +READ_REPEATED_FIXED_SIZE_PRIMITIVE(uint64_t, TYPE_FIXED64) +READ_REPEATED_FIXED_SIZE_PRIMITIVE(int32_t, TYPE_SFIXED32) +READ_REPEATED_FIXED_SIZE_PRIMITIVE(int64_t, TYPE_SFIXED64) +READ_REPEATED_FIXED_SIZE_PRIMITIVE(float, TYPE_FLOAT) +READ_REPEATED_FIXED_SIZE_PRIMITIVE(double, TYPE_DOUBLE) + +#undef READ_REPEATED_FIXED_SIZE_PRIMITIVE + +template <typename CType, enum WireFormatLite::FieldType DeclaredType> +bool WireFormatLite::ReadRepeatedPrimitiveNoInline( + int tag_size, uint32_t tag, io::CodedInputStream* input, + RepeatedField<CType>* value) { + return ReadRepeatedPrimitive<CType, DeclaredType>(tag_size, tag, input, + value); +} + +template <typename CType, enum WireFormatLite::FieldType DeclaredType> +inline bool WireFormatLite::ReadPackedPrimitive(io::CodedInputStream* input, + RepeatedField<CType>* values) { + int length; + if (!input->ReadVarintSizeAsInt(&length)) return false; + io::CodedInputStream::Limit limit = input->PushLimit(length); + while (input->BytesUntilLimit() > 0) { + CType value; + if (!ReadPrimitive<CType, DeclaredType>(input, &value)) return false; + values->Add(value); + } + input->PopLimit(limit); + return true; +} + +template <typename CType, enum WireFormatLite::FieldType DeclaredType> +inline bool WireFormatLite::ReadPackedFixedSizePrimitive( + io::CodedInputStream* input, RepeatedField<CType>* values) { + int length; + if (!input->ReadVarintSizeAsInt(&length)) return false; + const int old_entries = values->size(); + const int new_entries = length / static_cast<int>(sizeof(CType)); + const int new_bytes = new_entries * static_cast<int>(sizeof(CType)); + if (new_bytes != length) return false; + // We would *like* to pre-allocate the buffer to write into (for + // speed), but *must* avoid performing a very large allocation due + // to a malicious user-supplied "length" above. So we have a fast + // path that pre-allocates when the "length" is less than a bound. + // We determine the bound by calling BytesUntilTotalBytesLimit() and + // BytesUntilLimit(). These return -1 to mean "no limit set". + // There are four cases: + // TotalBytesLimit Limit + // -1 -1 Use slow path. + // -1 >= 0 Use fast path if length <= Limit. + // >= 0 -1 Use slow path. + // >= 0 >= 0 Use fast path if length <= min(both limits). + int64_t bytes_limit = input->BytesUntilTotalBytesLimit(); + if (bytes_limit == -1) { + bytes_limit = input->BytesUntilLimit(); + } else { + // parentheses around (std::min) prevents macro expansion of min(...) + bytes_limit = + (std::min)(bytes_limit, static_cast<int64_t>(input->BytesUntilLimit())); + } + if (bytes_limit >= new_bytes) { + // Fast-path that pre-allocates *values to the final size. +#if defined(PROTOBUF_LITTLE_ENDIAN) + values->Resize(old_entries + new_entries, 0); + // values->mutable_data() may change after Resize(), so do this after: + void* dest = reinterpret_cast<void*>(values->mutable_data() + old_entries); + if (!input->ReadRaw(dest, new_bytes)) { + values->Truncate(old_entries); + return false; + } +#else + values->Reserve(old_entries + new_entries); + CType value; + for (int i = 0; i < new_entries; ++i) { + if (!ReadPrimitive<CType, DeclaredType>(input, &value)) return false; + values->AddAlreadyReserved(value); + } +#endif + } else { + // This is the slow-path case where "length" may be too large to + // safely allocate. We read as much as we can into *values + // without pre-allocating "length" bytes. + CType value; + for (int i = 0; i < new_entries; ++i) { + if (!ReadPrimitive<CType, DeclaredType>(input, &value)) return false; + values->Add(value); + } + } + return true; +} + +// Specializations of ReadPackedPrimitive for the fixed size types, which use +// an optimized code path. +#define READ_REPEATED_PACKED_FIXED_SIZE_PRIMITIVE(CPPTYPE, DECLARED_TYPE) \ + template <> \ + inline bool \ + WireFormatLite::ReadPackedPrimitive<CPPTYPE, WireFormatLite::DECLARED_TYPE>( \ + io::CodedInputStream * input, RepeatedField<CPPTYPE> * values) { \ + return ReadPackedFixedSizePrimitive<CPPTYPE, \ + WireFormatLite::DECLARED_TYPE>( \ + input, values); \ + } + +READ_REPEATED_PACKED_FIXED_SIZE_PRIMITIVE(uint32_t, TYPE_FIXED32) +READ_REPEATED_PACKED_FIXED_SIZE_PRIMITIVE(uint64_t, TYPE_FIXED64) +READ_REPEATED_PACKED_FIXED_SIZE_PRIMITIVE(int32_t, TYPE_SFIXED32) +READ_REPEATED_PACKED_FIXED_SIZE_PRIMITIVE(int64_t, TYPE_SFIXED64) +READ_REPEATED_PACKED_FIXED_SIZE_PRIMITIVE(float, TYPE_FLOAT) +READ_REPEATED_PACKED_FIXED_SIZE_PRIMITIVE(double, TYPE_DOUBLE) + +#undef READ_REPEATED_PACKED_FIXED_SIZE_PRIMITIVE + +template <typename CType, enum WireFormatLite::FieldType DeclaredType> +bool WireFormatLite::ReadPackedPrimitiveNoInline(io::CodedInputStream* input, + RepeatedField<CType>* values) { + return ReadPackedPrimitive<CType, DeclaredType>(input, values); +} + + +template <typename MessageType> +inline bool WireFormatLite::ReadGroup(int field_number, + io::CodedInputStream* input, + MessageType* value) { + if (!input->IncrementRecursionDepth()) return false; + if (!value->MergePartialFromCodedStream(input)) return false; + input->UnsafeDecrementRecursionDepth(); + // Make sure the last thing read was an end tag for this group. + if (!input->LastTagWas(MakeTag(field_number, WIRETYPE_END_GROUP))) { + return false; + } + return true; +} +template <typename MessageType> +inline bool WireFormatLite::ReadMessage(io::CodedInputStream* input, + MessageType* value) { + int length; + if (!input->ReadVarintSizeAsInt(&length)) return false; + std::pair<io::CodedInputStream::Limit, int> p = + input->IncrementRecursionDepthAndPushLimit(length); + if (p.second < 0 || !value->MergePartialFromCodedStream(input)) return false; + // Make sure that parsing stopped when the limit was hit, not at an endgroup + // tag. + return input->DecrementRecursionDepthAndPopLimit(p.first); +} + +// =================================================================== + +inline void WireFormatLite::WriteTag(int field_number, WireType type, + io::CodedOutputStream* output) { + output->WriteTag(MakeTag(field_number, type)); +} + +inline void WireFormatLite::WriteInt32NoTag(int32_t value, + io::CodedOutputStream* output) { + output->WriteVarint32SignExtended(value); +} +inline void WireFormatLite::WriteInt64NoTag(int64_t value, + io::CodedOutputStream* output) { + output->WriteVarint64(static_cast<uint64_t>(value)); +} +inline void WireFormatLite::WriteUInt32NoTag(uint32_t value, + io::CodedOutputStream* output) { + output->WriteVarint32(value); +} +inline void WireFormatLite::WriteUInt64NoTag(uint64_t value, + io::CodedOutputStream* output) { + output->WriteVarint64(value); +} +inline void WireFormatLite::WriteSInt32NoTag(int32_t value, + io::CodedOutputStream* output) { + output->WriteVarint32(ZigZagEncode32(value)); +} +inline void WireFormatLite::WriteSInt64NoTag(int64_t value, + io::CodedOutputStream* output) { + output->WriteVarint64(ZigZagEncode64(value)); +} +inline void WireFormatLite::WriteFixed32NoTag(uint32_t value, + io::CodedOutputStream* output) { + output->WriteLittleEndian32(value); +} +inline void WireFormatLite::WriteFixed64NoTag(uint64_t value, + io::CodedOutputStream* output) { + output->WriteLittleEndian64(value); +} +inline void WireFormatLite::WriteSFixed32NoTag(int32_t value, + io::CodedOutputStream* output) { + output->WriteLittleEndian32(static_cast<uint32_t>(value)); +} +inline void WireFormatLite::WriteSFixed64NoTag(int64_t value, + io::CodedOutputStream* output) { + output->WriteLittleEndian64(static_cast<uint64_t>(value)); +} +inline void WireFormatLite::WriteFloatNoTag(float value, + io::CodedOutputStream* output) { + output->WriteLittleEndian32(EncodeFloat(value)); +} +inline void WireFormatLite::WriteDoubleNoTag(double value, + io::CodedOutputStream* output) { + output->WriteLittleEndian64(EncodeDouble(value)); +} +inline void WireFormatLite::WriteBoolNoTag(bool value, + io::CodedOutputStream* output) { + output->WriteVarint32(value ? 1 : 0); +} +inline void WireFormatLite::WriteEnumNoTag(int value, + io::CodedOutputStream* output) { + output->WriteVarint32SignExtended(value); +} + +// See comment on ReadGroupNoVirtual to understand the need for this template +// parameter name. +template <typename MessageType_WorkAroundCppLookupDefect> +inline void WireFormatLite::WriteGroupNoVirtual( + int field_number, const MessageType_WorkAroundCppLookupDefect& value, + io::CodedOutputStream* output) { + WriteTag(field_number, WIRETYPE_START_GROUP, output); + value.MessageType_WorkAroundCppLookupDefect::SerializeWithCachedSizes(output); + WriteTag(field_number, WIRETYPE_END_GROUP, output); +} +template <typename MessageType_WorkAroundCppLookupDefect> +inline void WireFormatLite::WriteMessageNoVirtual( + int field_number, const MessageType_WorkAroundCppLookupDefect& value, + io::CodedOutputStream* output) { + WriteTag(field_number, WIRETYPE_LENGTH_DELIMITED, output); + output->WriteVarint32( + value.MessageType_WorkAroundCppLookupDefect::GetCachedSize()); + value.MessageType_WorkAroundCppLookupDefect::SerializeWithCachedSizes(output); +} + +// =================================================================== + +inline uint8_t* WireFormatLite::WriteTagToArray(int field_number, WireType type, + uint8_t* target) { + return io::CodedOutputStream::WriteTagToArray(MakeTag(field_number, type), + target); +} + +inline uint8_t* WireFormatLite::WriteInt32NoTagToArray(int32_t value, + uint8_t* target) { + return io::CodedOutputStream::WriteVarint32SignExtendedToArray(value, target); +} +inline uint8_t* WireFormatLite::WriteInt64NoTagToArray(int64_t value, + uint8_t* target) { + return io::CodedOutputStream::WriteVarint64ToArray( + static_cast<uint64_t>(value), target); +} +inline uint8_t* WireFormatLite::WriteUInt32NoTagToArray(uint32_t value, + uint8_t* target) { + return io::CodedOutputStream::WriteVarint32ToArray(value, target); +} +inline uint8_t* WireFormatLite::WriteUInt64NoTagToArray(uint64_t value, + uint8_t* target) { + return io::CodedOutputStream::WriteVarint64ToArray(value, target); +} +inline uint8_t* WireFormatLite::WriteSInt32NoTagToArray(int32_t value, + uint8_t* target) { + return io::CodedOutputStream::WriteVarint32ToArray(ZigZagEncode32(value), + target); +} +inline uint8_t* WireFormatLite::WriteSInt64NoTagToArray(int64_t value, + uint8_t* target) { + return io::CodedOutputStream::WriteVarint64ToArray(ZigZagEncode64(value), + target); +} +inline uint8_t* WireFormatLite::WriteFixed32NoTagToArray(uint32_t value, + uint8_t* target) { + return io::CodedOutputStream::WriteLittleEndian32ToArray(value, target); +} +inline uint8_t* WireFormatLite::WriteFixed64NoTagToArray(uint64_t value, + uint8_t* target) { + return io::CodedOutputStream::WriteLittleEndian64ToArray(value, target); +} +inline uint8_t* WireFormatLite::WriteSFixed32NoTagToArray(int32_t value, + uint8_t* target) { + return io::CodedOutputStream::WriteLittleEndian32ToArray( + static_cast<uint32_t>(value), target); +} +inline uint8_t* WireFormatLite::WriteSFixed64NoTagToArray(int64_t value, + uint8_t* target) { + return io::CodedOutputStream::WriteLittleEndian64ToArray( + static_cast<uint64_t>(value), target); +} +inline uint8_t* WireFormatLite::WriteFloatNoTagToArray(float value, + uint8_t* target) { + return io::CodedOutputStream::WriteLittleEndian32ToArray(EncodeFloat(value), + target); +} +inline uint8_t* WireFormatLite::WriteDoubleNoTagToArray(double value, + uint8_t* target) { + return io::CodedOutputStream::WriteLittleEndian64ToArray(EncodeDouble(value), + target); +} +inline uint8_t* WireFormatLite::WriteBoolNoTagToArray(bool value, + uint8_t* target) { + return io::CodedOutputStream::WriteVarint32ToArray(value ? 1 : 0, target); +} +inline uint8_t* WireFormatLite::WriteEnumNoTagToArray(int value, + uint8_t* target) { + return io::CodedOutputStream::WriteVarint32SignExtendedToArray(value, target); +} + +template <typename T> +inline uint8_t* WireFormatLite::WritePrimitiveNoTagToArray( + const RepeatedField<T>& value, uint8_t* (*Writer)(T, uint8_t*), + uint8_t* target) { + const int n = value.size(); + GOOGLE_DCHECK_GT(n, 0); + + const T* ii = value.data(); + int i = 0; + do { + target = Writer(ii[i], target); + } while (++i < n); + + return target; +} + +template <typename T> +inline uint8_t* WireFormatLite::WriteFixedNoTagToArray( + const RepeatedField<T>& value, uint8_t* (*Writer)(T, uint8_t*), + uint8_t* target) { +#if defined(PROTOBUF_LITTLE_ENDIAN) + (void)Writer; + + const int n = value.size(); + GOOGLE_DCHECK_GT(n, 0); + + const T* ii = value.data(); + const int bytes = n * static_cast<int>(sizeof(ii[0])); + memcpy(target, ii, static_cast<size_t>(bytes)); + return target + bytes; +#else + return WritePrimitiveNoTagToArray(value, Writer, target); +#endif +} + +inline uint8_t* WireFormatLite::WriteInt32NoTagToArray( + const RepeatedField<int32_t>& value, uint8_t* target) { + return WritePrimitiveNoTagToArray(value, WriteInt32NoTagToArray, target); +} +inline uint8_t* WireFormatLite::WriteInt64NoTagToArray( + const RepeatedField<int64_t>& value, uint8_t* target) { + return WritePrimitiveNoTagToArray(value, WriteInt64NoTagToArray, target); +} +inline uint8_t* WireFormatLite::WriteUInt32NoTagToArray( + const RepeatedField<uint32_t>& value, uint8_t* target) { + return WritePrimitiveNoTagToArray(value, WriteUInt32NoTagToArray, target); +} +inline uint8_t* WireFormatLite::WriteUInt64NoTagToArray( + const RepeatedField<uint64_t>& value, uint8_t* target) { + return WritePrimitiveNoTagToArray(value, WriteUInt64NoTagToArray, target); +} +inline uint8_t* WireFormatLite::WriteSInt32NoTagToArray( + const RepeatedField<int32_t>& value, uint8_t* target) { + return WritePrimitiveNoTagToArray(value, WriteSInt32NoTagToArray, target); +} +inline uint8_t* WireFormatLite::WriteSInt64NoTagToArray( + const RepeatedField<int64_t>& value, uint8_t* target) { + return WritePrimitiveNoTagToArray(value, WriteSInt64NoTagToArray, target); +} +inline uint8_t* WireFormatLite::WriteFixed32NoTagToArray( + const RepeatedField<uint32_t>& value, uint8_t* target) { + return WriteFixedNoTagToArray(value, WriteFixed32NoTagToArray, target); +} +inline uint8_t* WireFormatLite::WriteFixed64NoTagToArray( + const RepeatedField<uint64_t>& value, uint8_t* target) { + return WriteFixedNoTagToArray(value, WriteFixed64NoTagToArray, target); +} +inline uint8_t* WireFormatLite::WriteSFixed32NoTagToArray( + const RepeatedField<int32_t>& value, uint8_t* target) { + return WriteFixedNoTagToArray(value, WriteSFixed32NoTagToArray, target); +} +inline uint8_t* WireFormatLite::WriteSFixed64NoTagToArray( + const RepeatedField<int64_t>& value, uint8_t* target) { + return WriteFixedNoTagToArray(value, WriteSFixed64NoTagToArray, target); +} +inline uint8_t* WireFormatLite::WriteFloatNoTagToArray( + const RepeatedField<float>& value, uint8_t* target) { + return WriteFixedNoTagToArray(value, WriteFloatNoTagToArray, target); +} +inline uint8_t* WireFormatLite::WriteDoubleNoTagToArray( + const RepeatedField<double>& value, uint8_t* target) { + return WriteFixedNoTagToArray(value, WriteDoubleNoTagToArray, target); +} +inline uint8_t* WireFormatLite::WriteBoolNoTagToArray( + const RepeatedField<bool>& value, uint8_t* target) { + return WritePrimitiveNoTagToArray(value, WriteBoolNoTagToArray, target); +} +inline uint8_t* WireFormatLite::WriteEnumNoTagToArray( + const RepeatedField<int>& value, uint8_t* target) { + return WritePrimitiveNoTagToArray(value, WriteEnumNoTagToArray, target); +} + +inline uint8_t* WireFormatLite::WriteInt32ToArray(int field_number, + int32_t value, + uint8_t* target) { + target = WriteTagToArray(field_number, WIRETYPE_VARINT, target); + return WriteInt32NoTagToArray(value, target); +} +inline uint8_t* WireFormatLite::WriteInt64ToArray(int field_number, + int64_t value, + uint8_t* target) { + target = WriteTagToArray(field_number, WIRETYPE_VARINT, target); + return WriteInt64NoTagToArray(value, target); +} +inline uint8_t* WireFormatLite::WriteUInt32ToArray(int field_number, + uint32_t value, + uint8_t* target) { + target = WriteTagToArray(field_number, WIRETYPE_VARINT, target); + return WriteUInt32NoTagToArray(value, target); +} +inline uint8_t* WireFormatLite::WriteUInt64ToArray(int field_number, + uint64_t value, + uint8_t* target) { + target = WriteTagToArray(field_number, WIRETYPE_VARINT, target); + return WriteUInt64NoTagToArray(value, target); +} +inline uint8_t* WireFormatLite::WriteSInt32ToArray(int field_number, + int32_t value, + uint8_t* target) { + target = WriteTagToArray(field_number, WIRETYPE_VARINT, target); + return WriteSInt32NoTagToArray(value, target); +} +inline uint8_t* WireFormatLite::WriteSInt64ToArray(int field_number, + int64_t value, + uint8_t* target) { + target = WriteTagToArray(field_number, WIRETYPE_VARINT, target); + return WriteSInt64NoTagToArray(value, target); +} +inline uint8_t* WireFormatLite::WriteFixed32ToArray(int field_number, + uint32_t value, + uint8_t* target) { + target = WriteTagToArray(field_number, WIRETYPE_FIXED32, target); + return WriteFixed32NoTagToArray(value, target); +} +inline uint8_t* WireFormatLite::WriteFixed64ToArray(int field_number, + uint64_t value, + uint8_t* target) { + target = WriteTagToArray(field_number, WIRETYPE_FIXED64, target); + return WriteFixed64NoTagToArray(value, target); +} +inline uint8_t* WireFormatLite::WriteSFixed32ToArray(int field_number, + int32_t value, + uint8_t* target) { + target = WriteTagToArray(field_number, WIRETYPE_FIXED32, target); + return WriteSFixed32NoTagToArray(value, target); +} +inline uint8_t* WireFormatLite::WriteSFixed64ToArray(int field_number, + int64_t value, + uint8_t* target) { + target = WriteTagToArray(field_number, WIRETYPE_FIXED64, target); + return WriteSFixed64NoTagToArray(value, target); +} +inline uint8_t* WireFormatLite::WriteFloatToArray(int field_number, float value, + uint8_t* target) { + target = WriteTagToArray(field_number, WIRETYPE_FIXED32, target); + return WriteFloatNoTagToArray(value, target); +} +inline uint8_t* WireFormatLite::WriteDoubleToArray(int field_number, + double value, + uint8_t* target) { + target = WriteTagToArray(field_number, WIRETYPE_FIXED64, target); + return WriteDoubleNoTagToArray(value, target); +} +inline uint8_t* WireFormatLite::WriteBoolToArray(int field_number, bool value, + uint8_t* target) { + target = WriteTagToArray(field_number, WIRETYPE_VARINT, target); + return WriteBoolNoTagToArray(value, target); +} +inline uint8_t* WireFormatLite::WriteEnumToArray(int field_number, int value, + uint8_t* target) { + target = WriteTagToArray(field_number, WIRETYPE_VARINT, target); + return WriteEnumNoTagToArray(value, target); +} + +template <typename T> +inline uint8_t* WireFormatLite::WritePrimitiveToArray( + int field_number, const RepeatedField<T>& value, + uint8_t* (*Writer)(int, T, uint8_t*), uint8_t* target) { + const int n = value.size(); + if (n == 0) { + return target; + } + + const T* ii = value.data(); + int i = 0; + do { + target = Writer(field_number, ii[i], target); + } while (++i < n); + + return target; +} + +inline uint8_t* WireFormatLite::WriteInt32ToArray( + int field_number, const RepeatedField<int32_t>& value, uint8_t* target) { + return WritePrimitiveToArray(field_number, value, WriteInt32ToArray, target); +} +inline uint8_t* WireFormatLite::WriteInt64ToArray( + int field_number, const RepeatedField<int64_t>& value, uint8_t* target) { + return WritePrimitiveToArray(field_number, value, WriteInt64ToArray, target); +} +inline uint8_t* WireFormatLite::WriteUInt32ToArray( + int field_number, const RepeatedField<uint32_t>& value, uint8_t* target) { + return WritePrimitiveToArray(field_number, value, WriteUInt32ToArray, target); +} +inline uint8_t* WireFormatLite::WriteUInt64ToArray( + int field_number, const RepeatedField<uint64_t>& value, uint8_t* target) { + return WritePrimitiveToArray(field_number, value, WriteUInt64ToArray, target); +} +inline uint8_t* WireFormatLite::WriteSInt32ToArray( + int field_number, const RepeatedField<int32_t>& value, uint8_t* target) { + return WritePrimitiveToArray(field_number, value, WriteSInt32ToArray, target); +} +inline uint8_t* WireFormatLite::WriteSInt64ToArray( + int field_number, const RepeatedField<int64_t>& value, uint8_t* target) { + return WritePrimitiveToArray(field_number, value, WriteSInt64ToArray, target); +} +inline uint8_t* WireFormatLite::WriteFixed32ToArray( + int field_number, const RepeatedField<uint32_t>& value, uint8_t* target) { + return WritePrimitiveToArray(field_number, value, WriteFixed32ToArray, + target); +} +inline uint8_t* WireFormatLite::WriteFixed64ToArray( + int field_number, const RepeatedField<uint64_t>& value, uint8_t* target) { + return WritePrimitiveToArray(field_number, value, WriteFixed64ToArray, + target); +} +inline uint8_t* WireFormatLite::WriteSFixed32ToArray( + int field_number, const RepeatedField<int32_t>& value, uint8_t* target) { + return WritePrimitiveToArray(field_number, value, WriteSFixed32ToArray, + target); +} +inline uint8_t* WireFormatLite::WriteSFixed64ToArray( + int field_number, const RepeatedField<int64_t>& value, uint8_t* target) { + return WritePrimitiveToArray(field_number, value, WriteSFixed64ToArray, + target); +} +inline uint8_t* WireFormatLite::WriteFloatToArray( + int field_number, const RepeatedField<float>& value, uint8_t* target) { + return WritePrimitiveToArray(field_number, value, WriteFloatToArray, target); +} +inline uint8_t* WireFormatLite::WriteDoubleToArray( + int field_number, const RepeatedField<double>& value, uint8_t* target) { + return WritePrimitiveToArray(field_number, value, WriteDoubleToArray, target); +} +inline uint8_t* WireFormatLite::WriteBoolToArray( + int field_number, const RepeatedField<bool>& value, uint8_t* target) { + return WritePrimitiveToArray(field_number, value, WriteBoolToArray, target); +} +inline uint8_t* WireFormatLite::WriteEnumToArray( + int field_number, const RepeatedField<int>& value, uint8_t* target) { + return WritePrimitiveToArray(field_number, value, WriteEnumToArray, target); +} +inline uint8_t* WireFormatLite::WriteStringToArray(int field_number, + const std::string& value, + uint8_t* target) { + // String is for UTF-8 text only + // WARNING: In wire_format.cc, both strings and bytes are handled by + // WriteString() to avoid code duplication. If the implementations become + // different, you will need to update that usage. + target = WriteTagToArray(field_number, WIRETYPE_LENGTH_DELIMITED, target); + return io::CodedOutputStream::WriteStringWithSizeToArray(value, target); +} +inline uint8_t* WireFormatLite::WriteBytesToArray(int field_number, + const std::string& value, + uint8_t* target) { + target = WriteTagToArray(field_number, WIRETYPE_LENGTH_DELIMITED, target); + return io::CodedOutputStream::WriteStringWithSizeToArray(value, target); +} + + +// See comment on ReadGroupNoVirtual to understand the need for this template +// parameter name. +template <typename MessageType_WorkAroundCppLookupDefect> +inline uint8_t* WireFormatLite::InternalWriteGroupNoVirtualToArray( + int field_number, const MessageType_WorkAroundCppLookupDefect& value, + uint8_t* target) { + target = WriteTagToArray(field_number, WIRETYPE_START_GROUP, target); + target = value.MessageType_WorkAroundCppLookupDefect:: + SerializeWithCachedSizesToArray(target); + return WriteTagToArray(field_number, WIRETYPE_END_GROUP, target); +} +template <typename MessageType_WorkAroundCppLookupDefect> +inline uint8_t* WireFormatLite::InternalWriteMessageNoVirtualToArray( + int field_number, const MessageType_WorkAroundCppLookupDefect& value, + uint8_t* target) { + target = WriteTagToArray(field_number, WIRETYPE_LENGTH_DELIMITED, target); + target = io::CodedOutputStream::WriteVarint32ToArray( + static_cast<uint32_t>( + value.MessageType_WorkAroundCppLookupDefect::GetCachedSize()), + target); + return value + .MessageType_WorkAroundCppLookupDefect::SerializeWithCachedSizesToArray( + target); +} + +// =================================================================== + +inline size_t WireFormatLite::Int32Size(int32_t value) { + return io::CodedOutputStream::VarintSize32SignExtended(value); +} +inline size_t WireFormatLite::Int64Size(int64_t value) { + return io::CodedOutputStream::VarintSize64(static_cast<uint64_t>(value)); +} +inline size_t WireFormatLite::UInt32Size(uint32_t value) { + return io::CodedOutputStream::VarintSize32(value); +} +inline size_t WireFormatLite::UInt64Size(uint64_t value) { + return io::CodedOutputStream::VarintSize64(value); +} +inline size_t WireFormatLite::SInt32Size(int32_t value) { + return io::CodedOutputStream::VarintSize32(ZigZagEncode32(value)); +} +inline size_t WireFormatLite::SInt64Size(int64_t value) { + return io::CodedOutputStream::VarintSize64(ZigZagEncode64(value)); +} +inline size_t WireFormatLite::EnumSize(int value) { + return io::CodedOutputStream::VarintSize32SignExtended(value); +} +inline size_t WireFormatLite::Int32SizePlusOne(int32_t value) { + return io::CodedOutputStream::VarintSize32SignExtendedPlusOne(value); +} +inline size_t WireFormatLite::Int64SizePlusOne(int64_t value) { + return io::CodedOutputStream::VarintSize64PlusOne( + static_cast<uint64_t>(value)); +} +inline size_t WireFormatLite::UInt32SizePlusOne(uint32_t value) { + return io::CodedOutputStream::VarintSize32PlusOne(value); +} +inline size_t WireFormatLite::UInt64SizePlusOne(uint64_t value) { + return io::CodedOutputStream::VarintSize64PlusOne(value); +} +inline size_t WireFormatLite::SInt32SizePlusOne(int32_t value) { + return io::CodedOutputStream::VarintSize32PlusOne(ZigZagEncode32(value)); +} +inline size_t WireFormatLite::SInt64SizePlusOne(int64_t value) { + return io::CodedOutputStream::VarintSize64PlusOne(ZigZagEncode64(value)); +} +inline size_t WireFormatLite::EnumSizePlusOne(int value) { + return io::CodedOutputStream::VarintSize32SignExtendedPlusOne(value); +} + +inline size_t WireFormatLite::StringSize(const std::string& value) { + return LengthDelimitedSize(value.size()); +} +inline size_t WireFormatLite::BytesSize(const std::string& value) { + return LengthDelimitedSize(value.size()); +} + + +template <typename MessageType> +inline size_t WireFormatLite::GroupSize(const MessageType& value) { + return value.ByteSizeLong(); +} +template <typename MessageType> +inline size_t WireFormatLite::MessageSize(const MessageType& value) { + return LengthDelimitedSize(value.ByteSizeLong()); +} + +// See comment on ReadGroupNoVirtual to understand the need for this template +// parameter name. +template <typename MessageType_WorkAroundCppLookupDefect> +inline size_t WireFormatLite::GroupSizeNoVirtual( + const MessageType_WorkAroundCppLookupDefect& value) { + return value.MessageType_WorkAroundCppLookupDefect::ByteSizeLong(); +} +template <typename MessageType_WorkAroundCppLookupDefect> +inline size_t WireFormatLite::MessageSizeNoVirtual( + const MessageType_WorkAroundCppLookupDefect& value) { + return LengthDelimitedSize( + value.MessageType_WorkAroundCppLookupDefect::ByteSizeLong()); +} + +inline size_t WireFormatLite::LengthDelimitedSize(size_t length) { + // The static_cast here prevents an error in certain compiler configurations + // but is not technically correct--if length is too large to fit in a uint32_t + // then it will be silently truncated. We will need to fix this if we ever + // decide to start supporting serialized messages greater than 2 GiB in size. + return length + + io::CodedOutputStream::VarintSize32(static_cast<uint32_t>(length)); +} + +template <typename MS> +bool ParseMessageSetItemImpl(io::CodedInputStream* input, MS ms) { + // This method parses a group which should contain two fields: + // required int32 type_id = 2; + // required data message = 3; + + uint32_t last_type_id = 0; + + // If we see message data before the type_id, we'll append it to this so + // we can parse it later. + std::string message_data; + + enum class State { kNoTag, kHasType, kHasPayload, kDone }; + State state = State::kNoTag; + + while (true) { + const uint32_t tag = input->ReadTagNoLastTag(); + if (tag == 0) return false; + + switch (tag) { + case WireFormatLite::kMessageSetTypeIdTag: { + uint32_t type_id; + if (!input->ReadVarint32(&type_id)) return false; + if (state == State::kNoTag) { + last_type_id = type_id; + state = State::kHasType; + } else if (state == State::kHasPayload) { + // We saw some message data before the type_id. Have to parse it + // now. + io::CodedInputStream sub_input( + reinterpret_cast<const uint8_t*>(message_data.data()), + static_cast<int>(message_data.size())); + sub_input.SetRecursionLimit(input->RecursionBudget()); + if (!ms.ParseField(type_id, &sub_input)) { + return false; + } + message_data.clear(); + state = State::kDone; + } + + break; + } + + case WireFormatLite::kMessageSetMessageTag: { + if (state == State::kHasType) { + // Already saw type_id, so we can parse this directly. + if (!ms.ParseField(last_type_id, input)) { + return false; + } + state = State::kDone; + } else if (state == State::kNoTag) { + // We haven't seen a type_id yet. Append this data to message_data. + uint32_t length; + if (!input->ReadVarint32(&length)) return false; + if (static_cast<int32_t>(length) < 0) return false; + uint32_t size = static_cast<uint32_t>( + length + io::CodedOutputStream::VarintSize32(length)); + message_data.resize(size); + auto ptr = reinterpret_cast<uint8_t*>(&message_data[0]); + ptr = io::CodedOutputStream::WriteVarint32ToArray(length, ptr); + if (!input->ReadRaw(ptr, length)) return false; + state = State::kHasPayload; + } else { + if (!ms.SkipField(tag, input)) return false; + } + + break; + } + + case WireFormatLite::kMessageSetItemEndTag: { + return true; + } + + default: { + if (!ms.SkipField(tag, input)) return false; + } + } + } +} + +} // namespace internal +} // namespace protobuf +} // namespace google + +#include <google/protobuf/port_undef.inc> + +#endif // GOOGLE_PROTOBUF_WIRE_FORMAT_LITE_H__ diff --git a/toolkit/components/protobuf/src/google/protobuf/wrappers.pb.cc b/toolkit/components/protobuf/src/google/protobuf/wrappers.pb.cc new file mode 100644 index 0000000000..40ba60a492 --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/wrappers.pb.cc @@ -0,0 +1,1979 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: google/protobuf/wrappers.proto + +#include <google/protobuf/wrappers.pb.h> + +#include <algorithm> + +#include <google/protobuf/io/coded_stream.h> +#include <google/protobuf/extension_set.h> +#include <google/protobuf/wire_format_lite.h> +#include <google/protobuf/descriptor.h> +#include <google/protobuf/generated_message_reflection.h> +#include <google/protobuf/reflection_ops.h> +#include <google/protobuf/wire_format.h> +// @@protoc_insertion_point(includes) +#include <google/protobuf/port_def.inc> + +PROTOBUF_PRAGMA_INIT_SEG + +namespace _pb = ::PROTOBUF_NAMESPACE_ID; +namespace _pbi = _pb::internal; + +PROTOBUF_NAMESPACE_OPEN +PROTOBUF_CONSTEXPR DoubleValue::DoubleValue( + ::_pbi::ConstantInitialized): _impl_{ + /*decltype(_impl_.value_)*/0 + , /*decltype(_impl_._cached_size_)*/{}} {} +struct DoubleValueDefaultTypeInternal { + PROTOBUF_CONSTEXPR DoubleValueDefaultTypeInternal() + : _instance(::_pbi::ConstantInitialized{}) {} + ~DoubleValueDefaultTypeInternal() {} + union { + DoubleValue _instance; + }; +}; +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 DoubleValueDefaultTypeInternal _DoubleValue_default_instance_; +PROTOBUF_CONSTEXPR FloatValue::FloatValue( + ::_pbi::ConstantInitialized): _impl_{ + /*decltype(_impl_.value_)*/0 + , /*decltype(_impl_._cached_size_)*/{}} {} +struct FloatValueDefaultTypeInternal { + PROTOBUF_CONSTEXPR FloatValueDefaultTypeInternal() + : _instance(::_pbi::ConstantInitialized{}) {} + ~FloatValueDefaultTypeInternal() {} + union { + FloatValue _instance; + }; +}; +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 FloatValueDefaultTypeInternal _FloatValue_default_instance_; +PROTOBUF_CONSTEXPR Int64Value::Int64Value( + ::_pbi::ConstantInitialized): _impl_{ + /*decltype(_impl_.value_)*/int64_t{0} + , /*decltype(_impl_._cached_size_)*/{}} {} +struct Int64ValueDefaultTypeInternal { + PROTOBUF_CONSTEXPR Int64ValueDefaultTypeInternal() + : _instance(::_pbi::ConstantInitialized{}) {} + ~Int64ValueDefaultTypeInternal() {} + union { + Int64Value _instance; + }; +}; +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 Int64ValueDefaultTypeInternal _Int64Value_default_instance_; +PROTOBUF_CONSTEXPR UInt64Value::UInt64Value( + ::_pbi::ConstantInitialized): _impl_{ + /*decltype(_impl_.value_)*/uint64_t{0u} + , /*decltype(_impl_._cached_size_)*/{}} {} +struct UInt64ValueDefaultTypeInternal { + PROTOBUF_CONSTEXPR UInt64ValueDefaultTypeInternal() + : _instance(::_pbi::ConstantInitialized{}) {} + ~UInt64ValueDefaultTypeInternal() {} + union { + UInt64Value _instance; + }; +}; +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 UInt64ValueDefaultTypeInternal _UInt64Value_default_instance_; +PROTOBUF_CONSTEXPR Int32Value::Int32Value( + ::_pbi::ConstantInitialized): _impl_{ + /*decltype(_impl_.value_)*/0 + , /*decltype(_impl_._cached_size_)*/{}} {} +struct Int32ValueDefaultTypeInternal { + PROTOBUF_CONSTEXPR Int32ValueDefaultTypeInternal() + : _instance(::_pbi::ConstantInitialized{}) {} + ~Int32ValueDefaultTypeInternal() {} + union { + Int32Value _instance; + }; +}; +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 Int32ValueDefaultTypeInternal _Int32Value_default_instance_; +PROTOBUF_CONSTEXPR UInt32Value::UInt32Value( + ::_pbi::ConstantInitialized): _impl_{ + /*decltype(_impl_.value_)*/0u + , /*decltype(_impl_._cached_size_)*/{}} {} +struct UInt32ValueDefaultTypeInternal { + PROTOBUF_CONSTEXPR UInt32ValueDefaultTypeInternal() + : _instance(::_pbi::ConstantInitialized{}) {} + ~UInt32ValueDefaultTypeInternal() {} + union { + UInt32Value _instance; + }; +}; +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 UInt32ValueDefaultTypeInternal _UInt32Value_default_instance_; +PROTOBUF_CONSTEXPR BoolValue::BoolValue( + ::_pbi::ConstantInitialized): _impl_{ + /*decltype(_impl_.value_)*/false + , /*decltype(_impl_._cached_size_)*/{}} {} +struct BoolValueDefaultTypeInternal { + PROTOBUF_CONSTEXPR BoolValueDefaultTypeInternal() + : _instance(::_pbi::ConstantInitialized{}) {} + ~BoolValueDefaultTypeInternal() {} + union { + BoolValue _instance; + }; +}; +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 BoolValueDefaultTypeInternal _BoolValue_default_instance_; +PROTOBUF_CONSTEXPR StringValue::StringValue( + ::_pbi::ConstantInitialized): _impl_{ + /*decltype(_impl_.value_)*/{&::_pbi::fixed_address_empty_string, ::_pbi::ConstantInitialized{}} + , /*decltype(_impl_._cached_size_)*/{}} {} +struct StringValueDefaultTypeInternal { + PROTOBUF_CONSTEXPR StringValueDefaultTypeInternal() + : _instance(::_pbi::ConstantInitialized{}) {} + ~StringValueDefaultTypeInternal() {} + union { + StringValue _instance; + }; +}; +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 StringValueDefaultTypeInternal _StringValue_default_instance_; +PROTOBUF_CONSTEXPR BytesValue::BytesValue( + ::_pbi::ConstantInitialized): _impl_{ + /*decltype(_impl_.value_)*/{&::_pbi::fixed_address_empty_string, ::_pbi::ConstantInitialized{}} + , /*decltype(_impl_._cached_size_)*/{}} {} +struct BytesValueDefaultTypeInternal { + PROTOBUF_CONSTEXPR BytesValueDefaultTypeInternal() + : _instance(::_pbi::ConstantInitialized{}) {} + ~BytesValueDefaultTypeInternal() {} + union { + BytesValue _instance; + }; +}; +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 BytesValueDefaultTypeInternal _BytesValue_default_instance_; +PROTOBUF_NAMESPACE_CLOSE +static ::_pb::Metadata file_level_metadata_google_2fprotobuf_2fwrappers_2eproto[9]; +static constexpr ::_pb::EnumDescriptor const** file_level_enum_descriptors_google_2fprotobuf_2fwrappers_2eproto = nullptr; +static constexpr ::_pb::ServiceDescriptor const** file_level_service_descriptors_google_2fprotobuf_2fwrappers_2eproto = nullptr; + +const uint32_t TableStruct_google_2fprotobuf_2fwrappers_2eproto::offsets[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = { + ~0u, // no _has_bits_ + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::DoubleValue, _internal_metadata_), + ~0u, // no _extensions_ + ~0u, // no _oneof_case_ + ~0u, // no _weak_field_map_ + ~0u, // no _inlined_string_donated_ + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::DoubleValue, _impl_.value_), + ~0u, // no _has_bits_ + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::FloatValue, _internal_metadata_), + ~0u, // no _extensions_ + ~0u, // no _oneof_case_ + ~0u, // no _weak_field_map_ + ~0u, // no _inlined_string_donated_ + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::FloatValue, _impl_.value_), + ~0u, // no _has_bits_ + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Int64Value, _internal_metadata_), + ~0u, // no _extensions_ + ~0u, // no _oneof_case_ + ~0u, // no _weak_field_map_ + ~0u, // no _inlined_string_donated_ + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Int64Value, _impl_.value_), + ~0u, // no _has_bits_ + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::UInt64Value, _internal_metadata_), + ~0u, // no _extensions_ + ~0u, // no _oneof_case_ + ~0u, // no _weak_field_map_ + ~0u, // no _inlined_string_donated_ + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::UInt64Value, _impl_.value_), + ~0u, // no _has_bits_ + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Int32Value, _internal_metadata_), + ~0u, // no _extensions_ + ~0u, // no _oneof_case_ + ~0u, // no _weak_field_map_ + ~0u, // no _inlined_string_donated_ + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Int32Value, _impl_.value_), + ~0u, // no _has_bits_ + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::UInt32Value, _internal_metadata_), + ~0u, // no _extensions_ + ~0u, // no _oneof_case_ + ~0u, // no _weak_field_map_ + ~0u, // no _inlined_string_donated_ + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::UInt32Value, _impl_.value_), + ~0u, // no _has_bits_ + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::BoolValue, _internal_metadata_), + ~0u, // no _extensions_ + ~0u, // no _oneof_case_ + ~0u, // no _weak_field_map_ + ~0u, // no _inlined_string_donated_ + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::BoolValue, _impl_.value_), + ~0u, // no _has_bits_ + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::StringValue, _internal_metadata_), + ~0u, // no _extensions_ + ~0u, // no _oneof_case_ + ~0u, // no _weak_field_map_ + ~0u, // no _inlined_string_donated_ + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::StringValue, _impl_.value_), + ~0u, // no _has_bits_ + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::BytesValue, _internal_metadata_), + ~0u, // no _extensions_ + ~0u, // no _oneof_case_ + ~0u, // no _weak_field_map_ + ~0u, // no _inlined_string_donated_ + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::BytesValue, _impl_.value_), +}; +static const ::_pbi::MigrationSchema schemas[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = { + { 0, -1, -1, sizeof(::PROTOBUF_NAMESPACE_ID::DoubleValue)}, + { 7, -1, -1, sizeof(::PROTOBUF_NAMESPACE_ID::FloatValue)}, + { 14, -1, -1, sizeof(::PROTOBUF_NAMESPACE_ID::Int64Value)}, + { 21, -1, -1, sizeof(::PROTOBUF_NAMESPACE_ID::UInt64Value)}, + { 28, -1, -1, sizeof(::PROTOBUF_NAMESPACE_ID::Int32Value)}, + { 35, -1, -1, sizeof(::PROTOBUF_NAMESPACE_ID::UInt32Value)}, + { 42, -1, -1, sizeof(::PROTOBUF_NAMESPACE_ID::BoolValue)}, + { 49, -1, -1, sizeof(::PROTOBUF_NAMESPACE_ID::StringValue)}, + { 56, -1, -1, sizeof(::PROTOBUF_NAMESPACE_ID::BytesValue)}, +}; + +static const ::_pb::Message* const file_default_instances[] = { + &::PROTOBUF_NAMESPACE_ID::_DoubleValue_default_instance_._instance, + &::PROTOBUF_NAMESPACE_ID::_FloatValue_default_instance_._instance, + &::PROTOBUF_NAMESPACE_ID::_Int64Value_default_instance_._instance, + &::PROTOBUF_NAMESPACE_ID::_UInt64Value_default_instance_._instance, + &::PROTOBUF_NAMESPACE_ID::_Int32Value_default_instance_._instance, + &::PROTOBUF_NAMESPACE_ID::_UInt32Value_default_instance_._instance, + &::PROTOBUF_NAMESPACE_ID::_BoolValue_default_instance_._instance, + &::PROTOBUF_NAMESPACE_ID::_StringValue_default_instance_._instance, + &::PROTOBUF_NAMESPACE_ID::_BytesValue_default_instance_._instance, +}; + +const char descriptor_table_protodef_google_2fprotobuf_2fwrappers_2eproto[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = + "\n\036google/protobuf/wrappers.proto\022\017google" + ".protobuf\"\034\n\013DoubleValue\022\r\n\005value\030\001 \001(\001\"" + "\033\n\nFloatValue\022\r\n\005value\030\001 \001(\002\"\033\n\nInt64Val" + "ue\022\r\n\005value\030\001 \001(\003\"\034\n\013UInt64Value\022\r\n\005valu" + "e\030\001 \001(\004\"\033\n\nInt32Value\022\r\n\005value\030\001 \001(\005\"\034\n\013" + "UInt32Value\022\r\n\005value\030\001 \001(\r\"\032\n\tBoolValue\022" + "\r\n\005value\030\001 \001(\010\"\034\n\013StringValue\022\r\n\005value\030\001" + " \001(\t\"\033\n\nBytesValue\022\r\n\005value\030\001 \001(\014B\203\001\n\023co" + "m.google.protobufB\rWrappersProtoP\001Z1goog" + "le.golang.org/protobuf/types/known/wrapp" + "erspb\370\001\001\242\002\003GPB\252\002\036Google.Protobuf.WellKno" + "wnTypesb\006proto3" + ; +static ::_pbi::once_flag descriptor_table_google_2fprotobuf_2fwrappers_2eproto_once; +const ::_pbi::DescriptorTable descriptor_table_google_2fprotobuf_2fwrappers_2eproto = { + false, false, 455, descriptor_table_protodef_google_2fprotobuf_2fwrappers_2eproto, + "google/protobuf/wrappers.proto", + &descriptor_table_google_2fprotobuf_2fwrappers_2eproto_once, nullptr, 0, 9, + schemas, file_default_instances, TableStruct_google_2fprotobuf_2fwrappers_2eproto::offsets, + file_level_metadata_google_2fprotobuf_2fwrappers_2eproto, file_level_enum_descriptors_google_2fprotobuf_2fwrappers_2eproto, + file_level_service_descriptors_google_2fprotobuf_2fwrappers_2eproto, +}; +PROTOBUF_ATTRIBUTE_WEAK const ::_pbi::DescriptorTable* descriptor_table_google_2fprotobuf_2fwrappers_2eproto_getter() { + return &descriptor_table_google_2fprotobuf_2fwrappers_2eproto; +} + +// Force running AddDescriptors() at dynamic initialization time. +PROTOBUF_ATTRIBUTE_INIT_PRIORITY2 static ::_pbi::AddDescriptorsRunner dynamic_init_dummy_google_2fprotobuf_2fwrappers_2eproto(&descriptor_table_google_2fprotobuf_2fwrappers_2eproto); +PROTOBUF_NAMESPACE_OPEN + +// =================================================================== + +class DoubleValue::_Internal { + public: +}; + +DoubleValue::DoubleValue(::PROTOBUF_NAMESPACE_ID::Arena* arena, + bool is_message_owned) + : ::PROTOBUF_NAMESPACE_ID::Message(arena, is_message_owned) { + SharedCtor(arena, is_message_owned); + // @@protoc_insertion_point(arena_constructor:google.protobuf.DoubleValue) +} +DoubleValue::DoubleValue(const DoubleValue& from) + : ::PROTOBUF_NAMESPACE_ID::Message() { + DoubleValue* const _this = this; (void)_this; + new (&_impl_) Impl_{ + decltype(_impl_.value_){} + , /*decltype(_impl_._cached_size_)*/{}}; + + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); + _this->_impl_.value_ = from._impl_.value_; + // @@protoc_insertion_point(copy_constructor:google.protobuf.DoubleValue) +} + +inline void DoubleValue::SharedCtor( + ::_pb::Arena* arena, bool is_message_owned) { + (void)arena; + (void)is_message_owned; + new (&_impl_) Impl_{ + decltype(_impl_.value_){0} + , /*decltype(_impl_._cached_size_)*/{} + }; +} + +DoubleValue::~DoubleValue() { + // @@protoc_insertion_point(destructor:google.protobuf.DoubleValue) + if (auto *arena = _internal_metadata_.DeleteReturnArena<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>()) { + (void)arena; + return; + } + SharedDtor(); +} + +inline void DoubleValue::SharedDtor() { + GOOGLE_DCHECK(GetArenaForAllocation() == nullptr); +} + +void DoubleValue::SetCachedSize(int size) const { + _impl_._cached_size_.Set(size); +} + +void DoubleValue::Clear() { +// @@protoc_insertion_point(message_clear_start:google.protobuf.DoubleValue) + uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + _impl_.value_ = 0; + _internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); +} + +const char* DoubleValue::_InternalParse(const char* ptr, ::_pbi::ParseContext* ctx) { +#define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure + while (!ctx->Done(&ptr)) { + uint32_t tag; + ptr = ::_pbi::ReadTag(ptr, &tag); + switch (tag >> 3) { + // double value = 1; + case 1: + if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 9)) { + _impl_.value_ = ::PROTOBUF_NAMESPACE_ID::internal::UnalignedLoad<double>(ptr); + ptr += sizeof(double); + } else + goto handle_unusual; + continue; + default: + goto handle_unusual; + } // switch + handle_unusual: + if ((tag == 0) || ((tag & 7) == 4)) { + CHK_(ptr); + ctx->SetLastTag(tag); + goto message_done; + } + ptr = UnknownFieldParse( + tag, + _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(), + ptr, ctx); + CHK_(ptr != nullptr); + } // while +message_done: + return ptr; +failure: + ptr = nullptr; + goto message_done; +#undef CHK_ +} + +uint8_t* DoubleValue::_InternalSerialize( + uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const { + // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.DoubleValue) + uint32_t cached_has_bits = 0; + (void) cached_has_bits; + + // double value = 1; + static_assert(sizeof(uint64_t) == sizeof(double), "Code assumes uint64_t and double are the same size."); + double tmp_value = this->_internal_value(); + uint64_t raw_value; + memcpy(&raw_value, &tmp_value, sizeof(tmp_value)); + if (raw_value != 0) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteDoubleToArray(1, this->_internal_value(), target); + } + + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + target = ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( + _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.DoubleValue) + return target; +} + +size_t DoubleValue::ByteSizeLong() const { +// @@protoc_insertion_point(message_byte_size_start:google.protobuf.DoubleValue) + size_t total_size = 0; + + uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + // double value = 1; + static_assert(sizeof(uint64_t) == sizeof(double), "Code assumes uint64_t and double are the same size."); + double tmp_value = this->_internal_value(); + uint64_t raw_value; + memcpy(&raw_value, &tmp_value, sizeof(tmp_value)); + if (raw_value != 0) { + total_size += 1 + 8; + } + + return MaybeComputeUnknownFieldsSize(total_size, &_impl_._cached_size_); +} + +const ::PROTOBUF_NAMESPACE_ID::Message::ClassData DoubleValue::_class_data_ = { + ::PROTOBUF_NAMESPACE_ID::Message::CopyWithSourceCheck, + DoubleValue::MergeImpl +}; +const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*DoubleValue::GetClassData() const { return &_class_data_; } + + +void DoubleValue::MergeImpl(::PROTOBUF_NAMESPACE_ID::Message& to_msg, const ::PROTOBUF_NAMESPACE_ID::Message& from_msg) { + auto* const _this = static_cast<DoubleValue*>(&to_msg); + auto& from = static_cast<const DoubleValue&>(from_msg); + // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.DoubleValue) + GOOGLE_DCHECK_NE(&from, _this); + uint32_t cached_has_bits = 0; + (void) cached_has_bits; + + static_assert(sizeof(uint64_t) == sizeof(double), "Code assumes uint64_t and double are the same size."); + double tmp_value = from._internal_value(); + uint64_t raw_value; + memcpy(&raw_value, &tmp_value, sizeof(tmp_value)); + if (raw_value != 0) { + _this->_internal_set_value(from._internal_value()); + } + _this->_internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); +} + +void DoubleValue::CopyFrom(const DoubleValue& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.DoubleValue) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool DoubleValue::IsInitialized() const { + return true; +} + +void DoubleValue::InternalSwap(DoubleValue* other) { + using std::swap; + _internal_metadata_.InternalSwap(&other->_internal_metadata_); + swap(_impl_.value_, other->_impl_.value_); +} + +::PROTOBUF_NAMESPACE_ID::Metadata DoubleValue::GetMetadata() const { + return ::_pbi::AssignDescriptors( + &descriptor_table_google_2fprotobuf_2fwrappers_2eproto_getter, &descriptor_table_google_2fprotobuf_2fwrappers_2eproto_once, + file_level_metadata_google_2fprotobuf_2fwrappers_2eproto[0]); +} + +// =================================================================== + +class FloatValue::_Internal { + public: +}; + +FloatValue::FloatValue(::PROTOBUF_NAMESPACE_ID::Arena* arena, + bool is_message_owned) + : ::PROTOBUF_NAMESPACE_ID::Message(arena, is_message_owned) { + SharedCtor(arena, is_message_owned); + // @@protoc_insertion_point(arena_constructor:google.protobuf.FloatValue) +} +FloatValue::FloatValue(const FloatValue& from) + : ::PROTOBUF_NAMESPACE_ID::Message() { + FloatValue* const _this = this; (void)_this; + new (&_impl_) Impl_{ + decltype(_impl_.value_){} + , /*decltype(_impl_._cached_size_)*/{}}; + + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); + _this->_impl_.value_ = from._impl_.value_; + // @@protoc_insertion_point(copy_constructor:google.protobuf.FloatValue) +} + +inline void FloatValue::SharedCtor( + ::_pb::Arena* arena, bool is_message_owned) { + (void)arena; + (void)is_message_owned; + new (&_impl_) Impl_{ + decltype(_impl_.value_){0} + , /*decltype(_impl_._cached_size_)*/{} + }; +} + +FloatValue::~FloatValue() { + // @@protoc_insertion_point(destructor:google.protobuf.FloatValue) + if (auto *arena = _internal_metadata_.DeleteReturnArena<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>()) { + (void)arena; + return; + } + SharedDtor(); +} + +inline void FloatValue::SharedDtor() { + GOOGLE_DCHECK(GetArenaForAllocation() == nullptr); +} + +void FloatValue::SetCachedSize(int size) const { + _impl_._cached_size_.Set(size); +} + +void FloatValue::Clear() { +// @@protoc_insertion_point(message_clear_start:google.protobuf.FloatValue) + uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + _impl_.value_ = 0; + _internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); +} + +const char* FloatValue::_InternalParse(const char* ptr, ::_pbi::ParseContext* ctx) { +#define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure + while (!ctx->Done(&ptr)) { + uint32_t tag; + ptr = ::_pbi::ReadTag(ptr, &tag); + switch (tag >> 3) { + // float value = 1; + case 1: + if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 13)) { + _impl_.value_ = ::PROTOBUF_NAMESPACE_ID::internal::UnalignedLoad<float>(ptr); + ptr += sizeof(float); + } else + goto handle_unusual; + continue; + default: + goto handle_unusual; + } // switch + handle_unusual: + if ((tag == 0) || ((tag & 7) == 4)) { + CHK_(ptr); + ctx->SetLastTag(tag); + goto message_done; + } + ptr = UnknownFieldParse( + tag, + _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(), + ptr, ctx); + CHK_(ptr != nullptr); + } // while +message_done: + return ptr; +failure: + ptr = nullptr; + goto message_done; +#undef CHK_ +} + +uint8_t* FloatValue::_InternalSerialize( + uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const { + // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.FloatValue) + uint32_t cached_has_bits = 0; + (void) cached_has_bits; + + // float value = 1; + static_assert(sizeof(uint32_t) == sizeof(float), "Code assumes uint32_t and float are the same size."); + float tmp_value = this->_internal_value(); + uint32_t raw_value; + memcpy(&raw_value, &tmp_value, sizeof(tmp_value)); + if (raw_value != 0) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteFloatToArray(1, this->_internal_value(), target); + } + + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + target = ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( + _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.FloatValue) + return target; +} + +size_t FloatValue::ByteSizeLong() const { +// @@protoc_insertion_point(message_byte_size_start:google.protobuf.FloatValue) + size_t total_size = 0; + + uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + // float value = 1; + static_assert(sizeof(uint32_t) == sizeof(float), "Code assumes uint32_t and float are the same size."); + float tmp_value = this->_internal_value(); + uint32_t raw_value; + memcpy(&raw_value, &tmp_value, sizeof(tmp_value)); + if (raw_value != 0) { + total_size += 1 + 4; + } + + return MaybeComputeUnknownFieldsSize(total_size, &_impl_._cached_size_); +} + +const ::PROTOBUF_NAMESPACE_ID::Message::ClassData FloatValue::_class_data_ = { + ::PROTOBUF_NAMESPACE_ID::Message::CopyWithSourceCheck, + FloatValue::MergeImpl +}; +const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*FloatValue::GetClassData() const { return &_class_data_; } + + +void FloatValue::MergeImpl(::PROTOBUF_NAMESPACE_ID::Message& to_msg, const ::PROTOBUF_NAMESPACE_ID::Message& from_msg) { + auto* const _this = static_cast<FloatValue*>(&to_msg); + auto& from = static_cast<const FloatValue&>(from_msg); + // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.FloatValue) + GOOGLE_DCHECK_NE(&from, _this); + uint32_t cached_has_bits = 0; + (void) cached_has_bits; + + static_assert(sizeof(uint32_t) == sizeof(float), "Code assumes uint32_t and float are the same size."); + float tmp_value = from._internal_value(); + uint32_t raw_value; + memcpy(&raw_value, &tmp_value, sizeof(tmp_value)); + if (raw_value != 0) { + _this->_internal_set_value(from._internal_value()); + } + _this->_internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); +} + +void FloatValue::CopyFrom(const FloatValue& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.FloatValue) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool FloatValue::IsInitialized() const { + return true; +} + +void FloatValue::InternalSwap(FloatValue* other) { + using std::swap; + _internal_metadata_.InternalSwap(&other->_internal_metadata_); + swap(_impl_.value_, other->_impl_.value_); +} + +::PROTOBUF_NAMESPACE_ID::Metadata FloatValue::GetMetadata() const { + return ::_pbi::AssignDescriptors( + &descriptor_table_google_2fprotobuf_2fwrappers_2eproto_getter, &descriptor_table_google_2fprotobuf_2fwrappers_2eproto_once, + file_level_metadata_google_2fprotobuf_2fwrappers_2eproto[1]); +} + +// =================================================================== + +class Int64Value::_Internal { + public: +}; + +Int64Value::Int64Value(::PROTOBUF_NAMESPACE_ID::Arena* arena, + bool is_message_owned) + : ::PROTOBUF_NAMESPACE_ID::Message(arena, is_message_owned) { + SharedCtor(arena, is_message_owned); + // @@protoc_insertion_point(arena_constructor:google.protobuf.Int64Value) +} +Int64Value::Int64Value(const Int64Value& from) + : ::PROTOBUF_NAMESPACE_ID::Message() { + Int64Value* const _this = this; (void)_this; + new (&_impl_) Impl_{ + decltype(_impl_.value_){} + , /*decltype(_impl_._cached_size_)*/{}}; + + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); + _this->_impl_.value_ = from._impl_.value_; + // @@protoc_insertion_point(copy_constructor:google.protobuf.Int64Value) +} + +inline void Int64Value::SharedCtor( + ::_pb::Arena* arena, bool is_message_owned) { + (void)arena; + (void)is_message_owned; + new (&_impl_) Impl_{ + decltype(_impl_.value_){int64_t{0}} + , /*decltype(_impl_._cached_size_)*/{} + }; +} + +Int64Value::~Int64Value() { + // @@protoc_insertion_point(destructor:google.protobuf.Int64Value) + if (auto *arena = _internal_metadata_.DeleteReturnArena<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>()) { + (void)arena; + return; + } + SharedDtor(); +} + +inline void Int64Value::SharedDtor() { + GOOGLE_DCHECK(GetArenaForAllocation() == nullptr); +} + +void Int64Value::SetCachedSize(int size) const { + _impl_._cached_size_.Set(size); +} + +void Int64Value::Clear() { +// @@protoc_insertion_point(message_clear_start:google.protobuf.Int64Value) + uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + _impl_.value_ = int64_t{0}; + _internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); +} + +const char* Int64Value::_InternalParse(const char* ptr, ::_pbi::ParseContext* ctx) { +#define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure + while (!ctx->Done(&ptr)) { + uint32_t tag; + ptr = ::_pbi::ReadTag(ptr, &tag); + switch (tag >> 3) { + // int64 value = 1; + case 1: + if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 8)) { + _impl_.value_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr); + CHK_(ptr); + } else + goto handle_unusual; + continue; + default: + goto handle_unusual; + } // switch + handle_unusual: + if ((tag == 0) || ((tag & 7) == 4)) { + CHK_(ptr); + ctx->SetLastTag(tag); + goto message_done; + } + ptr = UnknownFieldParse( + tag, + _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(), + ptr, ctx); + CHK_(ptr != nullptr); + } // while +message_done: + return ptr; +failure: + ptr = nullptr; + goto message_done; +#undef CHK_ +} + +uint8_t* Int64Value::_InternalSerialize( + uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const { + // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.Int64Value) + uint32_t cached_has_bits = 0; + (void) cached_has_bits; + + // int64 value = 1; + if (this->_internal_value() != 0) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteInt64ToArray(1, this->_internal_value(), target); + } + + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + target = ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( + _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.Int64Value) + return target; +} + +size_t Int64Value::ByteSizeLong() const { +// @@protoc_insertion_point(message_byte_size_start:google.protobuf.Int64Value) + size_t total_size = 0; + + uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + // int64 value = 1; + if (this->_internal_value() != 0) { + total_size += ::_pbi::WireFormatLite::Int64SizePlusOne(this->_internal_value()); + } + + return MaybeComputeUnknownFieldsSize(total_size, &_impl_._cached_size_); +} + +const ::PROTOBUF_NAMESPACE_ID::Message::ClassData Int64Value::_class_data_ = { + ::PROTOBUF_NAMESPACE_ID::Message::CopyWithSourceCheck, + Int64Value::MergeImpl +}; +const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*Int64Value::GetClassData() const { return &_class_data_; } + + +void Int64Value::MergeImpl(::PROTOBUF_NAMESPACE_ID::Message& to_msg, const ::PROTOBUF_NAMESPACE_ID::Message& from_msg) { + auto* const _this = static_cast<Int64Value*>(&to_msg); + auto& from = static_cast<const Int64Value&>(from_msg); + // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.Int64Value) + GOOGLE_DCHECK_NE(&from, _this); + uint32_t cached_has_bits = 0; + (void) cached_has_bits; + + if (from._internal_value() != 0) { + _this->_internal_set_value(from._internal_value()); + } + _this->_internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); +} + +void Int64Value::CopyFrom(const Int64Value& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.Int64Value) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool Int64Value::IsInitialized() const { + return true; +} + +void Int64Value::InternalSwap(Int64Value* other) { + using std::swap; + _internal_metadata_.InternalSwap(&other->_internal_metadata_); + swap(_impl_.value_, other->_impl_.value_); +} + +::PROTOBUF_NAMESPACE_ID::Metadata Int64Value::GetMetadata() const { + return ::_pbi::AssignDescriptors( + &descriptor_table_google_2fprotobuf_2fwrappers_2eproto_getter, &descriptor_table_google_2fprotobuf_2fwrappers_2eproto_once, + file_level_metadata_google_2fprotobuf_2fwrappers_2eproto[2]); +} + +// =================================================================== + +class UInt64Value::_Internal { + public: +}; + +UInt64Value::UInt64Value(::PROTOBUF_NAMESPACE_ID::Arena* arena, + bool is_message_owned) + : ::PROTOBUF_NAMESPACE_ID::Message(arena, is_message_owned) { + SharedCtor(arena, is_message_owned); + // @@protoc_insertion_point(arena_constructor:google.protobuf.UInt64Value) +} +UInt64Value::UInt64Value(const UInt64Value& from) + : ::PROTOBUF_NAMESPACE_ID::Message() { + UInt64Value* const _this = this; (void)_this; + new (&_impl_) Impl_{ + decltype(_impl_.value_){} + , /*decltype(_impl_._cached_size_)*/{}}; + + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); + _this->_impl_.value_ = from._impl_.value_; + // @@protoc_insertion_point(copy_constructor:google.protobuf.UInt64Value) +} + +inline void UInt64Value::SharedCtor( + ::_pb::Arena* arena, bool is_message_owned) { + (void)arena; + (void)is_message_owned; + new (&_impl_) Impl_{ + decltype(_impl_.value_){uint64_t{0u}} + , /*decltype(_impl_._cached_size_)*/{} + }; +} + +UInt64Value::~UInt64Value() { + // @@protoc_insertion_point(destructor:google.protobuf.UInt64Value) + if (auto *arena = _internal_metadata_.DeleteReturnArena<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>()) { + (void)arena; + return; + } + SharedDtor(); +} + +inline void UInt64Value::SharedDtor() { + GOOGLE_DCHECK(GetArenaForAllocation() == nullptr); +} + +void UInt64Value::SetCachedSize(int size) const { + _impl_._cached_size_.Set(size); +} + +void UInt64Value::Clear() { +// @@protoc_insertion_point(message_clear_start:google.protobuf.UInt64Value) + uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + _impl_.value_ = uint64_t{0u}; + _internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); +} + +const char* UInt64Value::_InternalParse(const char* ptr, ::_pbi::ParseContext* ctx) { +#define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure + while (!ctx->Done(&ptr)) { + uint32_t tag; + ptr = ::_pbi::ReadTag(ptr, &tag); + switch (tag >> 3) { + // uint64 value = 1; + case 1: + if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 8)) { + _impl_.value_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr); + CHK_(ptr); + } else + goto handle_unusual; + continue; + default: + goto handle_unusual; + } // switch + handle_unusual: + if ((tag == 0) || ((tag & 7) == 4)) { + CHK_(ptr); + ctx->SetLastTag(tag); + goto message_done; + } + ptr = UnknownFieldParse( + tag, + _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(), + ptr, ctx); + CHK_(ptr != nullptr); + } // while +message_done: + return ptr; +failure: + ptr = nullptr; + goto message_done; +#undef CHK_ +} + +uint8_t* UInt64Value::_InternalSerialize( + uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const { + // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.UInt64Value) + uint32_t cached_has_bits = 0; + (void) cached_has_bits; + + // uint64 value = 1; + if (this->_internal_value() != 0) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteUInt64ToArray(1, this->_internal_value(), target); + } + + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + target = ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( + _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.UInt64Value) + return target; +} + +size_t UInt64Value::ByteSizeLong() const { +// @@protoc_insertion_point(message_byte_size_start:google.protobuf.UInt64Value) + size_t total_size = 0; + + uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + // uint64 value = 1; + if (this->_internal_value() != 0) { + total_size += ::_pbi::WireFormatLite::UInt64SizePlusOne(this->_internal_value()); + } + + return MaybeComputeUnknownFieldsSize(total_size, &_impl_._cached_size_); +} + +const ::PROTOBUF_NAMESPACE_ID::Message::ClassData UInt64Value::_class_data_ = { + ::PROTOBUF_NAMESPACE_ID::Message::CopyWithSourceCheck, + UInt64Value::MergeImpl +}; +const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*UInt64Value::GetClassData() const { return &_class_data_; } + + +void UInt64Value::MergeImpl(::PROTOBUF_NAMESPACE_ID::Message& to_msg, const ::PROTOBUF_NAMESPACE_ID::Message& from_msg) { + auto* const _this = static_cast<UInt64Value*>(&to_msg); + auto& from = static_cast<const UInt64Value&>(from_msg); + // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.UInt64Value) + GOOGLE_DCHECK_NE(&from, _this); + uint32_t cached_has_bits = 0; + (void) cached_has_bits; + + if (from._internal_value() != 0) { + _this->_internal_set_value(from._internal_value()); + } + _this->_internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); +} + +void UInt64Value::CopyFrom(const UInt64Value& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.UInt64Value) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool UInt64Value::IsInitialized() const { + return true; +} + +void UInt64Value::InternalSwap(UInt64Value* other) { + using std::swap; + _internal_metadata_.InternalSwap(&other->_internal_metadata_); + swap(_impl_.value_, other->_impl_.value_); +} + +::PROTOBUF_NAMESPACE_ID::Metadata UInt64Value::GetMetadata() const { + return ::_pbi::AssignDescriptors( + &descriptor_table_google_2fprotobuf_2fwrappers_2eproto_getter, &descriptor_table_google_2fprotobuf_2fwrappers_2eproto_once, + file_level_metadata_google_2fprotobuf_2fwrappers_2eproto[3]); +} + +// =================================================================== + +class Int32Value::_Internal { + public: +}; + +Int32Value::Int32Value(::PROTOBUF_NAMESPACE_ID::Arena* arena, + bool is_message_owned) + : ::PROTOBUF_NAMESPACE_ID::Message(arena, is_message_owned) { + SharedCtor(arena, is_message_owned); + // @@protoc_insertion_point(arena_constructor:google.protobuf.Int32Value) +} +Int32Value::Int32Value(const Int32Value& from) + : ::PROTOBUF_NAMESPACE_ID::Message() { + Int32Value* const _this = this; (void)_this; + new (&_impl_) Impl_{ + decltype(_impl_.value_){} + , /*decltype(_impl_._cached_size_)*/{}}; + + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); + _this->_impl_.value_ = from._impl_.value_; + // @@protoc_insertion_point(copy_constructor:google.protobuf.Int32Value) +} + +inline void Int32Value::SharedCtor( + ::_pb::Arena* arena, bool is_message_owned) { + (void)arena; + (void)is_message_owned; + new (&_impl_) Impl_{ + decltype(_impl_.value_){0} + , /*decltype(_impl_._cached_size_)*/{} + }; +} + +Int32Value::~Int32Value() { + // @@protoc_insertion_point(destructor:google.protobuf.Int32Value) + if (auto *arena = _internal_metadata_.DeleteReturnArena<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>()) { + (void)arena; + return; + } + SharedDtor(); +} + +inline void Int32Value::SharedDtor() { + GOOGLE_DCHECK(GetArenaForAllocation() == nullptr); +} + +void Int32Value::SetCachedSize(int size) const { + _impl_._cached_size_.Set(size); +} + +void Int32Value::Clear() { +// @@protoc_insertion_point(message_clear_start:google.protobuf.Int32Value) + uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + _impl_.value_ = 0; + _internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); +} + +const char* Int32Value::_InternalParse(const char* ptr, ::_pbi::ParseContext* ctx) { +#define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure + while (!ctx->Done(&ptr)) { + uint32_t tag; + ptr = ::_pbi::ReadTag(ptr, &tag); + switch (tag >> 3) { + // int32 value = 1; + case 1: + if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 8)) { + _impl_.value_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint32(&ptr); + CHK_(ptr); + } else + goto handle_unusual; + continue; + default: + goto handle_unusual; + } // switch + handle_unusual: + if ((tag == 0) || ((tag & 7) == 4)) { + CHK_(ptr); + ctx->SetLastTag(tag); + goto message_done; + } + ptr = UnknownFieldParse( + tag, + _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(), + ptr, ctx); + CHK_(ptr != nullptr); + } // while +message_done: + return ptr; +failure: + ptr = nullptr; + goto message_done; +#undef CHK_ +} + +uint8_t* Int32Value::_InternalSerialize( + uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const { + // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.Int32Value) + uint32_t cached_has_bits = 0; + (void) cached_has_bits; + + // int32 value = 1; + if (this->_internal_value() != 0) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteInt32ToArray(1, this->_internal_value(), target); + } + + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + target = ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( + _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.Int32Value) + return target; +} + +size_t Int32Value::ByteSizeLong() const { +// @@protoc_insertion_point(message_byte_size_start:google.protobuf.Int32Value) + size_t total_size = 0; + + uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + // int32 value = 1; + if (this->_internal_value() != 0) { + total_size += ::_pbi::WireFormatLite::Int32SizePlusOne(this->_internal_value()); + } + + return MaybeComputeUnknownFieldsSize(total_size, &_impl_._cached_size_); +} + +const ::PROTOBUF_NAMESPACE_ID::Message::ClassData Int32Value::_class_data_ = { + ::PROTOBUF_NAMESPACE_ID::Message::CopyWithSourceCheck, + Int32Value::MergeImpl +}; +const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*Int32Value::GetClassData() const { return &_class_data_; } + + +void Int32Value::MergeImpl(::PROTOBUF_NAMESPACE_ID::Message& to_msg, const ::PROTOBUF_NAMESPACE_ID::Message& from_msg) { + auto* const _this = static_cast<Int32Value*>(&to_msg); + auto& from = static_cast<const Int32Value&>(from_msg); + // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.Int32Value) + GOOGLE_DCHECK_NE(&from, _this); + uint32_t cached_has_bits = 0; + (void) cached_has_bits; + + if (from._internal_value() != 0) { + _this->_internal_set_value(from._internal_value()); + } + _this->_internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); +} + +void Int32Value::CopyFrom(const Int32Value& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.Int32Value) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool Int32Value::IsInitialized() const { + return true; +} + +void Int32Value::InternalSwap(Int32Value* other) { + using std::swap; + _internal_metadata_.InternalSwap(&other->_internal_metadata_); + swap(_impl_.value_, other->_impl_.value_); +} + +::PROTOBUF_NAMESPACE_ID::Metadata Int32Value::GetMetadata() const { + return ::_pbi::AssignDescriptors( + &descriptor_table_google_2fprotobuf_2fwrappers_2eproto_getter, &descriptor_table_google_2fprotobuf_2fwrappers_2eproto_once, + file_level_metadata_google_2fprotobuf_2fwrappers_2eproto[4]); +} + +// =================================================================== + +class UInt32Value::_Internal { + public: +}; + +UInt32Value::UInt32Value(::PROTOBUF_NAMESPACE_ID::Arena* arena, + bool is_message_owned) + : ::PROTOBUF_NAMESPACE_ID::Message(arena, is_message_owned) { + SharedCtor(arena, is_message_owned); + // @@protoc_insertion_point(arena_constructor:google.protobuf.UInt32Value) +} +UInt32Value::UInt32Value(const UInt32Value& from) + : ::PROTOBUF_NAMESPACE_ID::Message() { + UInt32Value* const _this = this; (void)_this; + new (&_impl_) Impl_{ + decltype(_impl_.value_){} + , /*decltype(_impl_._cached_size_)*/{}}; + + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); + _this->_impl_.value_ = from._impl_.value_; + // @@protoc_insertion_point(copy_constructor:google.protobuf.UInt32Value) +} + +inline void UInt32Value::SharedCtor( + ::_pb::Arena* arena, bool is_message_owned) { + (void)arena; + (void)is_message_owned; + new (&_impl_) Impl_{ + decltype(_impl_.value_){0u} + , /*decltype(_impl_._cached_size_)*/{} + }; +} + +UInt32Value::~UInt32Value() { + // @@protoc_insertion_point(destructor:google.protobuf.UInt32Value) + if (auto *arena = _internal_metadata_.DeleteReturnArena<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>()) { + (void)arena; + return; + } + SharedDtor(); +} + +inline void UInt32Value::SharedDtor() { + GOOGLE_DCHECK(GetArenaForAllocation() == nullptr); +} + +void UInt32Value::SetCachedSize(int size) const { + _impl_._cached_size_.Set(size); +} + +void UInt32Value::Clear() { +// @@protoc_insertion_point(message_clear_start:google.protobuf.UInt32Value) + uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + _impl_.value_ = 0u; + _internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); +} + +const char* UInt32Value::_InternalParse(const char* ptr, ::_pbi::ParseContext* ctx) { +#define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure + while (!ctx->Done(&ptr)) { + uint32_t tag; + ptr = ::_pbi::ReadTag(ptr, &tag); + switch (tag >> 3) { + // uint32 value = 1; + case 1: + if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 8)) { + _impl_.value_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint32(&ptr); + CHK_(ptr); + } else + goto handle_unusual; + continue; + default: + goto handle_unusual; + } // switch + handle_unusual: + if ((tag == 0) || ((tag & 7) == 4)) { + CHK_(ptr); + ctx->SetLastTag(tag); + goto message_done; + } + ptr = UnknownFieldParse( + tag, + _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(), + ptr, ctx); + CHK_(ptr != nullptr); + } // while +message_done: + return ptr; +failure: + ptr = nullptr; + goto message_done; +#undef CHK_ +} + +uint8_t* UInt32Value::_InternalSerialize( + uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const { + // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.UInt32Value) + uint32_t cached_has_bits = 0; + (void) cached_has_bits; + + // uint32 value = 1; + if (this->_internal_value() != 0) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteUInt32ToArray(1, this->_internal_value(), target); + } + + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + target = ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( + _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.UInt32Value) + return target; +} + +size_t UInt32Value::ByteSizeLong() const { +// @@protoc_insertion_point(message_byte_size_start:google.protobuf.UInt32Value) + size_t total_size = 0; + + uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + // uint32 value = 1; + if (this->_internal_value() != 0) { + total_size += ::_pbi::WireFormatLite::UInt32SizePlusOne(this->_internal_value()); + } + + return MaybeComputeUnknownFieldsSize(total_size, &_impl_._cached_size_); +} + +const ::PROTOBUF_NAMESPACE_ID::Message::ClassData UInt32Value::_class_data_ = { + ::PROTOBUF_NAMESPACE_ID::Message::CopyWithSourceCheck, + UInt32Value::MergeImpl +}; +const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*UInt32Value::GetClassData() const { return &_class_data_; } + + +void UInt32Value::MergeImpl(::PROTOBUF_NAMESPACE_ID::Message& to_msg, const ::PROTOBUF_NAMESPACE_ID::Message& from_msg) { + auto* const _this = static_cast<UInt32Value*>(&to_msg); + auto& from = static_cast<const UInt32Value&>(from_msg); + // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.UInt32Value) + GOOGLE_DCHECK_NE(&from, _this); + uint32_t cached_has_bits = 0; + (void) cached_has_bits; + + if (from._internal_value() != 0) { + _this->_internal_set_value(from._internal_value()); + } + _this->_internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); +} + +void UInt32Value::CopyFrom(const UInt32Value& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.UInt32Value) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool UInt32Value::IsInitialized() const { + return true; +} + +void UInt32Value::InternalSwap(UInt32Value* other) { + using std::swap; + _internal_metadata_.InternalSwap(&other->_internal_metadata_); + swap(_impl_.value_, other->_impl_.value_); +} + +::PROTOBUF_NAMESPACE_ID::Metadata UInt32Value::GetMetadata() const { + return ::_pbi::AssignDescriptors( + &descriptor_table_google_2fprotobuf_2fwrappers_2eproto_getter, &descriptor_table_google_2fprotobuf_2fwrappers_2eproto_once, + file_level_metadata_google_2fprotobuf_2fwrappers_2eproto[5]); +} + +// =================================================================== + +class BoolValue::_Internal { + public: +}; + +BoolValue::BoolValue(::PROTOBUF_NAMESPACE_ID::Arena* arena, + bool is_message_owned) + : ::PROTOBUF_NAMESPACE_ID::Message(arena, is_message_owned) { + SharedCtor(arena, is_message_owned); + // @@protoc_insertion_point(arena_constructor:google.protobuf.BoolValue) +} +BoolValue::BoolValue(const BoolValue& from) + : ::PROTOBUF_NAMESPACE_ID::Message() { + BoolValue* const _this = this; (void)_this; + new (&_impl_) Impl_{ + decltype(_impl_.value_){} + , /*decltype(_impl_._cached_size_)*/{}}; + + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); + _this->_impl_.value_ = from._impl_.value_; + // @@protoc_insertion_point(copy_constructor:google.protobuf.BoolValue) +} + +inline void BoolValue::SharedCtor( + ::_pb::Arena* arena, bool is_message_owned) { + (void)arena; + (void)is_message_owned; + new (&_impl_) Impl_{ + decltype(_impl_.value_){false} + , /*decltype(_impl_._cached_size_)*/{} + }; +} + +BoolValue::~BoolValue() { + // @@protoc_insertion_point(destructor:google.protobuf.BoolValue) + if (auto *arena = _internal_metadata_.DeleteReturnArena<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>()) { + (void)arena; + return; + } + SharedDtor(); +} + +inline void BoolValue::SharedDtor() { + GOOGLE_DCHECK(GetArenaForAllocation() == nullptr); +} + +void BoolValue::SetCachedSize(int size) const { + _impl_._cached_size_.Set(size); +} + +void BoolValue::Clear() { +// @@protoc_insertion_point(message_clear_start:google.protobuf.BoolValue) + uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + _impl_.value_ = false; + _internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); +} + +const char* BoolValue::_InternalParse(const char* ptr, ::_pbi::ParseContext* ctx) { +#define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure + while (!ctx->Done(&ptr)) { + uint32_t tag; + ptr = ::_pbi::ReadTag(ptr, &tag); + switch (tag >> 3) { + // bool value = 1; + case 1: + if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 8)) { + _impl_.value_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr); + CHK_(ptr); + } else + goto handle_unusual; + continue; + default: + goto handle_unusual; + } // switch + handle_unusual: + if ((tag == 0) || ((tag & 7) == 4)) { + CHK_(ptr); + ctx->SetLastTag(tag); + goto message_done; + } + ptr = UnknownFieldParse( + tag, + _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(), + ptr, ctx); + CHK_(ptr != nullptr); + } // while +message_done: + return ptr; +failure: + ptr = nullptr; + goto message_done; +#undef CHK_ +} + +uint8_t* BoolValue::_InternalSerialize( + uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const { + // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.BoolValue) + uint32_t cached_has_bits = 0; + (void) cached_has_bits; + + // bool value = 1; + if (this->_internal_value() != 0) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteBoolToArray(1, this->_internal_value(), target); + } + + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + target = ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( + _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.BoolValue) + return target; +} + +size_t BoolValue::ByteSizeLong() const { +// @@protoc_insertion_point(message_byte_size_start:google.protobuf.BoolValue) + size_t total_size = 0; + + uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + // bool value = 1; + if (this->_internal_value() != 0) { + total_size += 1 + 1; + } + + return MaybeComputeUnknownFieldsSize(total_size, &_impl_._cached_size_); +} + +const ::PROTOBUF_NAMESPACE_ID::Message::ClassData BoolValue::_class_data_ = { + ::PROTOBUF_NAMESPACE_ID::Message::CopyWithSourceCheck, + BoolValue::MergeImpl +}; +const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*BoolValue::GetClassData() const { return &_class_data_; } + + +void BoolValue::MergeImpl(::PROTOBUF_NAMESPACE_ID::Message& to_msg, const ::PROTOBUF_NAMESPACE_ID::Message& from_msg) { + auto* const _this = static_cast<BoolValue*>(&to_msg); + auto& from = static_cast<const BoolValue&>(from_msg); + // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.BoolValue) + GOOGLE_DCHECK_NE(&from, _this); + uint32_t cached_has_bits = 0; + (void) cached_has_bits; + + if (from._internal_value() != 0) { + _this->_internal_set_value(from._internal_value()); + } + _this->_internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); +} + +void BoolValue::CopyFrom(const BoolValue& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.BoolValue) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool BoolValue::IsInitialized() const { + return true; +} + +void BoolValue::InternalSwap(BoolValue* other) { + using std::swap; + _internal_metadata_.InternalSwap(&other->_internal_metadata_); + swap(_impl_.value_, other->_impl_.value_); +} + +::PROTOBUF_NAMESPACE_ID::Metadata BoolValue::GetMetadata() const { + return ::_pbi::AssignDescriptors( + &descriptor_table_google_2fprotobuf_2fwrappers_2eproto_getter, &descriptor_table_google_2fprotobuf_2fwrappers_2eproto_once, + file_level_metadata_google_2fprotobuf_2fwrappers_2eproto[6]); +} + +// =================================================================== + +class StringValue::_Internal { + public: +}; + +StringValue::StringValue(::PROTOBUF_NAMESPACE_ID::Arena* arena, + bool is_message_owned) + : ::PROTOBUF_NAMESPACE_ID::Message(arena, is_message_owned) { + SharedCtor(arena, is_message_owned); + // @@protoc_insertion_point(arena_constructor:google.protobuf.StringValue) +} +StringValue::StringValue(const StringValue& from) + : ::PROTOBUF_NAMESPACE_ID::Message() { + StringValue* const _this = this; (void)_this; + new (&_impl_) Impl_{ + decltype(_impl_.value_){} + , /*decltype(_impl_._cached_size_)*/{}}; + + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); + _impl_.value_.InitDefault(); + #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + _impl_.value_.Set("", GetArenaForAllocation()); + #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (!from._internal_value().empty()) { + _this->_impl_.value_.Set(from._internal_value(), + _this->GetArenaForAllocation()); + } + // @@protoc_insertion_point(copy_constructor:google.protobuf.StringValue) +} + +inline void StringValue::SharedCtor( + ::_pb::Arena* arena, bool is_message_owned) { + (void)arena; + (void)is_message_owned; + new (&_impl_) Impl_{ + decltype(_impl_.value_){} + , /*decltype(_impl_._cached_size_)*/{} + }; + _impl_.value_.InitDefault(); + #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + _impl_.value_.Set("", GetArenaForAllocation()); + #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING +} + +StringValue::~StringValue() { + // @@protoc_insertion_point(destructor:google.protobuf.StringValue) + if (auto *arena = _internal_metadata_.DeleteReturnArena<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>()) { + (void)arena; + return; + } + SharedDtor(); +} + +inline void StringValue::SharedDtor() { + GOOGLE_DCHECK(GetArenaForAllocation() == nullptr); + _impl_.value_.Destroy(); +} + +void StringValue::SetCachedSize(int size) const { + _impl_._cached_size_.Set(size); +} + +void StringValue::Clear() { +// @@protoc_insertion_point(message_clear_start:google.protobuf.StringValue) + uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + _impl_.value_.ClearToEmpty(); + _internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); +} + +const char* StringValue::_InternalParse(const char* ptr, ::_pbi::ParseContext* ctx) { +#define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure + while (!ctx->Done(&ptr)) { + uint32_t tag; + ptr = ::_pbi::ReadTag(ptr, &tag); + switch (tag >> 3) { + // string value = 1; + case 1: + if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 10)) { + auto str = _internal_mutable_value(); + ptr = ::_pbi::InlineGreedyStringParser(str, ptr, ctx); + CHK_(ptr); + CHK_(::_pbi::VerifyUTF8(str, "google.protobuf.StringValue.value")); + } else + goto handle_unusual; + continue; + default: + goto handle_unusual; + } // switch + handle_unusual: + if ((tag == 0) || ((tag & 7) == 4)) { + CHK_(ptr); + ctx->SetLastTag(tag); + goto message_done; + } + ptr = UnknownFieldParse( + tag, + _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(), + ptr, ctx); + CHK_(ptr != nullptr); + } // while +message_done: + return ptr; +failure: + ptr = nullptr; + goto message_done; +#undef CHK_ +} + +uint8_t* StringValue::_InternalSerialize( + uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const { + // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.StringValue) + uint32_t cached_has_bits = 0; + (void) cached_has_bits; + + // string value = 1; + if (!this->_internal_value().empty()) { + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::VerifyUtf8String( + this->_internal_value().data(), static_cast<int>(this->_internal_value().length()), + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::SERIALIZE, + "google.protobuf.StringValue.value"); + target = stream->WriteStringMaybeAliased( + 1, this->_internal_value(), target); + } + + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + target = ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( + _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.StringValue) + return target; +} + +size_t StringValue::ByteSizeLong() const { +// @@protoc_insertion_point(message_byte_size_start:google.protobuf.StringValue) + size_t total_size = 0; + + uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + // string value = 1; + if (!this->_internal_value().empty()) { + total_size += 1 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize( + this->_internal_value()); + } + + return MaybeComputeUnknownFieldsSize(total_size, &_impl_._cached_size_); +} + +const ::PROTOBUF_NAMESPACE_ID::Message::ClassData StringValue::_class_data_ = { + ::PROTOBUF_NAMESPACE_ID::Message::CopyWithSourceCheck, + StringValue::MergeImpl +}; +const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*StringValue::GetClassData() const { return &_class_data_; } + + +void StringValue::MergeImpl(::PROTOBUF_NAMESPACE_ID::Message& to_msg, const ::PROTOBUF_NAMESPACE_ID::Message& from_msg) { + auto* const _this = static_cast<StringValue*>(&to_msg); + auto& from = static_cast<const StringValue&>(from_msg); + // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.StringValue) + GOOGLE_DCHECK_NE(&from, _this); + uint32_t cached_has_bits = 0; + (void) cached_has_bits; + + if (!from._internal_value().empty()) { + _this->_internal_set_value(from._internal_value()); + } + _this->_internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); +} + +void StringValue::CopyFrom(const StringValue& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.StringValue) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool StringValue::IsInitialized() const { + return true; +} + +void StringValue::InternalSwap(StringValue* other) { + using std::swap; + auto* lhs_arena = GetArenaForAllocation(); + auto* rhs_arena = other->GetArenaForAllocation(); + _internal_metadata_.InternalSwap(&other->_internal_metadata_); + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::InternalSwap( + &_impl_.value_, lhs_arena, + &other->_impl_.value_, rhs_arena + ); +} + +::PROTOBUF_NAMESPACE_ID::Metadata StringValue::GetMetadata() const { + return ::_pbi::AssignDescriptors( + &descriptor_table_google_2fprotobuf_2fwrappers_2eproto_getter, &descriptor_table_google_2fprotobuf_2fwrappers_2eproto_once, + file_level_metadata_google_2fprotobuf_2fwrappers_2eproto[7]); +} + +// =================================================================== + +class BytesValue::_Internal { + public: +}; + +BytesValue::BytesValue(::PROTOBUF_NAMESPACE_ID::Arena* arena, + bool is_message_owned) + : ::PROTOBUF_NAMESPACE_ID::Message(arena, is_message_owned) { + SharedCtor(arena, is_message_owned); + // @@protoc_insertion_point(arena_constructor:google.protobuf.BytesValue) +} +BytesValue::BytesValue(const BytesValue& from) + : ::PROTOBUF_NAMESPACE_ID::Message() { + BytesValue* const _this = this; (void)_this; + new (&_impl_) Impl_{ + decltype(_impl_.value_){} + , /*decltype(_impl_._cached_size_)*/{}}; + + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); + _impl_.value_.InitDefault(); + #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + _impl_.value_.Set("", GetArenaForAllocation()); + #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (!from._internal_value().empty()) { + _this->_impl_.value_.Set(from._internal_value(), + _this->GetArenaForAllocation()); + } + // @@protoc_insertion_point(copy_constructor:google.protobuf.BytesValue) +} + +inline void BytesValue::SharedCtor( + ::_pb::Arena* arena, bool is_message_owned) { + (void)arena; + (void)is_message_owned; + new (&_impl_) Impl_{ + decltype(_impl_.value_){} + , /*decltype(_impl_._cached_size_)*/{} + }; + _impl_.value_.InitDefault(); + #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + _impl_.value_.Set("", GetArenaForAllocation()); + #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING +} + +BytesValue::~BytesValue() { + // @@protoc_insertion_point(destructor:google.protobuf.BytesValue) + if (auto *arena = _internal_metadata_.DeleteReturnArena<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>()) { + (void)arena; + return; + } + SharedDtor(); +} + +inline void BytesValue::SharedDtor() { + GOOGLE_DCHECK(GetArenaForAllocation() == nullptr); + _impl_.value_.Destroy(); +} + +void BytesValue::SetCachedSize(int size) const { + _impl_._cached_size_.Set(size); +} + +void BytesValue::Clear() { +// @@protoc_insertion_point(message_clear_start:google.protobuf.BytesValue) + uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + _impl_.value_.ClearToEmpty(); + _internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); +} + +const char* BytesValue::_InternalParse(const char* ptr, ::_pbi::ParseContext* ctx) { +#define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure + while (!ctx->Done(&ptr)) { + uint32_t tag; + ptr = ::_pbi::ReadTag(ptr, &tag); + switch (tag >> 3) { + // bytes value = 1; + case 1: + if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 10)) { + auto str = _internal_mutable_value(); + ptr = ::_pbi::InlineGreedyStringParser(str, ptr, ctx); + CHK_(ptr); + } else + goto handle_unusual; + continue; + default: + goto handle_unusual; + } // switch + handle_unusual: + if ((tag == 0) || ((tag & 7) == 4)) { + CHK_(ptr); + ctx->SetLastTag(tag); + goto message_done; + } + ptr = UnknownFieldParse( + tag, + _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(), + ptr, ctx); + CHK_(ptr != nullptr); + } // while +message_done: + return ptr; +failure: + ptr = nullptr; + goto message_done; +#undef CHK_ +} + +uint8_t* BytesValue::_InternalSerialize( + uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const { + // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.BytesValue) + uint32_t cached_has_bits = 0; + (void) cached_has_bits; + + // bytes value = 1; + if (!this->_internal_value().empty()) { + target = stream->WriteBytesMaybeAliased( + 1, this->_internal_value(), target); + } + + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + target = ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( + _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.BytesValue) + return target; +} + +size_t BytesValue::ByteSizeLong() const { +// @@protoc_insertion_point(message_byte_size_start:google.protobuf.BytesValue) + size_t total_size = 0; + + uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + // bytes value = 1; + if (!this->_internal_value().empty()) { + total_size += 1 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::BytesSize( + this->_internal_value()); + } + + return MaybeComputeUnknownFieldsSize(total_size, &_impl_._cached_size_); +} + +const ::PROTOBUF_NAMESPACE_ID::Message::ClassData BytesValue::_class_data_ = { + ::PROTOBUF_NAMESPACE_ID::Message::CopyWithSourceCheck, + BytesValue::MergeImpl +}; +const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*BytesValue::GetClassData() const { return &_class_data_; } + + +void BytesValue::MergeImpl(::PROTOBUF_NAMESPACE_ID::Message& to_msg, const ::PROTOBUF_NAMESPACE_ID::Message& from_msg) { + auto* const _this = static_cast<BytesValue*>(&to_msg); + auto& from = static_cast<const BytesValue&>(from_msg); + // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.BytesValue) + GOOGLE_DCHECK_NE(&from, _this); + uint32_t cached_has_bits = 0; + (void) cached_has_bits; + + if (!from._internal_value().empty()) { + _this->_internal_set_value(from._internal_value()); + } + _this->_internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); +} + +void BytesValue::CopyFrom(const BytesValue& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.BytesValue) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool BytesValue::IsInitialized() const { + return true; +} + +void BytesValue::InternalSwap(BytesValue* other) { + using std::swap; + auto* lhs_arena = GetArenaForAllocation(); + auto* rhs_arena = other->GetArenaForAllocation(); + _internal_metadata_.InternalSwap(&other->_internal_metadata_); + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::InternalSwap( + &_impl_.value_, lhs_arena, + &other->_impl_.value_, rhs_arena + ); +} + +::PROTOBUF_NAMESPACE_ID::Metadata BytesValue::GetMetadata() const { + return ::_pbi::AssignDescriptors( + &descriptor_table_google_2fprotobuf_2fwrappers_2eproto_getter, &descriptor_table_google_2fprotobuf_2fwrappers_2eproto_once, + file_level_metadata_google_2fprotobuf_2fwrappers_2eproto[8]); +} + +// @@protoc_insertion_point(namespace_scope) +PROTOBUF_NAMESPACE_CLOSE +PROTOBUF_NAMESPACE_OPEN +template<> PROTOBUF_NOINLINE ::PROTOBUF_NAMESPACE_ID::DoubleValue* +Arena::CreateMaybeMessage< ::PROTOBUF_NAMESPACE_ID::DoubleValue >(Arena* arena) { + return Arena::CreateMessageInternal< ::PROTOBUF_NAMESPACE_ID::DoubleValue >(arena); +} +template<> PROTOBUF_NOINLINE ::PROTOBUF_NAMESPACE_ID::FloatValue* +Arena::CreateMaybeMessage< ::PROTOBUF_NAMESPACE_ID::FloatValue >(Arena* arena) { + return Arena::CreateMessageInternal< ::PROTOBUF_NAMESPACE_ID::FloatValue >(arena); +} +template<> PROTOBUF_NOINLINE ::PROTOBUF_NAMESPACE_ID::Int64Value* +Arena::CreateMaybeMessage< ::PROTOBUF_NAMESPACE_ID::Int64Value >(Arena* arena) { + return Arena::CreateMessageInternal< ::PROTOBUF_NAMESPACE_ID::Int64Value >(arena); +} +template<> PROTOBUF_NOINLINE ::PROTOBUF_NAMESPACE_ID::UInt64Value* +Arena::CreateMaybeMessage< ::PROTOBUF_NAMESPACE_ID::UInt64Value >(Arena* arena) { + return Arena::CreateMessageInternal< ::PROTOBUF_NAMESPACE_ID::UInt64Value >(arena); +} +template<> PROTOBUF_NOINLINE ::PROTOBUF_NAMESPACE_ID::Int32Value* +Arena::CreateMaybeMessage< ::PROTOBUF_NAMESPACE_ID::Int32Value >(Arena* arena) { + return Arena::CreateMessageInternal< ::PROTOBUF_NAMESPACE_ID::Int32Value >(arena); +} +template<> PROTOBUF_NOINLINE ::PROTOBUF_NAMESPACE_ID::UInt32Value* +Arena::CreateMaybeMessage< ::PROTOBUF_NAMESPACE_ID::UInt32Value >(Arena* arena) { + return Arena::CreateMessageInternal< ::PROTOBUF_NAMESPACE_ID::UInt32Value >(arena); +} +template<> PROTOBUF_NOINLINE ::PROTOBUF_NAMESPACE_ID::BoolValue* +Arena::CreateMaybeMessage< ::PROTOBUF_NAMESPACE_ID::BoolValue >(Arena* arena) { + return Arena::CreateMessageInternal< ::PROTOBUF_NAMESPACE_ID::BoolValue >(arena); +} +template<> PROTOBUF_NOINLINE ::PROTOBUF_NAMESPACE_ID::StringValue* +Arena::CreateMaybeMessage< ::PROTOBUF_NAMESPACE_ID::StringValue >(Arena* arena) { + return Arena::CreateMessageInternal< ::PROTOBUF_NAMESPACE_ID::StringValue >(arena); +} +template<> PROTOBUF_NOINLINE ::PROTOBUF_NAMESPACE_ID::BytesValue* +Arena::CreateMaybeMessage< ::PROTOBUF_NAMESPACE_ID::BytesValue >(Arena* arena) { + return Arena::CreateMessageInternal< ::PROTOBUF_NAMESPACE_ID::BytesValue >(arena); +} +PROTOBUF_NAMESPACE_CLOSE + +// @@protoc_insertion_point(global_scope) +#include <google/protobuf/port_undef.inc> diff --git a/toolkit/components/protobuf/src/google/protobuf/wrappers.pb.h b/toolkit/components/protobuf/src/google/protobuf/wrappers.pb.h new file mode 100644 index 0000000000..cc42a8ba5c --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/wrappers.pb.h @@ -0,0 +1,1741 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: google/protobuf/wrappers.proto + +#ifndef GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2fwrappers_2eproto +#define GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2fwrappers_2eproto + +#include <limits> +#include <string> + +#include <google/protobuf/port_def.inc> +#if PROTOBUF_VERSION < 3021000 +#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 3021006 < 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. +#endif + +#include <google/protobuf/port_undef.inc> +#include <google/protobuf/io/coded_stream.h> +#include <google/protobuf/arena.h> +#include <google/protobuf/arenastring.h> +#include <google/protobuf/generated_message_util.h> +#include <google/protobuf/metadata_lite.h> +#include <google/protobuf/generated_message_reflection.h> +#include <google/protobuf/message.h> +#include <google/protobuf/repeated_field.h> // IWYU pragma: export +#include <google/protobuf/extension_set.h> // IWYU pragma: export +#include <google/protobuf/unknown_field_set.h> +// @@protoc_insertion_point(includes) +#include <google/protobuf/port_def.inc> +#define PROTOBUF_INTERNAL_EXPORT_google_2fprotobuf_2fwrappers_2eproto PROTOBUF_EXPORT +PROTOBUF_NAMESPACE_OPEN +namespace internal { +class AnyMetadata; +} // namespace internal +PROTOBUF_NAMESPACE_CLOSE + +// Internal implementation detail -- do not use these members. +struct PROTOBUF_EXPORT TableStruct_google_2fprotobuf_2fwrappers_2eproto { + static const uint32_t offsets[]; +}; +PROTOBUF_EXPORT extern const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable descriptor_table_google_2fprotobuf_2fwrappers_2eproto; +PROTOBUF_NAMESPACE_OPEN +class BoolValue; +struct BoolValueDefaultTypeInternal; +PROTOBUF_EXPORT extern BoolValueDefaultTypeInternal _BoolValue_default_instance_; +class BytesValue; +struct BytesValueDefaultTypeInternal; +PROTOBUF_EXPORT extern BytesValueDefaultTypeInternal _BytesValue_default_instance_; +class DoubleValue; +struct DoubleValueDefaultTypeInternal; +PROTOBUF_EXPORT extern DoubleValueDefaultTypeInternal _DoubleValue_default_instance_; +class FloatValue; +struct FloatValueDefaultTypeInternal; +PROTOBUF_EXPORT extern FloatValueDefaultTypeInternal _FloatValue_default_instance_; +class Int32Value; +struct Int32ValueDefaultTypeInternal; +PROTOBUF_EXPORT extern Int32ValueDefaultTypeInternal _Int32Value_default_instance_; +class Int64Value; +struct Int64ValueDefaultTypeInternal; +PROTOBUF_EXPORT extern Int64ValueDefaultTypeInternal _Int64Value_default_instance_; +class StringValue; +struct StringValueDefaultTypeInternal; +PROTOBUF_EXPORT extern StringValueDefaultTypeInternal _StringValue_default_instance_; +class UInt32Value; +struct UInt32ValueDefaultTypeInternal; +PROTOBUF_EXPORT extern UInt32ValueDefaultTypeInternal _UInt32Value_default_instance_; +class UInt64Value; +struct UInt64ValueDefaultTypeInternal; +PROTOBUF_EXPORT extern UInt64ValueDefaultTypeInternal _UInt64Value_default_instance_; +PROTOBUF_NAMESPACE_CLOSE +PROTOBUF_NAMESPACE_OPEN +template<> PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::BoolValue* Arena::CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::BoolValue>(Arena*); +template<> PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::BytesValue* Arena::CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::BytesValue>(Arena*); +template<> PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::DoubleValue* Arena::CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::DoubleValue>(Arena*); +template<> PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::FloatValue* Arena::CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::FloatValue>(Arena*); +template<> PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::Int32Value* Arena::CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::Int32Value>(Arena*); +template<> PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::Int64Value* Arena::CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::Int64Value>(Arena*); +template<> PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::StringValue* Arena::CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::StringValue>(Arena*); +template<> PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::UInt32Value* Arena::CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::UInt32Value>(Arena*); +template<> PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::UInt64Value* Arena::CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::UInt64Value>(Arena*); +PROTOBUF_NAMESPACE_CLOSE +PROTOBUF_NAMESPACE_OPEN + +// =================================================================== + +class PROTOBUF_EXPORT DoubleValue final : + public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.DoubleValue) */ { + public: + inline DoubleValue() : DoubleValue(nullptr) {} + ~DoubleValue() override; + explicit PROTOBUF_CONSTEXPR DoubleValue(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized); + + DoubleValue(const DoubleValue& from); + DoubleValue(DoubleValue&& from) noexcept + : DoubleValue() { + *this = ::std::move(from); + } + + inline DoubleValue& operator=(const DoubleValue& from) { + CopyFrom(from); + return *this; + } + inline DoubleValue& operator=(DoubleValue&& from) noexcept { + if (this == &from) return *this; + if (GetOwningArena() == from.GetOwningArena() + #ifdef PROTOBUF_FORCE_COPY_IN_MOVE + && GetOwningArena() != nullptr + #endif // !PROTOBUF_FORCE_COPY_IN_MOVE + ) { + InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* descriptor() { + return GetDescriptor(); + } + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() { + return default_instance().GetMetadata().descriptor; + } + static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() { + return default_instance().GetMetadata().reflection; + } + static const DoubleValue& default_instance() { + return *internal_default_instance(); + } + static inline const DoubleValue* internal_default_instance() { + return reinterpret_cast<const DoubleValue*>( + &_DoubleValue_default_instance_); + } + static constexpr int kIndexInFileMessages = + 0; + + friend void swap(DoubleValue& a, DoubleValue& b) { + a.Swap(&b); + } + inline void Swap(DoubleValue* other) { + if (other == this) return; + #ifdef PROTOBUF_FORCE_COPY_IN_SWAP + if (GetOwningArena() != nullptr && + GetOwningArena() == other->GetOwningArena()) { + #else // PROTOBUF_FORCE_COPY_IN_SWAP + if (GetOwningArena() == other->GetOwningArena()) { + #endif // !PROTOBUF_FORCE_COPY_IN_SWAP + InternalSwap(other); + } else { + ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(DoubleValue* other) { + if (other == this) return; + GOOGLE_DCHECK(GetOwningArena() == other->GetOwningArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + DoubleValue* New(::PROTOBUF_NAMESPACE_ID::Arena* arena = nullptr) const final { + return CreateMaybeMessage<DoubleValue>(arena); + } + using ::PROTOBUF_NAMESPACE_ID::Message::CopyFrom; + void CopyFrom(const DoubleValue& from); + using ::PROTOBUF_NAMESPACE_ID::Message::MergeFrom; + void MergeFrom( const DoubleValue& from) { + DoubleValue::MergeImpl(*this, from); + } + private: + static void MergeImpl(::PROTOBUF_NAMESPACE_ID::Message& to_msg, const ::PROTOBUF_NAMESPACE_ID::Message& from_msg); + public: + PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + bool IsInitialized() const final; + + size_t ByteSizeLong() const final; + const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final; + uint8_t* _InternalSerialize( + uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final; + int GetCachedSize() const final { return _impl_._cached_size_.Get(); } + + private: + void SharedCtor(::PROTOBUF_NAMESPACE_ID::Arena* arena, bool is_message_owned); + void SharedDtor(); + void SetCachedSize(int size) const final; + void InternalSwap(DoubleValue* other); + + private: + friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata; + static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() { + return "google.protobuf.DoubleValue"; + } + protected: + explicit DoubleValue(::PROTOBUF_NAMESPACE_ID::Arena* arena, + bool is_message_owned = false); + public: + + static const ClassData _class_data_; + const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*GetClassData() const final; + + ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final; + + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + + enum : int { + kValueFieldNumber = 1, + }; + // double value = 1; + void clear_value(); + double value() const; + void set_value(double value); + private: + double _internal_value() const; + void _internal_set_value(double value); + public: + + // @@protoc_insertion_point(class_scope:google.protobuf.DoubleValue) + private: + class _Internal; + + template <typename T> friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper; + typedef void InternalArenaConstructable_; + typedef void DestructorSkippable_; + struct Impl_ { + double value_; + mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_; + }; + union { Impl_ _impl_; }; + friend struct ::TableStruct_google_2fprotobuf_2fwrappers_2eproto; +}; +// ------------------------------------------------------------------- + +class PROTOBUF_EXPORT FloatValue final : + public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.FloatValue) */ { + public: + inline FloatValue() : FloatValue(nullptr) {} + ~FloatValue() override; + explicit PROTOBUF_CONSTEXPR FloatValue(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized); + + FloatValue(const FloatValue& from); + FloatValue(FloatValue&& from) noexcept + : FloatValue() { + *this = ::std::move(from); + } + + inline FloatValue& operator=(const FloatValue& from) { + CopyFrom(from); + return *this; + } + inline FloatValue& operator=(FloatValue&& from) noexcept { + if (this == &from) return *this; + if (GetOwningArena() == from.GetOwningArena() + #ifdef PROTOBUF_FORCE_COPY_IN_MOVE + && GetOwningArena() != nullptr + #endif // !PROTOBUF_FORCE_COPY_IN_MOVE + ) { + InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* descriptor() { + return GetDescriptor(); + } + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() { + return default_instance().GetMetadata().descriptor; + } + static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() { + return default_instance().GetMetadata().reflection; + } + static const FloatValue& default_instance() { + return *internal_default_instance(); + } + static inline const FloatValue* internal_default_instance() { + return reinterpret_cast<const FloatValue*>( + &_FloatValue_default_instance_); + } + static constexpr int kIndexInFileMessages = + 1; + + friend void swap(FloatValue& a, FloatValue& b) { + a.Swap(&b); + } + inline void Swap(FloatValue* other) { + if (other == this) return; + #ifdef PROTOBUF_FORCE_COPY_IN_SWAP + if (GetOwningArena() != nullptr && + GetOwningArena() == other->GetOwningArena()) { + #else // PROTOBUF_FORCE_COPY_IN_SWAP + if (GetOwningArena() == other->GetOwningArena()) { + #endif // !PROTOBUF_FORCE_COPY_IN_SWAP + InternalSwap(other); + } else { + ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(FloatValue* other) { + if (other == this) return; + GOOGLE_DCHECK(GetOwningArena() == other->GetOwningArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + FloatValue* New(::PROTOBUF_NAMESPACE_ID::Arena* arena = nullptr) const final { + return CreateMaybeMessage<FloatValue>(arena); + } + using ::PROTOBUF_NAMESPACE_ID::Message::CopyFrom; + void CopyFrom(const FloatValue& from); + using ::PROTOBUF_NAMESPACE_ID::Message::MergeFrom; + void MergeFrom( const FloatValue& from) { + FloatValue::MergeImpl(*this, from); + } + private: + static void MergeImpl(::PROTOBUF_NAMESPACE_ID::Message& to_msg, const ::PROTOBUF_NAMESPACE_ID::Message& from_msg); + public: + PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + bool IsInitialized() const final; + + size_t ByteSizeLong() const final; + const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final; + uint8_t* _InternalSerialize( + uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final; + int GetCachedSize() const final { return _impl_._cached_size_.Get(); } + + private: + void SharedCtor(::PROTOBUF_NAMESPACE_ID::Arena* arena, bool is_message_owned); + void SharedDtor(); + void SetCachedSize(int size) const final; + void InternalSwap(FloatValue* other); + + private: + friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata; + static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() { + return "google.protobuf.FloatValue"; + } + protected: + explicit FloatValue(::PROTOBUF_NAMESPACE_ID::Arena* arena, + bool is_message_owned = false); + public: + + static const ClassData _class_data_; + const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*GetClassData() const final; + + ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final; + + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + + enum : int { + kValueFieldNumber = 1, + }; + // float value = 1; + void clear_value(); + float value() const; + void set_value(float value); + private: + float _internal_value() const; + void _internal_set_value(float value); + public: + + // @@protoc_insertion_point(class_scope:google.protobuf.FloatValue) + private: + class _Internal; + + template <typename T> friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper; + typedef void InternalArenaConstructable_; + typedef void DestructorSkippable_; + struct Impl_ { + float value_; + mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_; + }; + union { Impl_ _impl_; }; + friend struct ::TableStruct_google_2fprotobuf_2fwrappers_2eproto; +}; +// ------------------------------------------------------------------- + +class PROTOBUF_EXPORT Int64Value final : + public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.Int64Value) */ { + public: + inline Int64Value() : Int64Value(nullptr) {} + ~Int64Value() override; + explicit PROTOBUF_CONSTEXPR Int64Value(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized); + + Int64Value(const Int64Value& from); + Int64Value(Int64Value&& from) noexcept + : Int64Value() { + *this = ::std::move(from); + } + + inline Int64Value& operator=(const Int64Value& from) { + CopyFrom(from); + return *this; + } + inline Int64Value& operator=(Int64Value&& from) noexcept { + if (this == &from) return *this; + if (GetOwningArena() == from.GetOwningArena() + #ifdef PROTOBUF_FORCE_COPY_IN_MOVE + && GetOwningArena() != nullptr + #endif // !PROTOBUF_FORCE_COPY_IN_MOVE + ) { + InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* descriptor() { + return GetDescriptor(); + } + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() { + return default_instance().GetMetadata().descriptor; + } + static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() { + return default_instance().GetMetadata().reflection; + } + static const Int64Value& default_instance() { + return *internal_default_instance(); + } + static inline const Int64Value* internal_default_instance() { + return reinterpret_cast<const Int64Value*>( + &_Int64Value_default_instance_); + } + static constexpr int kIndexInFileMessages = + 2; + + friend void swap(Int64Value& a, Int64Value& b) { + a.Swap(&b); + } + inline void Swap(Int64Value* other) { + if (other == this) return; + #ifdef PROTOBUF_FORCE_COPY_IN_SWAP + if (GetOwningArena() != nullptr && + GetOwningArena() == other->GetOwningArena()) { + #else // PROTOBUF_FORCE_COPY_IN_SWAP + if (GetOwningArena() == other->GetOwningArena()) { + #endif // !PROTOBUF_FORCE_COPY_IN_SWAP + InternalSwap(other); + } else { + ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(Int64Value* other) { + if (other == this) return; + GOOGLE_DCHECK(GetOwningArena() == other->GetOwningArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + Int64Value* New(::PROTOBUF_NAMESPACE_ID::Arena* arena = nullptr) const final { + return CreateMaybeMessage<Int64Value>(arena); + } + using ::PROTOBUF_NAMESPACE_ID::Message::CopyFrom; + void CopyFrom(const Int64Value& from); + using ::PROTOBUF_NAMESPACE_ID::Message::MergeFrom; + void MergeFrom( const Int64Value& from) { + Int64Value::MergeImpl(*this, from); + } + private: + static void MergeImpl(::PROTOBUF_NAMESPACE_ID::Message& to_msg, const ::PROTOBUF_NAMESPACE_ID::Message& from_msg); + public: + PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + bool IsInitialized() const final; + + size_t ByteSizeLong() const final; + const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final; + uint8_t* _InternalSerialize( + uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final; + int GetCachedSize() const final { return _impl_._cached_size_.Get(); } + + private: + void SharedCtor(::PROTOBUF_NAMESPACE_ID::Arena* arena, bool is_message_owned); + void SharedDtor(); + void SetCachedSize(int size) const final; + void InternalSwap(Int64Value* other); + + private: + friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata; + static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() { + return "google.protobuf.Int64Value"; + } + protected: + explicit Int64Value(::PROTOBUF_NAMESPACE_ID::Arena* arena, + bool is_message_owned = false); + public: + + static const ClassData _class_data_; + const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*GetClassData() const final; + + ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final; + + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + + enum : int { + kValueFieldNumber = 1, + }; + // int64 value = 1; + void clear_value(); + int64_t value() const; + void set_value(int64_t value); + private: + int64_t _internal_value() const; + void _internal_set_value(int64_t value); + public: + + // @@protoc_insertion_point(class_scope:google.protobuf.Int64Value) + private: + class _Internal; + + template <typename T> friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper; + typedef void InternalArenaConstructable_; + typedef void DestructorSkippable_; + struct Impl_ { + int64_t value_; + mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_; + }; + union { Impl_ _impl_; }; + friend struct ::TableStruct_google_2fprotobuf_2fwrappers_2eproto; +}; +// ------------------------------------------------------------------- + +class PROTOBUF_EXPORT UInt64Value final : + public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.UInt64Value) */ { + public: + inline UInt64Value() : UInt64Value(nullptr) {} + ~UInt64Value() override; + explicit PROTOBUF_CONSTEXPR UInt64Value(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized); + + UInt64Value(const UInt64Value& from); + UInt64Value(UInt64Value&& from) noexcept + : UInt64Value() { + *this = ::std::move(from); + } + + inline UInt64Value& operator=(const UInt64Value& from) { + CopyFrom(from); + return *this; + } + inline UInt64Value& operator=(UInt64Value&& from) noexcept { + if (this == &from) return *this; + if (GetOwningArena() == from.GetOwningArena() + #ifdef PROTOBUF_FORCE_COPY_IN_MOVE + && GetOwningArena() != nullptr + #endif // !PROTOBUF_FORCE_COPY_IN_MOVE + ) { + InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* descriptor() { + return GetDescriptor(); + } + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() { + return default_instance().GetMetadata().descriptor; + } + static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() { + return default_instance().GetMetadata().reflection; + } + static const UInt64Value& default_instance() { + return *internal_default_instance(); + } + static inline const UInt64Value* internal_default_instance() { + return reinterpret_cast<const UInt64Value*>( + &_UInt64Value_default_instance_); + } + static constexpr int kIndexInFileMessages = + 3; + + friend void swap(UInt64Value& a, UInt64Value& b) { + a.Swap(&b); + } + inline void Swap(UInt64Value* other) { + if (other == this) return; + #ifdef PROTOBUF_FORCE_COPY_IN_SWAP + if (GetOwningArena() != nullptr && + GetOwningArena() == other->GetOwningArena()) { + #else // PROTOBUF_FORCE_COPY_IN_SWAP + if (GetOwningArena() == other->GetOwningArena()) { + #endif // !PROTOBUF_FORCE_COPY_IN_SWAP + InternalSwap(other); + } else { + ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(UInt64Value* other) { + if (other == this) return; + GOOGLE_DCHECK(GetOwningArena() == other->GetOwningArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + UInt64Value* New(::PROTOBUF_NAMESPACE_ID::Arena* arena = nullptr) const final { + return CreateMaybeMessage<UInt64Value>(arena); + } + using ::PROTOBUF_NAMESPACE_ID::Message::CopyFrom; + void CopyFrom(const UInt64Value& from); + using ::PROTOBUF_NAMESPACE_ID::Message::MergeFrom; + void MergeFrom( const UInt64Value& from) { + UInt64Value::MergeImpl(*this, from); + } + private: + static void MergeImpl(::PROTOBUF_NAMESPACE_ID::Message& to_msg, const ::PROTOBUF_NAMESPACE_ID::Message& from_msg); + public: + PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + bool IsInitialized() const final; + + size_t ByteSizeLong() const final; + const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final; + uint8_t* _InternalSerialize( + uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final; + int GetCachedSize() const final { return _impl_._cached_size_.Get(); } + + private: + void SharedCtor(::PROTOBUF_NAMESPACE_ID::Arena* arena, bool is_message_owned); + void SharedDtor(); + void SetCachedSize(int size) const final; + void InternalSwap(UInt64Value* other); + + private: + friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata; + static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() { + return "google.protobuf.UInt64Value"; + } + protected: + explicit UInt64Value(::PROTOBUF_NAMESPACE_ID::Arena* arena, + bool is_message_owned = false); + public: + + static const ClassData _class_data_; + const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*GetClassData() const final; + + ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final; + + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + + enum : int { + kValueFieldNumber = 1, + }; + // uint64 value = 1; + void clear_value(); + uint64_t value() const; + void set_value(uint64_t value); + private: + uint64_t _internal_value() const; + void _internal_set_value(uint64_t value); + public: + + // @@protoc_insertion_point(class_scope:google.protobuf.UInt64Value) + private: + class _Internal; + + template <typename T> friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper; + typedef void InternalArenaConstructable_; + typedef void DestructorSkippable_; + struct Impl_ { + uint64_t value_; + mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_; + }; + union { Impl_ _impl_; }; + friend struct ::TableStruct_google_2fprotobuf_2fwrappers_2eproto; +}; +// ------------------------------------------------------------------- + +class PROTOBUF_EXPORT Int32Value final : + public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.Int32Value) */ { + public: + inline Int32Value() : Int32Value(nullptr) {} + ~Int32Value() override; + explicit PROTOBUF_CONSTEXPR Int32Value(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized); + + Int32Value(const Int32Value& from); + Int32Value(Int32Value&& from) noexcept + : Int32Value() { + *this = ::std::move(from); + } + + inline Int32Value& operator=(const Int32Value& from) { + CopyFrom(from); + return *this; + } + inline Int32Value& operator=(Int32Value&& from) noexcept { + if (this == &from) return *this; + if (GetOwningArena() == from.GetOwningArena() + #ifdef PROTOBUF_FORCE_COPY_IN_MOVE + && GetOwningArena() != nullptr + #endif // !PROTOBUF_FORCE_COPY_IN_MOVE + ) { + InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* descriptor() { + return GetDescriptor(); + } + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() { + return default_instance().GetMetadata().descriptor; + } + static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() { + return default_instance().GetMetadata().reflection; + } + static const Int32Value& default_instance() { + return *internal_default_instance(); + } + static inline const Int32Value* internal_default_instance() { + return reinterpret_cast<const Int32Value*>( + &_Int32Value_default_instance_); + } + static constexpr int kIndexInFileMessages = + 4; + + friend void swap(Int32Value& a, Int32Value& b) { + a.Swap(&b); + } + inline void Swap(Int32Value* other) { + if (other == this) return; + #ifdef PROTOBUF_FORCE_COPY_IN_SWAP + if (GetOwningArena() != nullptr && + GetOwningArena() == other->GetOwningArena()) { + #else // PROTOBUF_FORCE_COPY_IN_SWAP + if (GetOwningArena() == other->GetOwningArena()) { + #endif // !PROTOBUF_FORCE_COPY_IN_SWAP + InternalSwap(other); + } else { + ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(Int32Value* other) { + if (other == this) return; + GOOGLE_DCHECK(GetOwningArena() == other->GetOwningArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + Int32Value* New(::PROTOBUF_NAMESPACE_ID::Arena* arena = nullptr) const final { + return CreateMaybeMessage<Int32Value>(arena); + } + using ::PROTOBUF_NAMESPACE_ID::Message::CopyFrom; + void CopyFrom(const Int32Value& from); + using ::PROTOBUF_NAMESPACE_ID::Message::MergeFrom; + void MergeFrom( const Int32Value& from) { + Int32Value::MergeImpl(*this, from); + } + private: + static void MergeImpl(::PROTOBUF_NAMESPACE_ID::Message& to_msg, const ::PROTOBUF_NAMESPACE_ID::Message& from_msg); + public: + PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + bool IsInitialized() const final; + + size_t ByteSizeLong() const final; + const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final; + uint8_t* _InternalSerialize( + uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final; + int GetCachedSize() const final { return _impl_._cached_size_.Get(); } + + private: + void SharedCtor(::PROTOBUF_NAMESPACE_ID::Arena* arena, bool is_message_owned); + void SharedDtor(); + void SetCachedSize(int size) const final; + void InternalSwap(Int32Value* other); + + private: + friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata; + static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() { + return "google.protobuf.Int32Value"; + } + protected: + explicit Int32Value(::PROTOBUF_NAMESPACE_ID::Arena* arena, + bool is_message_owned = false); + public: + + static const ClassData _class_data_; + const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*GetClassData() const final; + + ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final; + + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + + enum : int { + kValueFieldNumber = 1, + }; + // int32 value = 1; + void clear_value(); + int32_t value() const; + void set_value(int32_t value); + private: + int32_t _internal_value() const; + void _internal_set_value(int32_t value); + public: + + // @@protoc_insertion_point(class_scope:google.protobuf.Int32Value) + private: + class _Internal; + + template <typename T> friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper; + typedef void InternalArenaConstructable_; + typedef void DestructorSkippable_; + struct Impl_ { + int32_t value_; + mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_; + }; + union { Impl_ _impl_; }; + friend struct ::TableStruct_google_2fprotobuf_2fwrappers_2eproto; +}; +// ------------------------------------------------------------------- + +class PROTOBUF_EXPORT UInt32Value final : + public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.UInt32Value) */ { + public: + inline UInt32Value() : UInt32Value(nullptr) {} + ~UInt32Value() override; + explicit PROTOBUF_CONSTEXPR UInt32Value(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized); + + UInt32Value(const UInt32Value& from); + UInt32Value(UInt32Value&& from) noexcept + : UInt32Value() { + *this = ::std::move(from); + } + + inline UInt32Value& operator=(const UInt32Value& from) { + CopyFrom(from); + return *this; + } + inline UInt32Value& operator=(UInt32Value&& from) noexcept { + if (this == &from) return *this; + if (GetOwningArena() == from.GetOwningArena() + #ifdef PROTOBUF_FORCE_COPY_IN_MOVE + && GetOwningArena() != nullptr + #endif // !PROTOBUF_FORCE_COPY_IN_MOVE + ) { + InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* descriptor() { + return GetDescriptor(); + } + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() { + return default_instance().GetMetadata().descriptor; + } + static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() { + return default_instance().GetMetadata().reflection; + } + static const UInt32Value& default_instance() { + return *internal_default_instance(); + } + static inline const UInt32Value* internal_default_instance() { + return reinterpret_cast<const UInt32Value*>( + &_UInt32Value_default_instance_); + } + static constexpr int kIndexInFileMessages = + 5; + + friend void swap(UInt32Value& a, UInt32Value& b) { + a.Swap(&b); + } + inline void Swap(UInt32Value* other) { + if (other == this) return; + #ifdef PROTOBUF_FORCE_COPY_IN_SWAP + if (GetOwningArena() != nullptr && + GetOwningArena() == other->GetOwningArena()) { + #else // PROTOBUF_FORCE_COPY_IN_SWAP + if (GetOwningArena() == other->GetOwningArena()) { + #endif // !PROTOBUF_FORCE_COPY_IN_SWAP + InternalSwap(other); + } else { + ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(UInt32Value* other) { + if (other == this) return; + GOOGLE_DCHECK(GetOwningArena() == other->GetOwningArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + UInt32Value* New(::PROTOBUF_NAMESPACE_ID::Arena* arena = nullptr) const final { + return CreateMaybeMessage<UInt32Value>(arena); + } + using ::PROTOBUF_NAMESPACE_ID::Message::CopyFrom; + void CopyFrom(const UInt32Value& from); + using ::PROTOBUF_NAMESPACE_ID::Message::MergeFrom; + void MergeFrom( const UInt32Value& from) { + UInt32Value::MergeImpl(*this, from); + } + private: + static void MergeImpl(::PROTOBUF_NAMESPACE_ID::Message& to_msg, const ::PROTOBUF_NAMESPACE_ID::Message& from_msg); + public: + PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + bool IsInitialized() const final; + + size_t ByteSizeLong() const final; + const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final; + uint8_t* _InternalSerialize( + uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final; + int GetCachedSize() const final { return _impl_._cached_size_.Get(); } + + private: + void SharedCtor(::PROTOBUF_NAMESPACE_ID::Arena* arena, bool is_message_owned); + void SharedDtor(); + void SetCachedSize(int size) const final; + void InternalSwap(UInt32Value* other); + + private: + friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata; + static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() { + return "google.protobuf.UInt32Value"; + } + protected: + explicit UInt32Value(::PROTOBUF_NAMESPACE_ID::Arena* arena, + bool is_message_owned = false); + public: + + static const ClassData _class_data_; + const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*GetClassData() const final; + + ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final; + + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + + enum : int { + kValueFieldNumber = 1, + }; + // uint32 value = 1; + void clear_value(); + uint32_t value() const; + void set_value(uint32_t value); + private: + uint32_t _internal_value() const; + void _internal_set_value(uint32_t value); + public: + + // @@protoc_insertion_point(class_scope:google.protobuf.UInt32Value) + private: + class _Internal; + + template <typename T> friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper; + typedef void InternalArenaConstructable_; + typedef void DestructorSkippable_; + struct Impl_ { + uint32_t value_; + mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_; + }; + union { Impl_ _impl_; }; + friend struct ::TableStruct_google_2fprotobuf_2fwrappers_2eproto; +}; +// ------------------------------------------------------------------- + +class PROTOBUF_EXPORT BoolValue final : + public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.BoolValue) */ { + public: + inline BoolValue() : BoolValue(nullptr) {} + ~BoolValue() override; + explicit PROTOBUF_CONSTEXPR BoolValue(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized); + + BoolValue(const BoolValue& from); + BoolValue(BoolValue&& from) noexcept + : BoolValue() { + *this = ::std::move(from); + } + + inline BoolValue& operator=(const BoolValue& from) { + CopyFrom(from); + return *this; + } + inline BoolValue& operator=(BoolValue&& from) noexcept { + if (this == &from) return *this; + if (GetOwningArena() == from.GetOwningArena() + #ifdef PROTOBUF_FORCE_COPY_IN_MOVE + && GetOwningArena() != nullptr + #endif // !PROTOBUF_FORCE_COPY_IN_MOVE + ) { + InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* descriptor() { + return GetDescriptor(); + } + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() { + return default_instance().GetMetadata().descriptor; + } + static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() { + return default_instance().GetMetadata().reflection; + } + static const BoolValue& default_instance() { + return *internal_default_instance(); + } + static inline const BoolValue* internal_default_instance() { + return reinterpret_cast<const BoolValue*>( + &_BoolValue_default_instance_); + } + static constexpr int kIndexInFileMessages = + 6; + + friend void swap(BoolValue& a, BoolValue& b) { + a.Swap(&b); + } + inline void Swap(BoolValue* other) { + if (other == this) return; + #ifdef PROTOBUF_FORCE_COPY_IN_SWAP + if (GetOwningArena() != nullptr && + GetOwningArena() == other->GetOwningArena()) { + #else // PROTOBUF_FORCE_COPY_IN_SWAP + if (GetOwningArena() == other->GetOwningArena()) { + #endif // !PROTOBUF_FORCE_COPY_IN_SWAP + InternalSwap(other); + } else { + ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(BoolValue* other) { + if (other == this) return; + GOOGLE_DCHECK(GetOwningArena() == other->GetOwningArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + BoolValue* New(::PROTOBUF_NAMESPACE_ID::Arena* arena = nullptr) const final { + return CreateMaybeMessage<BoolValue>(arena); + } + using ::PROTOBUF_NAMESPACE_ID::Message::CopyFrom; + void CopyFrom(const BoolValue& from); + using ::PROTOBUF_NAMESPACE_ID::Message::MergeFrom; + void MergeFrom( const BoolValue& from) { + BoolValue::MergeImpl(*this, from); + } + private: + static void MergeImpl(::PROTOBUF_NAMESPACE_ID::Message& to_msg, const ::PROTOBUF_NAMESPACE_ID::Message& from_msg); + public: + PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + bool IsInitialized() const final; + + size_t ByteSizeLong() const final; + const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final; + uint8_t* _InternalSerialize( + uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final; + int GetCachedSize() const final { return _impl_._cached_size_.Get(); } + + private: + void SharedCtor(::PROTOBUF_NAMESPACE_ID::Arena* arena, bool is_message_owned); + void SharedDtor(); + void SetCachedSize(int size) const final; + void InternalSwap(BoolValue* other); + + private: + friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata; + static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() { + return "google.protobuf.BoolValue"; + } + protected: + explicit BoolValue(::PROTOBUF_NAMESPACE_ID::Arena* arena, + bool is_message_owned = false); + public: + + static const ClassData _class_data_; + const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*GetClassData() const final; + + ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final; + + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + + enum : int { + kValueFieldNumber = 1, + }; + // bool value = 1; + void clear_value(); + bool value() const; + void set_value(bool value); + private: + bool _internal_value() const; + void _internal_set_value(bool value); + public: + + // @@protoc_insertion_point(class_scope:google.protobuf.BoolValue) + private: + class _Internal; + + template <typename T> friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper; + typedef void InternalArenaConstructable_; + typedef void DestructorSkippable_; + struct Impl_ { + bool value_; + mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_; + }; + union { Impl_ _impl_; }; + friend struct ::TableStruct_google_2fprotobuf_2fwrappers_2eproto; +}; +// ------------------------------------------------------------------- + +class PROTOBUF_EXPORT StringValue final : + public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.StringValue) */ { + public: + inline StringValue() : StringValue(nullptr) {} + ~StringValue() override; + explicit PROTOBUF_CONSTEXPR StringValue(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized); + + StringValue(const StringValue& from); + StringValue(StringValue&& from) noexcept + : StringValue() { + *this = ::std::move(from); + } + + inline StringValue& operator=(const StringValue& from) { + CopyFrom(from); + return *this; + } + inline StringValue& operator=(StringValue&& from) noexcept { + if (this == &from) return *this; + if (GetOwningArena() == from.GetOwningArena() + #ifdef PROTOBUF_FORCE_COPY_IN_MOVE + && GetOwningArena() != nullptr + #endif // !PROTOBUF_FORCE_COPY_IN_MOVE + ) { + InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* descriptor() { + return GetDescriptor(); + } + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() { + return default_instance().GetMetadata().descriptor; + } + static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() { + return default_instance().GetMetadata().reflection; + } + static const StringValue& default_instance() { + return *internal_default_instance(); + } + static inline const StringValue* internal_default_instance() { + return reinterpret_cast<const StringValue*>( + &_StringValue_default_instance_); + } + static constexpr int kIndexInFileMessages = + 7; + + friend void swap(StringValue& a, StringValue& b) { + a.Swap(&b); + } + inline void Swap(StringValue* other) { + if (other == this) return; + #ifdef PROTOBUF_FORCE_COPY_IN_SWAP + if (GetOwningArena() != nullptr && + GetOwningArena() == other->GetOwningArena()) { + #else // PROTOBUF_FORCE_COPY_IN_SWAP + if (GetOwningArena() == other->GetOwningArena()) { + #endif // !PROTOBUF_FORCE_COPY_IN_SWAP + InternalSwap(other); + } else { + ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(StringValue* other) { + if (other == this) return; + GOOGLE_DCHECK(GetOwningArena() == other->GetOwningArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + StringValue* New(::PROTOBUF_NAMESPACE_ID::Arena* arena = nullptr) const final { + return CreateMaybeMessage<StringValue>(arena); + } + using ::PROTOBUF_NAMESPACE_ID::Message::CopyFrom; + void CopyFrom(const StringValue& from); + using ::PROTOBUF_NAMESPACE_ID::Message::MergeFrom; + void MergeFrom( const StringValue& from) { + StringValue::MergeImpl(*this, from); + } + private: + static void MergeImpl(::PROTOBUF_NAMESPACE_ID::Message& to_msg, const ::PROTOBUF_NAMESPACE_ID::Message& from_msg); + public: + PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + bool IsInitialized() const final; + + size_t ByteSizeLong() const final; + const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final; + uint8_t* _InternalSerialize( + uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final; + int GetCachedSize() const final { return _impl_._cached_size_.Get(); } + + private: + void SharedCtor(::PROTOBUF_NAMESPACE_ID::Arena* arena, bool is_message_owned); + void SharedDtor(); + void SetCachedSize(int size) const final; + void InternalSwap(StringValue* other); + + private: + friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata; + static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() { + return "google.protobuf.StringValue"; + } + protected: + explicit StringValue(::PROTOBUF_NAMESPACE_ID::Arena* arena, + bool is_message_owned = false); + public: + + static const ClassData _class_data_; + const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*GetClassData() const final; + + ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final; + + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + + enum : int { + kValueFieldNumber = 1, + }; + // string value = 1; + void clear_value(); + const std::string& value() const; + template <typename ArgT0 = const std::string&, typename... ArgT> + void set_value(ArgT0&& arg0, ArgT... args); + std::string* mutable_value(); + PROTOBUF_NODISCARD std::string* release_value(); + void set_allocated_value(std::string* value); + private: + const std::string& _internal_value() const; + inline PROTOBUF_ALWAYS_INLINE void _internal_set_value(const std::string& value); + std::string* _internal_mutable_value(); + public: + + // @@protoc_insertion_point(class_scope:google.protobuf.StringValue) + private: + class _Internal; + + template <typename T> friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper; + typedef void InternalArenaConstructable_; + typedef void DestructorSkippable_; + struct Impl_ { + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr value_; + mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_; + }; + union { Impl_ _impl_; }; + friend struct ::TableStruct_google_2fprotobuf_2fwrappers_2eproto; +}; +// ------------------------------------------------------------------- + +class PROTOBUF_EXPORT BytesValue final : + public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.BytesValue) */ { + public: + inline BytesValue() : BytesValue(nullptr) {} + ~BytesValue() override; + explicit PROTOBUF_CONSTEXPR BytesValue(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized); + + BytesValue(const BytesValue& from); + BytesValue(BytesValue&& from) noexcept + : BytesValue() { + *this = ::std::move(from); + } + + inline BytesValue& operator=(const BytesValue& from) { + CopyFrom(from); + return *this; + } + inline BytesValue& operator=(BytesValue&& from) noexcept { + if (this == &from) return *this; + if (GetOwningArena() == from.GetOwningArena() + #ifdef PROTOBUF_FORCE_COPY_IN_MOVE + && GetOwningArena() != nullptr + #endif // !PROTOBUF_FORCE_COPY_IN_MOVE + ) { + InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* descriptor() { + return GetDescriptor(); + } + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() { + return default_instance().GetMetadata().descriptor; + } + static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() { + return default_instance().GetMetadata().reflection; + } + static const BytesValue& default_instance() { + return *internal_default_instance(); + } + static inline const BytesValue* internal_default_instance() { + return reinterpret_cast<const BytesValue*>( + &_BytesValue_default_instance_); + } + static constexpr int kIndexInFileMessages = + 8; + + friend void swap(BytesValue& a, BytesValue& b) { + a.Swap(&b); + } + inline void Swap(BytesValue* other) { + if (other == this) return; + #ifdef PROTOBUF_FORCE_COPY_IN_SWAP + if (GetOwningArena() != nullptr && + GetOwningArena() == other->GetOwningArena()) { + #else // PROTOBUF_FORCE_COPY_IN_SWAP + if (GetOwningArena() == other->GetOwningArena()) { + #endif // !PROTOBUF_FORCE_COPY_IN_SWAP + InternalSwap(other); + } else { + ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(BytesValue* other) { + if (other == this) return; + GOOGLE_DCHECK(GetOwningArena() == other->GetOwningArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + BytesValue* New(::PROTOBUF_NAMESPACE_ID::Arena* arena = nullptr) const final { + return CreateMaybeMessage<BytesValue>(arena); + } + using ::PROTOBUF_NAMESPACE_ID::Message::CopyFrom; + void CopyFrom(const BytesValue& from); + using ::PROTOBUF_NAMESPACE_ID::Message::MergeFrom; + void MergeFrom( const BytesValue& from) { + BytesValue::MergeImpl(*this, from); + } + private: + static void MergeImpl(::PROTOBUF_NAMESPACE_ID::Message& to_msg, const ::PROTOBUF_NAMESPACE_ID::Message& from_msg); + public: + PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + bool IsInitialized() const final; + + size_t ByteSizeLong() const final; + const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final; + uint8_t* _InternalSerialize( + uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final; + int GetCachedSize() const final { return _impl_._cached_size_.Get(); } + + private: + void SharedCtor(::PROTOBUF_NAMESPACE_ID::Arena* arena, bool is_message_owned); + void SharedDtor(); + void SetCachedSize(int size) const final; + void InternalSwap(BytesValue* other); + + private: + friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata; + static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() { + return "google.protobuf.BytesValue"; + } + protected: + explicit BytesValue(::PROTOBUF_NAMESPACE_ID::Arena* arena, + bool is_message_owned = false); + public: + + static const ClassData _class_data_; + const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*GetClassData() const final; + + ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final; + + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + + enum : int { + kValueFieldNumber = 1, + }; + // bytes value = 1; + void clear_value(); + const std::string& value() const; + template <typename ArgT0 = const std::string&, typename... ArgT> + void set_value(ArgT0&& arg0, ArgT... args); + std::string* mutable_value(); + PROTOBUF_NODISCARD std::string* release_value(); + void set_allocated_value(std::string* value); + private: + const std::string& _internal_value() const; + inline PROTOBUF_ALWAYS_INLINE void _internal_set_value(const std::string& value); + std::string* _internal_mutable_value(); + public: + + // @@protoc_insertion_point(class_scope:google.protobuf.BytesValue) + private: + class _Internal; + + template <typename T> friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper; + typedef void InternalArenaConstructable_; + typedef void DestructorSkippable_; + struct Impl_ { + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr value_; + mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_; + }; + union { Impl_ _impl_; }; + friend struct ::TableStruct_google_2fprotobuf_2fwrappers_2eproto; +}; +// =================================================================== + + +// =================================================================== + +#ifdef __GNUC__ + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wstrict-aliasing" +#endif // __GNUC__ +// DoubleValue + +// double value = 1; +inline void DoubleValue::clear_value() { + _impl_.value_ = 0; +} +inline double DoubleValue::_internal_value() const { + return _impl_.value_; +} +inline double DoubleValue::value() const { + // @@protoc_insertion_point(field_get:google.protobuf.DoubleValue.value) + return _internal_value(); +} +inline void DoubleValue::_internal_set_value(double value) { + + _impl_.value_ = value; +} +inline void DoubleValue::set_value(double value) { + _internal_set_value(value); + // @@protoc_insertion_point(field_set:google.protobuf.DoubleValue.value) +} + +// ------------------------------------------------------------------- + +// FloatValue + +// float value = 1; +inline void FloatValue::clear_value() { + _impl_.value_ = 0; +} +inline float FloatValue::_internal_value() const { + return _impl_.value_; +} +inline float FloatValue::value() const { + // @@protoc_insertion_point(field_get:google.protobuf.FloatValue.value) + return _internal_value(); +} +inline void FloatValue::_internal_set_value(float value) { + + _impl_.value_ = value; +} +inline void FloatValue::set_value(float value) { + _internal_set_value(value); + // @@protoc_insertion_point(field_set:google.protobuf.FloatValue.value) +} + +// ------------------------------------------------------------------- + +// Int64Value + +// int64 value = 1; +inline void Int64Value::clear_value() { + _impl_.value_ = int64_t{0}; +} +inline int64_t Int64Value::_internal_value() const { + return _impl_.value_; +} +inline int64_t Int64Value::value() const { + // @@protoc_insertion_point(field_get:google.protobuf.Int64Value.value) + return _internal_value(); +} +inline void Int64Value::_internal_set_value(int64_t value) { + + _impl_.value_ = value; +} +inline void Int64Value::set_value(int64_t value) { + _internal_set_value(value); + // @@protoc_insertion_point(field_set:google.protobuf.Int64Value.value) +} + +// ------------------------------------------------------------------- + +// UInt64Value + +// uint64 value = 1; +inline void UInt64Value::clear_value() { + _impl_.value_ = uint64_t{0u}; +} +inline uint64_t UInt64Value::_internal_value() const { + return _impl_.value_; +} +inline uint64_t UInt64Value::value() const { + // @@protoc_insertion_point(field_get:google.protobuf.UInt64Value.value) + return _internal_value(); +} +inline void UInt64Value::_internal_set_value(uint64_t value) { + + _impl_.value_ = value; +} +inline void UInt64Value::set_value(uint64_t value) { + _internal_set_value(value); + // @@protoc_insertion_point(field_set:google.protobuf.UInt64Value.value) +} + +// ------------------------------------------------------------------- + +// Int32Value + +// int32 value = 1; +inline void Int32Value::clear_value() { + _impl_.value_ = 0; +} +inline int32_t Int32Value::_internal_value() const { + return _impl_.value_; +} +inline int32_t Int32Value::value() const { + // @@protoc_insertion_point(field_get:google.protobuf.Int32Value.value) + return _internal_value(); +} +inline void Int32Value::_internal_set_value(int32_t value) { + + _impl_.value_ = value; +} +inline void Int32Value::set_value(int32_t value) { + _internal_set_value(value); + // @@protoc_insertion_point(field_set:google.protobuf.Int32Value.value) +} + +// ------------------------------------------------------------------- + +// UInt32Value + +// uint32 value = 1; +inline void UInt32Value::clear_value() { + _impl_.value_ = 0u; +} +inline uint32_t UInt32Value::_internal_value() const { + return _impl_.value_; +} +inline uint32_t UInt32Value::value() const { + // @@protoc_insertion_point(field_get:google.protobuf.UInt32Value.value) + return _internal_value(); +} +inline void UInt32Value::_internal_set_value(uint32_t value) { + + _impl_.value_ = value; +} +inline void UInt32Value::set_value(uint32_t value) { + _internal_set_value(value); + // @@protoc_insertion_point(field_set:google.protobuf.UInt32Value.value) +} + +// ------------------------------------------------------------------- + +// BoolValue + +// bool value = 1; +inline void BoolValue::clear_value() { + _impl_.value_ = false; +} +inline bool BoolValue::_internal_value() const { + return _impl_.value_; +} +inline bool BoolValue::value() const { + // @@protoc_insertion_point(field_get:google.protobuf.BoolValue.value) + return _internal_value(); +} +inline void BoolValue::_internal_set_value(bool value) { + + _impl_.value_ = value; +} +inline void BoolValue::set_value(bool value) { + _internal_set_value(value); + // @@protoc_insertion_point(field_set:google.protobuf.BoolValue.value) +} + +// ------------------------------------------------------------------- + +// StringValue + +// string value = 1; +inline void StringValue::clear_value() { + _impl_.value_.ClearToEmpty(); +} +inline const std::string& StringValue::value() const { + // @@protoc_insertion_point(field_get:google.protobuf.StringValue.value) + return _internal_value(); +} +template <typename ArgT0, typename... ArgT> +inline PROTOBUF_ALWAYS_INLINE +void StringValue::set_value(ArgT0&& arg0, ArgT... args) { + + _impl_.value_.Set(static_cast<ArgT0 &&>(arg0), args..., GetArenaForAllocation()); + // @@protoc_insertion_point(field_set:google.protobuf.StringValue.value) +} +inline std::string* StringValue::mutable_value() { + std::string* _s = _internal_mutable_value(); + // @@protoc_insertion_point(field_mutable:google.protobuf.StringValue.value) + return _s; +} +inline const std::string& StringValue::_internal_value() const { + return _impl_.value_.Get(); +} +inline void StringValue::_internal_set_value(const std::string& value) { + + _impl_.value_.Set(value, GetArenaForAllocation()); +} +inline std::string* StringValue::_internal_mutable_value() { + + return _impl_.value_.Mutable(GetArenaForAllocation()); +} +inline std::string* StringValue::release_value() { + // @@protoc_insertion_point(field_release:google.protobuf.StringValue.value) + return _impl_.value_.Release(); +} +inline void StringValue::set_allocated_value(std::string* value) { + if (value != nullptr) { + + } else { + + } + _impl_.value_.SetAllocated(value, GetArenaForAllocation()); +#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (_impl_.value_.IsDefault()) { + _impl_.value_.Set("", GetArenaForAllocation()); + } +#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + // @@protoc_insertion_point(field_set_allocated:google.protobuf.StringValue.value) +} + +// ------------------------------------------------------------------- + +// BytesValue + +// bytes value = 1; +inline void BytesValue::clear_value() { + _impl_.value_.ClearToEmpty(); +} +inline const std::string& BytesValue::value() const { + // @@protoc_insertion_point(field_get:google.protobuf.BytesValue.value) + return _internal_value(); +} +template <typename ArgT0, typename... ArgT> +inline PROTOBUF_ALWAYS_INLINE +void BytesValue::set_value(ArgT0&& arg0, ArgT... args) { + + _impl_.value_.SetBytes(static_cast<ArgT0 &&>(arg0), args..., GetArenaForAllocation()); + // @@protoc_insertion_point(field_set:google.protobuf.BytesValue.value) +} +inline std::string* BytesValue::mutable_value() { + std::string* _s = _internal_mutable_value(); + // @@protoc_insertion_point(field_mutable:google.protobuf.BytesValue.value) + return _s; +} +inline const std::string& BytesValue::_internal_value() const { + return _impl_.value_.Get(); +} +inline void BytesValue::_internal_set_value(const std::string& value) { + + _impl_.value_.Set(value, GetArenaForAllocation()); +} +inline std::string* BytesValue::_internal_mutable_value() { + + return _impl_.value_.Mutable(GetArenaForAllocation()); +} +inline std::string* BytesValue::release_value() { + // @@protoc_insertion_point(field_release:google.protobuf.BytesValue.value) + return _impl_.value_.Release(); +} +inline void BytesValue::set_allocated_value(std::string* value) { + if (value != nullptr) { + + } else { + + } + _impl_.value_.SetAllocated(value, GetArenaForAllocation()); +#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (_impl_.value_.IsDefault()) { + _impl_.value_.Set("", GetArenaForAllocation()); + } +#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + // @@protoc_insertion_point(field_set_allocated:google.protobuf.BytesValue.value) +} + +#ifdef __GNUC__ + #pragma GCC diagnostic pop +#endif // __GNUC__ +// ------------------------------------------------------------------- + +// ------------------------------------------------------------------- + +// ------------------------------------------------------------------- + +// ------------------------------------------------------------------- + +// ------------------------------------------------------------------- + +// ------------------------------------------------------------------- + +// ------------------------------------------------------------------- + +// ------------------------------------------------------------------- + + +// @@protoc_insertion_point(namespace_scope) + +PROTOBUF_NAMESPACE_CLOSE + +// @@protoc_insertion_point(global_scope) + +#include <google/protobuf/port_undef.inc> +#endif // GOOGLE_PROTOBUF_INCLUDED_GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2fwrappers_2eproto diff --git a/toolkit/components/protobuf/src/google/protobuf/wrappers.proto b/toolkit/components/protobuf/src/google/protobuf/wrappers.proto new file mode 100644 index 0000000000..d49dd53c8d --- /dev/null +++ b/toolkit/components/protobuf/src/google/protobuf/wrappers.proto @@ -0,0 +1,123 @@ +// 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. + +// Wrappers for primitive (non-message) types. These types are useful +// for embedding primitives in the `google.protobuf.Any` type and for places +// where we need to distinguish between the absence of a primitive +// typed field and its default value. +// +// These wrappers have no meaningful use within repeated fields as they lack +// the ability to detect presence on individual elements. +// These wrappers have no meaningful use within a map or a oneof since +// individual entries of a map or fields of a oneof can already detect presence. + +syntax = "proto3"; + +package google.protobuf; + +option csharp_namespace = "Google.Protobuf.WellKnownTypes"; +option cc_enable_arenas = true; +option go_package = "google.golang.org/protobuf/types/known/wrapperspb"; +option java_package = "com.google.protobuf"; +option java_outer_classname = "WrappersProto"; +option java_multiple_files = true; +option objc_class_prefix = "GPB"; + +// Wrapper message for `double`. +// +// The JSON representation for `DoubleValue` is JSON number. +message DoubleValue { + // The double value. + double value = 1; +} + +// Wrapper message for `float`. +// +// The JSON representation for `FloatValue` is JSON number. +message FloatValue { + // The float value. + float value = 1; +} + +// Wrapper message for `int64`. +// +// The JSON representation for `Int64Value` is JSON string. +message Int64Value { + // The int64 value. + int64 value = 1; +} + +// Wrapper message for `uint64`. +// +// The JSON representation for `UInt64Value` is JSON string. +message UInt64Value { + // The uint64 value. + uint64 value = 1; +} + +// Wrapper message for `int32`. +// +// The JSON representation for `Int32Value` is JSON number. +message Int32Value { + // The int32 value. + int32 value = 1; +} + +// Wrapper message for `uint32`. +// +// The JSON representation for `UInt32Value` is JSON number. +message UInt32Value { + // The uint32 value. + uint32 value = 1; +} + +// Wrapper message for `bool`. +// +// The JSON representation for `BoolValue` is JSON `true` and `false`. +message BoolValue { + // The bool value. + bool value = 1; +} + +// Wrapper message for `string`. +// +// The JSON representation for `StringValue` is JSON string. +message StringValue { + // The string value. + string value = 1; +} + +// Wrapper message for `bytes`. +// +// The JSON representation for `BytesValue` is JSON string. +message BytesValue { + // The bytes value. + bytes value = 1; +} diff --git a/toolkit/components/protobuf/upgrade_protobuf.sh b/toolkit/components/protobuf/upgrade_protobuf.sh new file mode 100755 index 0000000000..6d071f43b8 --- /dev/null +++ b/toolkit/components/protobuf/upgrade_protobuf.sh @@ -0,0 +1,75 @@ +#!/usr/bin/env bash + +set -e + +usage() { + echo "Usage: upgrade_protobuf.sh path/to/protobuf" + echo + echo " Upgrades mozilla-central's copy of the protobuf library." + echo + echo " Get a protobuf release from here:" + echo " https://github.com/google/protobuf/releases" +} + +if [[ "$#" -ne 1 ]]; then + usage + exit 1 +fi + +PROTOBUF_LIB_PATH=$1 + +if [[ ! -d "$PROTOBUF_LIB_PATH" ]]; then + echo No such directory: $PROTOBUF_LIB_PATH + echo + usage + exit 1 +fi + +realpath() { + if [[ $1 = /* ]]; then + echo "$1" + else + echo "$PWD/${1#./}" + fi +} + +PROTOBUF_LIB_PATH=$(realpath $PROTOBUF_LIB_PATH) + +cd $(dirname $0) + +# Remove the old protobuf sources. +rm -rf src/google/* + +# Add all the new protobuf sources. +cp -r $PROTOBUF_LIB_PATH/src/google/* src/google/ + +# Remove compiler sources. +rm -rf src/google/protobuf/compiler + +# Remove test files. +find src/google -name '*_unittest*' | xargs rm -f +find src/google -name '*unittest_*' | xargs rm -f +find src/google -name 'unittest.*' | xargs rm -f +find src/google -name '*_test*' | xargs rm -f +find src/google -name '*test_*' | xargs rm -f +find src/google -type d -name 'testdata' | xargs rm -rf +find src/google -type d -name 'testing' | xargs rm -rf + +# Remove protobuf's build files. +find src/google/ -name '.deps' | xargs rm -rf +find src/google/ -name '.dirstamp' | xargs rm -rf +rm -rf src/google/protobuf/SEBS + +# Apply custom changes for building as part of mozilla-central. + +echo +echo Applying custom changes for mozilla-central. If this fails, you need to +echo edit the 'toolkit/components/protobuf/src/google/*' sources manually and +echo update the 'toolkit/components/protobuf/*.patch' patch file +echo accordingly. +echo + +patch -p4 < 14174.patch + +echo +echo Successfully upgraded the protobuf lib! |