Coverage Report

Created: 2023-11-12 09:30

/proc/self/cwd/source/common/protobuf/visitor.cc
Line
Count
Source (jump to first uncovered line)
1
#include "source/common/protobuf/visitor.h"
2
3
#include <vector>
4
5
#include "source/common/protobuf/utility.h"
6
#include "source/common/protobuf/visitor_helper.h"
7
8
#include "udpa/type/v1/typed_struct.pb.h"
9
#include "xds/type/v3/typed_struct.pb.h"
10
11
namespace Envoy {
12
namespace ProtobufMessage {
13
namespace {
14
15
void traverseMessageWorker(ConstProtoVisitor& visitor, const Protobuf::Message& message,
16
                           std::vector<const Protobuf::Message*>& parents,
17
10.1M
                           bool was_any_or_top_level, bool recurse_into_any) {
18
10.1M
  visitor.onMessage(message, parents, was_any_or_top_level);
19
20
  // If told to recurse into Any messages, do that here and skip the rest of the function.
21
10.1M
  if (recurse_into_any) {
22
0
    std::unique_ptr<Protobuf::Message> inner_message;
23
0
    absl::string_view target_type_url;
24
25
0
    if (message.GetTypeName() == "google.protobuf.Any") {
26
0
      auto* any_message = Protobuf::DynamicCastToGenerated<ProtobufWkt::Any>(&message);
27
0
      inner_message = Helper::typeUrlToMessage(any_message->type_url());
28
0
      target_type_url = any_message->type_url();
29
      // inner_message must be valid as parsing would have already failed to load if there was an
30
      // invalid type_url.
31
0
      MessageUtil::unpackTo(*any_message, *inner_message);
32
0
    } else if (message.GetTypeName() == "xds.type.v3.TypedStruct") {
33
0
      std::tie(inner_message, target_type_url) =
34
0
          Helper::convertTypedStruct<xds::type::v3::TypedStruct>(message);
35
0
    } else if (message.GetTypeName() == "udpa.type.v1.TypedStruct") {
36
0
      std::tie(inner_message, target_type_url) =
37
0
          Helper::convertTypedStruct<udpa::type::v1::TypedStruct>(message);
38
0
    }
39
40
0
    if (inner_message != nullptr) {
41
      // Push the Any message as a wrapper.
42
0
      Helper::ScopedMessageParents scoped_parents(parents, message);
43
0
      traverseMessageWorker(visitor, *inner_message, parents, true, recurse_into_any);
44
0
      return;
45
0
    } else if (!target_type_url.empty()) {
46
0
      throwEnvoyExceptionOrPanic(
47
0
          fmt::format("Invalid type_url '{}' during traversal", target_type_url));
48
0
    }
49
0
  }
50
10.1M
  Protobuf::ReflectableMessage reflectable_message = createReflectableMessage(message);
51
10.1M
  const Protobuf::Descriptor* descriptor = reflectable_message->GetDescriptor();
52
10.1M
  const Protobuf::Reflection* reflection = reflectable_message->GetReflection();
53
54.7M
  for (int i = 0; i < descriptor->field_count(); ++i) {
54
44.5M
    const Protobuf::FieldDescriptor* field = descriptor->field(i);
55
44.5M
    visitor.onField(message, *field);
56
57
    // If this is a message, recurse in to the sub-message.
58
44.5M
    if (field->cpp_type() == Protobuf::FieldDescriptor::CPPTYPE_MESSAGE) {
59
25.9M
      Helper::ScopedMessageParents scoped_parents(parents, message);
60
61
25.9M
      if (field->is_repeated()) {
62
2.87M
        const int size = reflection->FieldSize(*reflectable_message, field);
63
7.69M
        for (int j = 0; j < size; ++j) {
64
4.82M
          traverseMessageWorker(visitor,
65
4.82M
                                reflection->GetRepeatedMessage(*reflectable_message, field, j),
66
4.82M
                                parents, false, recurse_into_any);
67
4.82M
        }
68
23.0M
      } else if (reflection->HasField(*reflectable_message, field)) {
69
5.05M
        traverseMessageWorker(visitor, reflection->GetMessage(*reflectable_message, field), parents,
70
5.05M
                              false, recurse_into_any);
71
5.05M
      }
72
25.9M
    }
73
44.5M
  }
74
10.1M
}
75
76
} // namespace
77
78
void traverseMessage(ConstProtoVisitor& visitor, const Protobuf::Message& message,
79
274k
                     bool recurse_into_any) {
80
274k
  std::vector<const Protobuf::Message*> parents;
81
274k
  traverseMessageWorker(visitor, message, parents, true, recurse_into_any);
82
274k
}
83
84
} // namespace ProtobufMessage
85
} // namespace Envoy