32 void(google::protobuf::Message&,
const google::protobuf::FieldDescriptor&)>;
87 void Compile(
const google::protobuf::Descriptor* descriptor);
90 void Compile(
const DescriptorList& descriptors);
110 using Dependencies = std::unordered_map<
111 const google::protobuf::Descriptor*,
112 std::unordered_set<
const google::protobuf::FieldDescriptor*>>;
115 using DescriptorSet = std::unordered_set<
const google::protobuf::Descriptor*>;
118 using FieldDescriptorSet = std::unordered_set<
const google::protobuf::FieldDescriptor*>;
121 const Dependencies& GetFieldsWithSelectedChildren(utils::
impl::InternalTag)
const;
124 const Dependencies& GetReverseEdges(utils::
impl::InternalTag)
const;
127 const DescriptorSet& GetPropagated(utils::
impl::InternalTag)
const;
130 const DescriptorSet& GetCompiled(utils::
impl::InternalTag)
const;
134 : lock_behavior_(lock_behavior)
138 ~VisitorCompiler() =
default;
141 std::shared_lock<
engine::SharedMutex> LockRead();
144 std::unique_lock<
engine::SharedMutex> LockWrite();
146 const Dependencies& GetFieldsWithSelectedChildren()
const {
return fields_with_selected_children_; }
150 virtual void CompileOne(
const google::protobuf::Descriptor& descriptor) = 0;
153 virtual bool IsSelected(
const google::protobuf::Descriptor&)
const = 0;
157 DescriptorSet GetFullSubtrees(
const DescriptorList& descriptors)
const;
160 void PropagateSelected(
const google::protobuf::Descriptor* descriptor);
162 engine::SharedMutex mutex_;
165 Dependencies fields_with_selected_children_;
166 Dependencies reverse_edges_;
167 DescriptorSet propagated_;
168 DescriptorSet compiled_;
180 void Visit(google::protobuf::Message& message, Callback callback) {
182 Compile(message.GetDescriptor());
184 const std::shared_lock read_lock = LockRead();
194 Compile(message.GetDescriptor());
196 constexpr int kMaxRecursionLimit = 100;
197 const std::shared_lock read_lock = LockRead();
198 VisitRecursiveImpl(message, callback, kMaxRecursionLimit);
207 ~BaseVisitor() =
default;
210 virtual void DoVisit(google::protobuf::Message& message, Callback callback)
const = 0;
214 void VisitRecursiveImpl(google::protobuf::Message& message, Callback callback,
int recursion_limit) {
215 UINVARIANT(recursion_limit > 0,
"Recursion limit reached while traversing protobuf Message.");
221 const auto it = GetFieldsWithSelectedChildren().find(message.GetDescriptor());
222 if (it == GetFieldsWithSelectedChildren().end()) {
226 const FieldDescriptorSet& fields = it->second;
227 for (
const google::protobuf::FieldDescriptor* field : fields) {
229 VisitNestedMessage(message, *field, [&](google::protobuf::Message& msg) {
230 VisitRecursiveImpl(msg, callback, recursion_limit - 1);
250class FieldsVisitor
final :
public BaseVisitor<FieldVisitCallback> {
252 using Selector = utils::function_ref<
bool(
const google::protobuf::FieldDescriptor& field)>;
276 const Dependencies& GetSelectedFields(utils::
impl::InternalTag)
const;
280 void CompileOne(
const google::protobuf::Descriptor& descriptor)
override;
282 bool IsSelected(
const google::protobuf::Descriptor& descriptor)
const override {
283 return selected_fields_.find(&descriptor) != selected_fields_.end();
286 void DoVisit(google::protobuf::Message& message, FieldVisitCallback callback)
const override;
288 Dependencies selected_fields_;
289 const Selector selector_;
303class MessagesVisitor
final :
public BaseVisitor<MessageVisitCallback> {
305 using Selector = utils::function_ref<
bool(
const google::protobuf::Descriptor& descriptor)>;
329 const DescriptorSet& GetSelectedMessages(utils::
impl::InternalTag)
const;
333 void CompileOne(
const google::protobuf::Descriptor& descriptor)
override;
335 bool IsSelected(
const google::protobuf::Descriptor& descriptor)
const override {
336 return selected_messages_.find(&descriptor) != selected_messages_.end();
339 void DoVisit(google::protobuf::Message& message, MessageVisitCallback callback)
const override;
341 DescriptorSet selected_messages_;
342 const Selector selector_;