| /* |
| * Copyright (C) 2019 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| #ifndef SRC_TRACE_PROCESSOR_UTIL_DESCRIPTORS_H_ |
| #define SRC_TRACE_PROCESSOR_UTIL_DESCRIPTORS_H_ |
| |
| #include <algorithm> |
| #include <string> |
| #include <vector> |
| |
| #include "perfetto/ext/base/optional.h" |
| #include "perfetto/trace_processor/basic_types.h" |
| #include "perfetto/trace_processor/status.h" |
| |
| namespace protozero { |
| struct ConstBytes; |
| } |
| |
| namespace perfetto { |
| namespace trace_processor { |
| |
| class FieldDescriptor { |
| public: |
| FieldDescriptor(std::string name, |
| uint32_t number, |
| uint32_t type, |
| std::string raw_type_name, |
| bool is_repeated); |
| |
| const std::string& name() const { return name_; } |
| uint32_t number() const { return number_; } |
| uint32_t type() const { return type_; } |
| const std::string& raw_type_name() const { return raw_type_name_; } |
| const std::string& resolved_type_name() const { return resolved_type_name_; } |
| bool is_repeated() const { return is_repeated_; } |
| |
| void set_resolved_type_name(const std::string& resolved_type_name) { |
| resolved_type_name_ = resolved_type_name; |
| } |
| |
| private: |
| std::string name_; |
| uint32_t number_; |
| uint32_t type_; |
| std::string raw_type_name_; |
| std::string resolved_type_name_; |
| bool is_repeated_; |
| }; |
| |
| class ProtoDescriptor { |
| public: |
| enum class Type { kEnum = 0, kMessage = 1 }; |
| |
| ProtoDescriptor(std::string package_name, |
| std::string full_name, |
| Type type, |
| base::Optional<uint32_t> parent_id); |
| |
| void AddField(FieldDescriptor descriptor) { |
| PERFETTO_DCHECK(type_ == Type::kMessage); |
| fields_.emplace_back(std::move(descriptor)); |
| } |
| |
| void AddEnumValue(int32_t integer_representation, |
| std::string string_representation) { |
| PERFETTO_DCHECK(type_ == Type::kEnum); |
| enum_values_.emplace_back(integer_representation, |
| std::move(string_representation)); |
| } |
| |
| base::Optional<uint32_t> FindFieldIdxByName(const std::string& name) const { |
| PERFETTO_DCHECK(type_ == Type::kMessage); |
| auto it = std::find_if( |
| fields_.begin(), fields_.end(), |
| [name](const FieldDescriptor& desc) { return desc.name() == name; }); |
| auto idx = static_cast<uint32_t>(std::distance(fields_.begin(), it)); |
| return idx < fields_.size() ? base::Optional<uint32_t>(idx) : base::nullopt; |
| } |
| |
| base::Optional<uint32_t> FindFieldIdxByTag(const uint16_t tag_number) const { |
| PERFETTO_DCHECK(type_ == Type::kMessage); |
| auto it = std::find_if(fields_.begin(), fields_.end(), |
| [tag_number](const FieldDescriptor& desc) { |
| return desc.number() == tag_number; |
| }); |
| auto idx = static_cast<uint32_t>(std::distance(fields_.begin(), it)); |
| return idx < fields_.size() ? base::Optional<uint32_t>(idx) : base::nullopt; |
| } |
| |
| base::Optional<std::string> FindEnumString(const int32_t value) const { |
| PERFETTO_DCHECK(type_ == Type::kEnum); |
| auto it = |
| std::find_if(enum_values_.begin(), enum_values_.end(), |
| [value](const std::pair<int32_t, std::string>& enum_val) { |
| return enum_val.first == value; |
| }); |
| return it == enum_values_.end() ? base::nullopt |
| : base::Optional<std::string>(it->second); |
| } |
| |
| const std::string& package_name() const { return package_name_; } |
| |
| const std::string& full_name() const { return full_name_; } |
| |
| const std::vector<FieldDescriptor>& fields() const { return fields_; } |
| std::vector<FieldDescriptor>* mutable_fields() { return &fields_; } |
| |
| private: |
| std::string package_name_; |
| std::string full_name_; |
| const Type type_; |
| base::Optional<uint32_t> parent_id_; |
| std::vector<FieldDescriptor> fields_; |
| std::vector<std::pair<int32_t, std::string>> enum_values_; |
| }; |
| |
| class DescriptorPool { |
| public: |
| util::Status AddFromFileDescriptorSet( |
| const uint8_t* file_descriptor_set_proto, |
| size_t size); |
| |
| base::Optional<uint32_t> FindDescriptorIdx( |
| const std::string& full_name) const; |
| |
| const std::vector<ProtoDescriptor>& descriptors() const { |
| return descriptors_; |
| } |
| |
| private: |
| void AddNestedProtoDescriptors(const std::string& package_name, |
| base::Optional<uint32_t> parent_idx, |
| protozero::ConstBytes descriptor_proto); |
| void AddEnumProtoDescriptors(const std::string& package_name, |
| base::Optional<uint32_t> parent_idx, |
| protozero::ConstBytes descriptor_proto); |
| |
| util::Status AddExtensionField(const std::string& package_name, |
| protozero::ConstBytes field_desc_proto); |
| |
| // Recursively searches for the given short type in all parent messages |
| // and packages. |
| base::Optional<uint32_t> ResolveShortType(const std::string& parent_path, |
| const std::string& short_type); |
| |
| std::vector<ProtoDescriptor> descriptors_; |
| }; |
| |
| } // namespace trace_processor |
| } // namespace perfetto |
| |
| #endif // SRC_TRACE_PROCESSOR_UTIL_DESCRIPTORS_H_ |