| /* | |
| * Copyright (C) 2025 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_PROTOVM_NODE_H_ | |
| #define SRC_PROTOVM_NODE_H_ | |
| #include <type_traits> | |
| #include <variant> | |
| #include "src/base/intrusive_tree.h" | |
| #include "src/protovm/owned_ptr.h" | |
| #include "src/protovm/scalar.h" | |
| namespace perfetto { | |
| namespace protovm { | |
| struct Node; | |
| namespace internal { | |
| struct MapNode { | |
| struct Traits { | |
| using KeyType = uint64_t; | |
| static constexpr size_t NodeOffset() { | |
| static_assert(std::is_standard_layout_v<MapNode>); | |
| return offsetof(MapNode, node); | |
| } | |
| static const KeyType& GetKey(const MapNode& n) { return n.key; } | |
| }; | |
| MapNode(uint64_t k, OwnedPtr<Node> v) : key{k}, value{std::move(v)} {} | |
| base::IntrusiveTreeNode node{}; | |
| uint64_t key; | |
| OwnedPtr<Node> value; | |
| }; | |
| } // namespace internal | |
| using IntrusiveMap = | |
| base::IntrusiveTree<internal::MapNode, internal::MapNode::Traits>; | |
| struct Node { | |
| using MapNode = internal::MapNode; | |
| struct Bytes { | |
| OwnedPtr<void> data; | |
| size_t size; | |
| }; | |
| struct Empty {}; | |
| struct MappedRepeatedField { | |
| IntrusiveMap key_to_node; | |
| }; | |
| struct IndexedRepeatedField { | |
| IntrusiveMap index_to_node; | |
| // Flag needed to track the merge state of indexed repeated field | |
| // (see implementation of Merge operation in RW proto) | |
| bool has_been_merged; | |
| }; | |
| struct Message { | |
| IntrusiveMap field_id_to_node; | |
| }; | |
| template <class T> | |
| T* GetIf() { | |
| return std::get_if<T>(&value); | |
| } | |
| template <class T> | |
| const T* GetIf() const { | |
| return std::get_if<T>(&value); | |
| } | |
| const char* GetTypeName() const; | |
| std::variant<Bytes, | |
| Empty, | |
| IndexedRepeatedField, | |
| MapNode, | |
| MappedRepeatedField, | |
| Message, | |
| Scalar> | |
| value; | |
| }; | |
| Node& GetOuterNode(Node::MapNode& map_node); | |
| } // namespace protovm | |
| } // namespace perfetto | |
| #endif // SRC_PROTOVM_NODE_H_ |