32 utils::function_ref<
void(google::protobuf::Message&,
const google::protobuf::FieldDescriptor&)>;
85 void Compile(
const google::protobuf::Descriptor* descriptor);
88 void Compile(
const DescriptorList& descriptors);
108 using Dependencies = std::unordered_map<
109 const google::protobuf::Descriptor*,
110 std::unordered_set<
const google::protobuf::FieldDescriptor*>>;
113 using DescriptorSet = std::unordered_set<
const google::protobuf::Descriptor*>;
116 using FieldDescriptorSet = std::unordered_set<
const google::protobuf::FieldDescriptor*>;
119 const Dependencies& GetFieldsWithSelectedChildren(
utils::impl::InternalTag)
const;
122 const Dependencies& GetReverseEdges(
utils::impl::InternalTag)
const;
125 const DescriptorSet& GetPropagated(
utils::impl::InternalTag)
const;
128 const DescriptorSet& GetCompiled(
utils::impl::InternalTag)
const;
131 explicit VisitorCompiler(
LockBehavior lock_behavior) : lock_behavior_(lock_behavior) {}
134 ~VisitorCompiler() =
default;
137 std::shared_lock<engine::SharedMutex> LockRead();
140 std::unique_lock<engine::SharedMutex> LockWrite();
142 const Dependencies& GetFieldsWithSelectedChildren()
const {
return fields_with_selected_children_; }
146 virtual void CompileOne(
const google::protobuf::Descriptor& descriptor) = 0;
149 virtual bool IsSelected(
const google::protobuf::Descriptor&)
const = 0;
153 DescriptorSet GetFullSubtrees(
const DescriptorList& descriptors)
const;
156 void PropagateSelected(
const google::protobuf::Descriptor* descriptor);
158 engine::SharedMutex mutex_;
161 Dependencies fields_with_selected_children_;
162 Dependencies reverse_edges_;
163 DescriptorSet propagated_;
164 DescriptorSet compiled_;
176 void Visit(google::protobuf::Message& message, Callback callback) {
178 Compile(message.GetDescriptor());
180 const std::shared_lock read_lock = LockRead();
190 Compile(message.GetDescriptor());
192 constexpr int kMaxRecursionLimit = 100;
193 const std::shared_lock read_lock = LockRead();
194 VisitRecursiveImpl(message, callback, kMaxRecursionLimit);
201 ~BaseVisitor() =
default;
204 virtual void DoVisit(google::protobuf::Message& message, Callback callback)
const = 0;
208 void VisitRecursiveImpl(google::protobuf::Message& message, Callback callback,
int recursion_limit) {
209 UINVARIANT(recursion_limit > 0,
"Recursion limit reached while traversing protobuf Message.");
215 const auto it = GetFieldsWithSelectedChildren().find(message.GetDescriptor());
216 if (it == GetFieldsWithSelectedChildren().end())
return;
218 const FieldDescriptorSet& fields = it->second;
219 for (
const google::protobuf::FieldDescriptor* field : fields) {
221 VisitNestedMessage(message, *field, [&](google::protobuf::Message& msg) {
222 VisitRecursiveImpl(msg, callback, recursion_limit - 1);
242class FieldsVisitor
final :
public BaseVisitor<FieldVisitCallback> {
244 using Selector =
utils::function_ref<
bool(
const google::protobuf::FieldDescriptor& field)>;
268 const Dependencies& GetSelectedFields(
utils::impl::InternalTag)
const;
272 void CompileOne(
const google::protobuf::Descriptor& descriptor)
override;
274 bool IsSelected(
const google::protobuf::Descriptor& descriptor)
const override {
275 return selected_fields_.find(&descriptor) != selected_fields_.end();
278 void DoVisit(google::protobuf::Message& message, FieldVisitCallback callback)
const override;
280 Dependencies selected_fields_;
281 const Selector selector_;
295class MessagesVisitor
final :
public BaseVisitor<MessageVisitCallback> {
297 using Selector =
utils::function_ref<
bool(
const google::protobuf::Descriptor& descriptor)>;
321 const DescriptorSet& GetSelectedMessages(
utils::impl::InternalTag)
const;
325 void CompileOne(
const google::protobuf::Descriptor& descriptor)
override;
327 bool IsSelected(
const google::protobuf::Descriptor& descriptor)
const override {
328 return selected_messages_.find(&descriptor) != selected_messages_.end();
331 void DoVisit(google::protobuf::Message& message, MessageVisitCallback callback)
const override;
333 DescriptorSet selected_messages_;
334 const Selector selector_;