summaryrefslogtreecommitdiffstats
path: root/contrib/libs/protoc/src/google/protobuf/compiler/cpp/tracker.cc
diff options
context:
space:
mode:
authornechda <[email protected]>2024-08-29 23:50:27 +0300
committernechda <[email protected]>2024-08-30 00:05:25 +0300
commite10d6638f07a82edae3ea8197b9f5c0affcc07ea (patch)
tree571c38cec05813766a1ad290c9d51ce7ace52919 /contrib/libs/protoc/src/google/protobuf/compiler/cpp/tracker.cc
parente79b38f2bbbf78d295d1901d2a79f898022d5224 (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.cc339
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