blob: 0b6b65528c198ab8dafdc728db50e44a9ca5c292 [file] [edit]
/*
* 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.
*/
#include "src/protovm/rw_proto.h"
#include "perfetto/protozero/message.h"
#include "perfetto/protozero/proto_utils.h"
namespace perfetto {
namespace protovm {
RwProto::RwProto(Allocator* allocator)
: allocator_{allocator}, root_{Node::Empty{}} {}
RwProto::~RwProto() {
allocator_->DeleteReferencedData(&root_);
}
RwProto::Cursor RwProto::GetRoot() {
return Cursor{&root_, allocator_};
}
void RwProto::Serialize(protozero::Message* proto) const {
if (root_.GetIf<Node::Empty>()) {
return;
}
if (auto* bytes = root_.GetIf<Node::Bytes>()) {
proto->AppendRawProtoBytes(bytes->data.get(), bytes->size);
return;
}
auto* message = root_.GetIf<Node::Message>();
PERFETTO_DCHECK(message);
for (auto it = message->field_id_to_node.begin(); it; ++it) {
auto field_id = static_cast<uint32_t>(it->key);
SerializeField(field_id, *it->value, proto);
}
}
void RwProto::SerializeField(uint32_t field_id,
const Node& node,
protozero::Message* proto) const {
if (node.GetIf<Node::Empty>()) {
return;
}
if (auto* bytes = node.GetIf<Node::Bytes>()) {
proto->AppendBytes(field_id, bytes->data.get(), bytes->size);
return;
}
if (auto* scalar = node.GetIf<Scalar>()) {
if (scalar->wire_type == protozero::proto_utils::ProtoWireType::kFixed32) {
proto->AppendFixed(field_id, static_cast<uint32_t>(scalar->value));
return;
}
if (scalar->wire_type == protozero::proto_utils::ProtoWireType::kFixed64) {
proto->AppendFixed(field_id, static_cast<uint64_t>(scalar->value));
return;
}
proto->AppendVarInt(field_id, scalar->value);
return;
}
if (auto* message = node.GetIf<Node::Message>()) {
auto* message_proto =
proto->BeginNestedMessage<protozero::Message>(field_id);
for (auto it = message->field_id_to_node.begin(); it; ++it) {
auto message_field_id = static_cast<uint32_t>(it->key);
SerializeField(message_field_id, *it->value, message_proto);
}
}
if (node.GetIf<Node::IndexedRepeatedField>() ||
node.GetIf<Node::MappedRepeatedField>()) {
const IntrusiveMap* map;
if (auto* indexed = node.GetIf<Node::IndexedRepeatedField>()) {
map = &indexed->index_to_node;
} else {
map = &node.GetIf<Node::MappedRepeatedField>()->key_to_node;
}
for (auto it = map->begin(); it; ++it) {
SerializeField(field_id, *it->value, proto);
}
}
}
} // namespace protovm
} // namespace perfetto