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_;