1 /*
2 * Copyright (C) 2023 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #ifndef INCLUDE_PERFETTO_PROTOZERO_GEN_FIELD_HELPERS_H_
18 #define INCLUDE_PERFETTO_PROTOZERO_GEN_FIELD_HELPERS_H_
19
20 #include "perfetto/protozero/message.h"
21 #include "perfetto/protozero/proto_decoder.h"
22 #include "perfetto/protozero/proto_utils.h"
23 #include "perfetto/protozero/scattered_heap_buffer.h"
24
25 namespace protozero {
26 namespace internal {
27 namespace gen_helpers {
28
29 // This file implements some helpers used by the protobuf generated code in the
30 // .gen.cc files.
31 //
32 // The .gen.cc generated protobuf implementation (as opposed to the .pbzero.h
33 // implementation) is not zero-copy and is not supposed to be used in fast
34 // paths, so most of these helpers are designed to reduce binary size.
35
36 void DeserializeString(const protozero::Field& field, std::string* dst);
37
38 // Read packed repeated elements (serialized as `wire_type`) from `field` into
39 // the `*dst` vector. Returns false if some bytes of `field` could not be
40 // interpreted correctly as `wire_type`.
41 template <proto_utils::ProtoWireType wire_type, typename CppType>
DeserializePackedRepeated(const protozero::Field & field,std::vector<CppType> * dst)42 bool DeserializePackedRepeated(const protozero::Field& field,
43 std::vector<CppType>* dst) {
44 bool parse_error = false;
45 for (::protozero::PackedRepeatedFieldIterator<wire_type, CppType> rep(
46 field.data(), field.size(), &parse_error);
47 rep; ++rep) {
48 dst->emplace_back(*rep);
49 }
50 return !parse_error;
51 }
52
53 extern template bool
54 DeserializePackedRepeated<proto_utils::ProtoWireType::kVarInt, uint64_t>(
55 const protozero::Field& field,
56 std::vector<uint64_t>* dst);
57
58 extern template bool
59 DeserializePackedRepeated<proto_utils::ProtoWireType::kVarInt, int64_t>(
60 const protozero::Field& field,
61 std::vector<int64_t>* dst);
62
63 extern template bool
64 DeserializePackedRepeated<proto_utils::ProtoWireType::kVarInt, uint32_t>(
65 const protozero::Field& field,
66 std::vector<uint32_t>* dst);
67
68 extern template bool
69 DeserializePackedRepeated<proto_utils::ProtoWireType::kVarInt, int32_t>(
70 const protozero::Field& field,
71 std::vector<int32_t>* dst);
72
73 // Serializers for different type of fields
74
75 void SerializeTinyVarInt(uint32_t field_id, bool value, Message* msg);
76
77 template <typename T>
SerializeExtendedVarInt(uint32_t field_id,T value,Message * msg)78 void SerializeExtendedVarInt(uint32_t field_id, T value, Message* msg) {
79 msg->AppendVarInt(field_id, value);
80 }
81
82 extern template void SerializeExtendedVarInt<uint64_t>(uint32_t field_id,
83 uint64_t value,
84 Message* msg);
85
86 extern template void SerializeExtendedVarInt<uint32_t>(uint32_t field_id,
87 uint32_t value,
88 Message* msg);
89
90 template <typename T>
SerializeVarInt(uint32_t field_id,T value,Message * msg)91 void SerializeVarInt(uint32_t field_id, T value, Message* msg) {
92 SerializeExtendedVarInt(
93 field_id, proto_utils::ExtendValueForVarIntSerialization(value), msg);
94 }
95
96 template <typename T>
SerializeSignedVarInt(uint32_t field_id,T value,Message * msg)97 void SerializeSignedVarInt(uint32_t field_id, T value, Message* msg) {
98 SerializeVarInt(field_id, proto_utils::ZigZagEncode(value), msg);
99 }
100
101 template <typename T>
SerializeFixed(uint32_t field_id,T value,Message * msg)102 void SerializeFixed(uint32_t field_id, T value, Message* msg) {
103 msg->AppendFixed(field_id, value);
104 }
105
106 extern template void SerializeFixed<double>(uint32_t field_id,
107 double value,
108 Message* msg);
109
110 extern template void SerializeFixed<float>(uint32_t field_id,
111 float value,
112 Message* msg);
113
114 extern template void SerializeFixed<uint64_t>(uint32_t field_id,
115 uint64_t value,
116 Message* msg);
117
118 extern template void SerializeFixed<int64_t>(uint32_t field_id,
119 int64_t value,
120 Message* msg);
121
122 extern template void SerializeFixed<uint32_t>(uint32_t field_id,
123 uint32_t value,
124 Message* msg);
125
126 extern template void SerializeFixed<int32_t>(uint32_t field_id,
127 int32_t value,
128 Message* msg);
129
130 void SerializeString(uint32_t field_id, const std::string& value, Message* msg);
131
132 void SerializeUnknownFields(const std::string& unknown_fields, Message* msg);
133
134 // Wrapper around HeapBuffered that avoids inlining.
135 class MessageSerializer {
136 public:
137 MessageSerializer();
138 ~MessageSerializer();
139
get()140 Message* get() { return msg_.get(); }
141 std::vector<uint8_t> SerializeAsArray();
142 std::string SerializeAsString();
143
144 private:
145 HeapBuffered<Message> msg_;
146 };
147
148 } // namespace gen_helpers
149 } // namespace internal
150 } // namespace protozero
151
152 #endif // INCLUDE_PERFETTO_PROTOZERO_GEN_FIELD_HELPERS_H_
153