blob: ad3dee850bb9a374c41e6ad2353a15f276d7ae19 [file] [log] [blame]
/*
* Copyright (C) 2023 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 INCLUDE_PERFETTO_PROTOZERO_GEN_FIELD_HELPERS_H_
#define INCLUDE_PERFETTO_PROTOZERO_GEN_FIELD_HELPERS_H_
#include "perfetto/protozero/message.h"
#include "perfetto/protozero/proto_decoder.h"
#include "perfetto/protozero/proto_utils.h"
#include "perfetto/protozero/scattered_heap_buffer.h"
namespace protozero {
namespace internal {
namespace gen_helpers {
// This file implements some helpers used by the protobuf generated code in the
// .gen.cc files.
//
// The .gen.cc generated protobuf implementation (as opposed to the .pbzero.h
// implementation) is not zero-copy and is not supposed to be used in fast
// paths, so most of these helpers are designed to reduce binary size.
void DeserializeString(const protozero::Field& field, std::string* dst);
// Read packed repeated elements (serialized as `wire_type`) from `field` into
// the `*dst` vector. Returns false if some bytes of `field` could not be
// interpreted correctly as `wire_type`.
template <proto_utils::ProtoWireType wire_type, typename CppType>
bool DeserializePackedRepeated(const protozero::Field& field,
std::vector<CppType>* dst) {
bool parse_error = false;
for (::protozero::PackedRepeatedFieldIterator<wire_type, CppType> rep(
field.data(), field.size(), &parse_error);
rep; ++rep) {
dst->emplace_back(*rep);
}
return !parse_error;
}
extern template bool
DeserializePackedRepeated<proto_utils::ProtoWireType::kVarInt, uint64_t>(
const protozero::Field& field,
std::vector<uint64_t>* dst);
extern template bool
DeserializePackedRepeated<proto_utils::ProtoWireType::kVarInt, int64_t>(
const protozero::Field& field,
std::vector<int64_t>* dst);
extern template bool
DeserializePackedRepeated<proto_utils::ProtoWireType::kVarInt, uint32_t>(
const protozero::Field& field,
std::vector<uint32_t>* dst);
extern template bool
DeserializePackedRepeated<proto_utils::ProtoWireType::kVarInt, int32_t>(
const protozero::Field& field,
std::vector<int32_t>* dst);
// Serializers for different type of fields
void SerializeTinyVarInt(uint32_t field_id, bool value, Message* msg);
template <typename T>
void SerializeExtendedVarInt(uint32_t field_id, T value, Message* msg) {
msg->AppendVarInt(field_id, value);
}
extern template void SerializeExtendedVarInt<uint64_t>(uint32_t field_id,
uint64_t value,
Message* msg);
extern template void SerializeExtendedVarInt<uint32_t>(uint32_t field_id,
uint32_t value,
Message* msg);
template <typename T>
void SerializeVarInt(uint32_t field_id, T value, Message* msg) {
SerializeExtendedVarInt(
field_id, proto_utils::ExtendValueForVarIntSerialization(value), msg);
}
template <typename T>
void SerializeSignedVarInt(uint32_t field_id, T value, Message* msg) {
SerializeVarInt(field_id, proto_utils::ZigZagEncode(value), msg);
}
template <typename T>
void SerializeFixed(uint32_t field_id, T value, Message* msg) {
msg->AppendFixed(field_id, value);
}
extern template void SerializeFixed<double>(uint32_t field_id,
double value,
Message* msg);
extern template void SerializeFixed<float>(uint32_t field_id,
float value,
Message* msg);
extern template void SerializeFixed<uint64_t>(uint32_t field_id,
uint64_t value,
Message* msg);
extern template void SerializeFixed<int64_t>(uint32_t field_id,
int64_t value,
Message* msg);
extern template void SerializeFixed<uint32_t>(uint32_t field_id,
uint32_t value,
Message* msg);
extern template void SerializeFixed<int32_t>(uint32_t field_id,
int32_t value,
Message* msg);
void SerializeString(uint32_t field_id, const std::string& value, Message* msg);
void SerializeUnknownFields(const std::string& unknown_fields, Message* msg);
// Wrapper around HeapBuffered that avoids inlining.
class MessageSerializer {
public:
MessageSerializer();
~MessageSerializer();
Message* get() { return msg_.get(); }
std::vector<uint8_t> SerializeAsArray();
std::string SerializeAsString();
private:
HeapBuffered<Message> msg_;
};
} // namespace gen_helpers
} // namespace internal
} // namespace protozero
#endif // INCLUDE_PERFETTO_PROTOZERO_GEN_FIELD_HELPERS_H_