/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 |