8#include <unordered_map>
9#include <unordered_set>
12#include <google/protobuf/stubs/common.h>
14#include <userver/utils/function_ref.hpp>
15#include <userver/utils/impl/internal_tag.hpp>
16#include <userver/utils/span.hpp>
18namespace google::protobuf {
26USERVER_NAMESPACE_BEGIN
30using MessageVisitCallback = utils::function_ref<
void(google::protobuf::Message&)>;
32using FieldVisitCallback =
33 utils::function_ref<
void(google::protobuf::Message&,
const google::protobuf::FieldDescriptor&)>;
36void VisitFields(google::protobuf::Message& message, FieldVisitCallback callback);
45using DescriptorList = std::vector<
const google::protobuf::Descriptor*>;
47using FieldDescriptorList = std::vector<
const google::protobuf::FieldDescriptor*>;
59const google::protobuf::FieldDescriptor*
60FindField(
const google::protobuf::Descriptor* descriptor, std::string_view field);
65template <
typename Callback>
82 void Compile(
const google::protobuf::Descriptor* descriptor);
86 void Compile(
const DescriptorList& descriptors);
90 void CompileGenerated(std::string_view message_name) { Compile(FindGeneratedMessage(message_name)); }
95 DescriptorList descriptors;
96 for (
const std::string_view& message_name : message_names) {
97 descriptors.push_back(FindGeneratedMessage(message_name));
106 void Visit(google::protobuf::Message& message, Callback callback);
127 const Dependencies& GetFieldsWithSelectedChildren(utils::impl::InternalTag)
const {
128 return fields_with_selected_children_;
132 const Dependencies& GetReverseEdges(utils::impl::InternalTag)
const {
return reverse_edges_; }
135 const DescriptorSet& GetPropagated(utils::impl::InternalTag)
const {
return propagated_; }
138 const DescriptorSet& GetCompiled(utils::impl::InternalTag)
const {
return compiled_; }
143 explicit BaseVisitor(
LockBehavior lock_behavior) : lock_behavior_(lock_behavior) {}
146 ~BaseVisitor() =
default;
149 virtual void CompileOne(
const google::protobuf::Descriptor& descriptor) = 0;
152 virtual bool IsSelected(
const google::protobuf::Descriptor&)
const = 0;
155 virtual void DoVisit(google::protobuf::Message& message, Callback callback) = 0;
160 DescriptorSet GetFullSubtrees(
const DescriptorList& descriptors)
const;
163 void PropagateSelected(
const google::protobuf::Descriptor* descriptor);
166 void VisitRecursiveImpl(google::protobuf::Message& message, Callback callback,
int recursion_limit);
168 std::shared_mutex mutex_;
171 Dependencies fields_with_selected_children_;
172 Dependencies reverse_edges_;
173 DescriptorSet propagated_;
174 DescriptorSet compiled_;
190class FieldsVisitor
final :
public BaseVisitor<FieldVisitCallback> {
192 using Selector = utils::function_ref<
193 bool(
const google::protobuf::Descriptor& descriptor,
const google::protobuf::FieldDescriptor& field)>;
213 FieldsVisitor(Selector selector,
const DescriptorList& descriptors, LockBehavior lock_behavior);
217 const Dependencies& GetSelectedFields(utils::impl::InternalTag)
const {
return selected_fields_; }
221 void CompileOne(
const google::protobuf::Descriptor& descriptor) override;
223 bool IsSelected(
const google::protobuf::Descriptor& descriptor)
const override {
224 return selected_fields_.find(&descriptor) != selected_fields_.end();
227 void DoVisit(google::protobuf::Message& message, FieldVisitCallback callback)
override;
229 Dependencies selected_fields_;
230 const Selector selector_;
244class MessagesVisitor
final :
public BaseVisitor<MessageVisitCallback> {
246 using Selector = utils::function_ref<
bool(
const google::protobuf::Descriptor& descriptor)>;
266 MessagesVisitor(Selector selector,
const DescriptorList& descriptors, LockBehavior lock_behavior);
270 const DescriptorSet& GetSelectedMessages(utils::impl::InternalTag)
const {
return selected_messages_; }
274 void CompileOne(
const google::protobuf::Descriptor& descriptor) override;
276 bool IsSelected(
const google::protobuf::Descriptor& descriptor)
const override {
277 return selected_messages_.find(&descriptor) != selected_messages_.end();
280 void DoVisit(google::protobuf::Message& message, MessageVisitCallback callback)
override;
282 DescriptorSet selected_messages_;
283 const Selector selector_;