diff options
author | nechda <[email protected]> | 2024-08-29 23:50:27 +0300 |
---|---|---|
committer | nechda <[email protected]> | 2024-08-30 00:05:25 +0300 |
commit | e10d6638f07a82edae3ea8197b9f5c0affcc07ea (patch) | |
tree | 571c38cec05813766a1ad290c9d51ce7ace52919 /contrib/libs/protoc/src/google/protobuf/compiler/cpp/tracker.cc | |
parent | e79b38f2bbbf78d295d1901d2a79f898022d5224 (diff) |
Update cpp-protobuf to 22.5
Привет!\
Этот PR переключат cpp & python библиотеки protobuf на версию 22.5
Если у вас возникли проблемы после влития этого PR:
1. Если начали падать канон тесты, то проведите их переканонизацию
2. Прочитайте <https://wiki.yandex-team.ru/users/nechda/obnovlenie-cpp-protobuf-22.5/> страничку с основными изменениями
3. Если страничка в вики не помогла, то пишите в [DEVTOOLSSUPPORT](https://st.yandex-team.ru/DEVTOOLSSUPPORT)
7fecade616c20a841b9e9af7b7998bdfc8d2807d
Diffstat (limited to 'contrib/libs/protoc/src/google/protobuf/compiler/cpp/tracker.cc')
-rw-r--r-- | contrib/libs/protoc/src/google/protobuf/compiler/cpp/tracker.cc | 339 |
1 files changed, 339 insertions, 0 deletions
diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/cpp/tracker.cc b/contrib/libs/protoc/src/google/protobuf/compiler/cpp/tracker.cc new file mode 100644 index 00000000000..77c45a8ee54 --- /dev/null +++ b/contrib/libs/protoc/src/google/protobuf/compiler/cpp/tracker.cc @@ -0,0 +1,339 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2022 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/compiler/cpp/tracker.h" + +#include <string> +#include <utility> +#include <vector> + +#include "google/protobuf/descriptor.h" +#include "y_absl/strings/str_cat.h" +#include "y_absl/strings/str_format.h" +#include "y_absl/strings/string_view.h" +#include "y_absl/strings/substitute.h" +#include "y_absl/types/optional.h" +#include "google/protobuf/compiler/cpp/helpers.h" +#include "google/protobuf/compiler/cpp/options.h" +#include "google/protobuf/io/printer.h" + +namespace google { +namespace protobuf { +namespace compiler { +namespace cpp { +namespace { +using Sub = ::google::protobuf::io::Printer::Sub; + +constexpr y_absl::string_view kTracker = "Impl_::_tracker_"; +constexpr y_absl::string_view kVarPrefix = "annotate_"; +constexpr y_absl::string_view kTypeTraits = "_proto_TypeTraits"; + +struct Call { + Call(y_absl::string_view var, y_absl::string_view call) : var(var), call(call) {} + Call(y_absl::optional<int> field_index, y_absl::string_view var, + y_absl::string_view call) + : var(var), call(call), field_index(field_index) {} + + Call This(y_absl::optional<y_absl::string_view> thiz) && { + this->thiz = thiz; + return std::move(*this); + } + + template <typename... SubArgs> + Call Arg(y_absl::string_view format, const SubArgs&... args) && { + this->args.emplace_back(y_absl::Substitute(format, args...)); + return std::move(*this); + } + + Call Suppressed() && { + suppressed = true; + return std::move(*this); + } + + y_absl::string_view var; + y_absl::string_view call; + y_absl::optional<int> field_index; + y_absl::optional<y_absl::string_view> thiz = "this"; + std::vector<TProtoStringType> args; + bool suppressed = false; +}; + +std::vector<Sub> GenerateTrackerCalls( + const Options& opts, const Descriptor* message, + y_absl::optional<TProtoStringType> alt_annotation, y_absl::Span<const Call> calls) { + bool enable_tracking = HasTracker(message, opts); + const auto& forbidden = + opts.field_listener_options.forbidden_field_listener_events; + + std::vector<Sub> subs; + for (const auto& call : calls) { + TProtoStringType call_str; + if (enable_tracking && !call.suppressed && !forbidden.contains(call.var)) { + y_absl::SubstituteAndAppend(&call_str, "$0.$1", kTracker, call.call); + if (call.field_index.has_value()) { + y_absl::SubstituteAndAppend(&call_str, "<$0>", *call.field_index); + } + y_absl::StrAppend(&call_str, "("); + + y_absl::string_view arg_sep = ""; + if (call.thiz.has_value()) { + y_absl::StrAppend(&call_str, *call.thiz); + arg_sep = ", "; + } + + for (const auto& arg : call.args) { + y_absl::StrAppend(&call_str, arg_sep, arg); + arg_sep = ", "; + } + + y_absl::StrAppend(&call_str, ");"); + } else if (opts.annotate_accessor && alt_annotation.has_value()) { + call_str = *alt_annotation; + } + + if (!call_str.empty()) { + // TODO(b/245791219): Until we migrate all of the C++ backend to use + // Emit(), we need to include a newline here so that the line that follows + // the annotation is on its own line. + call_str.push_back('\n'); + } + + subs.push_back( + Sub(y_absl::StrCat(kVarPrefix, call.var), call_str).WithSuffix(";")); + } + + return subs; +} +} // namespace + +std::vector<Sub> MakeTrackerCalls(const Descriptor* message, + const Options& opts) { + y_absl::string_view extns = + IsMapEntryMessage(message) ? "_extensions_" : "_impl_._extensions_"; + + auto primitive_extn_accessor = [extns](y_absl::string_view var, + y_absl::string_view call) { + return Call(var, call) + .Arg("id.number()") + .Arg("$0::GetPtr(id.number(), $1, id.default_value_ref())", kTypeTraits, + extns); + }; + + auto index_extn_accessor = [extns](y_absl::string_view var, + y_absl::string_view call) { + return Call(var, call) + .Arg("id.number()") + .Arg("$0::GetPtr(id.number(), $1, index)", kTypeTraits, extns); + }; + + auto add_extn_accessor = [extns](y_absl::string_view var, + y_absl::string_view call) { + return Call(var, call) + .Arg("id.number()") + .Arg("$0::GetPtr(id.number(), $1, $1.ExtensionSize(id.number()) - 1)", + kTypeTraits, extns); + }; + + auto list_extn_accessor = [extns](y_absl::string_view var, + y_absl::string_view call) { + return Call(var, call) + .Arg("id.number()") + .Arg("$0::GetRepeatedPtr(id.number(), $1)", kTypeTraits, extns); + }; + + return GenerateTrackerCalls( + opts, message, y_absl::nullopt, + { + Call("serialize", "OnSerialize"), + Call("deserialize", "OnDeserialize"), + // TODO(danilak): Ideally annotate_reflection should not exist and we + // need to annotate all reflective calls on our own, however, as this + // is a cause for side effects, i.e. reading values dynamically, we + // want the users know that dynamic access can happen. + Call("reflection", "OnGetMetadata").This(y_absl::nullopt), + Call("bytesize", "OnByteSize"), + Call("mergefrom", "OnMergeFrom").This("_this").Arg("&from"), + + // "Has" is here as users calling "has" on a repeated field is a + // mistake. + primitive_extn_accessor("extension_has", "OnHasExtension"), + primitive_extn_accessor("extension_get", "OnGetExtension"), + primitive_extn_accessor("extension_mutable", "OnMutableExtension"), + primitive_extn_accessor("extension_set", "OnSetExtension"), + primitive_extn_accessor("extension_release", "OnReleaseExtension"), + + index_extn_accessor("repeated_extension_get", "OnGetExtension"), + index_extn_accessor("repeated_extension_mutable", + "OnMutableExtension"), + index_extn_accessor("repeated_extension_set", "OnSetExtension"), + + add_extn_accessor("repeated_extension_add", "OnAddExtension"), + add_extn_accessor("repeated_extension_add_mutable", + "OnAddMutableExtension"), + + list_extn_accessor("extension_repeated_size", "OnExtensionSize"), + list_extn_accessor("repeated_extension_list", "OnListExtension"), + list_extn_accessor("repeated_extension_list_mutable", + "OnMutableListExtension"), + + // Generic accessors such as "clear". + // TODO(b/190614678): Generalize clear from both repeated and non + // repeated calls, currently their underlying memory interfaces are + // very different. Or think of removing clear callback as no usages + // are needed and no memory exist + Call("extension_clear", "OnClearExtension").Suppressed(), + }); +} + +namespace { +struct Getters { + TProtoStringType base = "nullptr"; + TProtoStringType for_last = "nullptr"; + TProtoStringType for_flat = "nullptr"; +}; + +Getters RepeatedFieldGetters(const FieldDescriptor* field, + const Options& opts) { + TProtoStringType member = FieldMemberName(field, ShouldSplit(field, opts)); + + Getters getters; + if (!field->is_map() && + field->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE) { + getters.base = y_absl::Substitute("&$0.Get(index)", member); + getters.for_last = y_absl::Substitute("&$0.Get($0.size() - 1)", member); + getters.for_flat = y_absl::StrCat("&", member); + } + + return getters; +} + +Getters StringFieldGetters(const FieldDescriptor* field, const Options& opts) { + TProtoStringType member = FieldMemberName(field, ShouldSplit(field, opts)); + bool is_std_string = field->options().ctype() == FieldOptions::STRING; + + Getters getters; + if (is_std_string && !field->default_value_string().empty()) { + getters.base = + y_absl::Substitute("$0.IsDefault() ? &$1.get() : $0.UnsafeGetPointer()", + member, MakeDefaultFieldName(field)); + } else { + getters.base = y_absl::StrCat("&", member); + } + + getters.for_flat = getters.base; + return getters; +} + +Getters StringOneofGetters(const FieldDescriptor* field, + const OneofDescriptor* oneof, const Options& opts) { + Y_ABSL_CHECK(oneof != nullptr); + + TProtoStringType member = FieldMemberName(field, ShouldSplit(field, opts)); + bool is_std_string = field->options().ctype() == FieldOptions::STRING; + + TProtoStringType field_ptr = member; + if (is_std_string) { + field_ptr = y_absl::Substitute("$0.UnsafeGetPointer()", member); + } + + TProtoStringType has = + y_absl::Substitute("$0_case() == k$1", oneof->name(), + UnderscoresToCamelCase(field->name(), true)); + + TProtoStringType default_field = MakeDefaultFieldName(field); + if (is_std_string) { + y_absl::StrAppend(&default_field, ".get()"); + } + + Getters getters; + if (field->default_value_string().empty() || + field->options().ctype() == FieldOptions::STRING_PIECE) { + getters.base = y_absl::Substitute("$0 ? $1 : nullptr", has, field_ptr); + } else { + getters.base = + y_absl::Substitute("$0 ? $1 : &$2", has, field_ptr, default_field); + } + + getters.for_flat = getters.base; + return getters; +} + +Getters SingularFieldGetters(const FieldDescriptor* field, + const Options& opts) { + TProtoStringType member = FieldMemberName(field, ShouldSplit(field, opts)); + + Getters getters; + getters.base = y_absl::StrCat("&", member); + if (field->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE) { + getters.for_flat = y_absl::StrCat("&", member); + } + return getters; +} +} // namespace + +std::vector<Sub> MakeTrackerCalls(const FieldDescriptor* field, + const Options& opts) { + Getters getters; + if (field->is_repeated()) { + getters = RepeatedFieldGetters(field, opts); + } else if (field->cpp_type() == FieldDescriptor::CPPTYPE_STRING) { + const auto* oneof = field->real_containing_oneof(); + if (oneof != nullptr) { + getters = StringOneofGetters(field, oneof, opts); + } else { + getters = StringFieldGetters(field, opts); + } + } else if (field->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE || + IsExplicitLazy(field)) { + getters = SingularFieldGetters(field, opts); + } + + auto index = field->index(); + return GenerateTrackerCalls( + opts, field->containing_type(), + y_absl::Substitute("$0_AccessedNoStrip = true;", FieldName(field)), + { + Call(index, "get", "OnGet").Arg(getters.base), + Call(index, "set", "OnSet").Arg(getters.base), + Call(index, "has", "OnHas").Arg(getters.base), + Call(index, "mutable", "OnMutable").Arg(getters.base), + Call(index, "release", "OnRelease").Arg(getters.base), + Call(index, "clear", "OnClear").Arg(getters.for_flat), + Call(index, "size", "OnSize").Arg(getters.for_flat), + Call(index, "list", "OnList").Arg(getters.for_flat), + Call(index, "mutable_list", "OnMutableList").Arg(getters.for_flat), + Call(index, "add", "OnAdd").Arg(getters.for_last), + Call(index, "add_mutable", "OnAddMutable").Arg(getters.for_last), + }); +} +} // namespace cpp +} // namespace compiler +} // namespace protobuf +} // namespace google |