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_PUBLIC_PB_PACKED_H_
18 #define INCLUDE_PERFETTO_PUBLIC_PB_PACKED_H_
19
20 #include <stdint.h>
21 #include <string.h>
22
23 #include "perfetto/public/compiler.h"
24 #include "perfetto/public/pb_msg.h"
25 #include "perfetto/public/pb_utils.h"
26
27 // This file provides a way of serializing packed repeated fields. All the
28 // strongly typed `struct PerfettoPbPackedMsg*` variants behave as protozero
29 // nested messages and allow zero-copy serialization. A protobuf message that
30 // has a packed repeated field provides begin and end operations that accept a
31 // PerfettoPbPackedMsg. The downside of this approach is that (like all
32 // protozero nested messages), it reserves 4 bytes to encode the length, so it
33 // might add overhead for lots of small messages.
34
35 // ***
36 // Sample usage of PerfettoPbPackedMsg*
37 // ***
38 // ```
39 // struct PerfettoPbPackedMsgUint64 f;
40 // PROTO_begin_FIELD_NAME(&msg, &f);
41 // PerfettoPbPackedMsgUint64Append(&f, 1);
42 // PerfettoPbPackedMsgUint64Append(&f, 2);
43 // PROTO_end_FIELD_NAME(&msg, &f);
44 // ```
45
46 // ***
47 // Implementations of struct PerfettoPbPackedMsg for all supported field types.
48 // ***
49 struct PerfettoPbPackedMsgUint64 {
50 struct PerfettoPbMsg msg;
51 };
PerfettoPbPackedMsgUint64Append(struct PerfettoPbPackedMsgUint64 * buf,uint64_t value)52 static inline void PerfettoPbPackedMsgUint64Append(
53 struct PerfettoPbPackedMsgUint64* buf,
54 uint64_t value) {
55 PerfettoPbMsgAppendVarInt(&buf->msg, value);
56 }
57
58 struct PerfettoPbPackedMsgUint32 {
59 struct PerfettoPbMsg msg;
60 };
PerfettoPbPackedMsgUint32Append(struct PerfettoPbPackedMsgUint32 * buf,uint32_t value)61 static inline void PerfettoPbPackedMsgUint32Append(
62 struct PerfettoPbPackedMsgUint32* buf,
63 uint32_t value) {
64 PerfettoPbMsgAppendVarInt(&buf->msg, value);
65 }
66
67 struct PerfettoPbPackedMsgInt64 {
68 struct PerfettoPbMsg msg;
69 };
PerfettoPbPackedMsgInt64Append(struct PerfettoPbPackedMsgInt64 * buf,int64_t value)70 static inline void PerfettoPbPackedMsgInt64Append(
71 struct PerfettoPbPackedMsgInt64* buf,
72 int64_t value) {
73 PerfettoPbMsgAppendVarInt(&buf->msg, PERFETTO_STATIC_CAST(uint64_t, value));
74 }
75
76 struct PerfettoPbPackedMsgInt32 {
77 struct PerfettoPbMsg msg;
78 };
PerfettoPbPackedMsgInt32Append(struct PerfettoPbPackedMsgInt32 * buf,int32_t value)79 static inline void PerfettoPbPackedMsgInt32Append(
80 struct PerfettoPbPackedMsgInt32* buf,
81 int32_t value) {
82 PerfettoPbMsgAppendVarInt(&buf->msg, PERFETTO_STATIC_CAST(uint64_t, value));
83 }
84
85 struct PerfettoPbPackedMsgSint64 {
86 struct PerfettoPbMsg msg;
87 };
PerfettoPbPackedMsgSint64Append(struct PerfettoPbPackedMsgSint64 * buf,int64_t value)88 static inline void PerfettoPbPackedMsgSint64Append(
89 struct PerfettoPbPackedMsgSint64* buf,
90 int64_t value) {
91 uint64_t encoded = PerfettoPbZigZagEncode64(value);
92 PerfettoPbMsgAppendVarInt(&buf->msg, encoded);
93 }
94
95 struct PerfettoPbPackedMsgSint32 {
96 struct PerfettoPbMsg msg;
97 };
PerfettoPbPackedMsgSint32Append(struct PerfettoPbPackedMsgSint32 * buf,int32_t value)98 static inline void PerfettoPbPackedMsgSint32Append(
99 struct PerfettoPbPackedMsgSint32* buf,
100 int32_t value) {
101 uint64_t encoded =
102 PerfettoPbZigZagEncode64(PERFETTO_STATIC_CAST(int64_t, value));
103 PerfettoPbMsgAppendVarInt(&buf->msg, encoded);
104 }
105
106 struct PerfettoPbPackedMsgFixed64 {
107 struct PerfettoPbMsg msg;
108 };
PerfettoPbPackedMsgFixed64Append(struct PerfettoPbPackedMsgFixed64 * buf,uint64_t value)109 static inline void PerfettoPbPackedMsgFixed64Append(
110 struct PerfettoPbPackedMsgFixed64* buf,
111 uint64_t value) {
112 PerfettoPbMsgAppendFixed64(&buf->msg, value);
113 }
114
115 struct PerfettoPbPackedMsgFixed32 {
116 struct PerfettoPbMsg msg;
117 };
PerfettoPbPackedMsgFixed32Append(struct PerfettoPbPackedMsgFixed32 * buf,uint32_t value)118 static inline void PerfettoPbPackedMsgFixed32Append(
119 struct PerfettoPbPackedMsgFixed32* buf,
120 uint32_t value) {
121 PerfettoPbMsgAppendFixed32(&buf->msg, value);
122 }
123
124 struct PerfettoPbPackedMsgSfixed64 {
125 struct PerfettoPbMsg msg;
126 };
PerfettoPbPackedMsgSfixed64Append(struct PerfettoPbPackedMsgSfixed64 * buf,int64_t value)127 static inline void PerfettoPbPackedMsgSfixed64Append(
128 struct PerfettoPbPackedMsgSfixed64* buf,
129 int64_t value) {
130 uint64_t encoded;
131 memcpy(&encoded, &value, sizeof(encoded));
132 PerfettoPbMsgAppendFixed64(&buf->msg, encoded);
133 }
134
135 struct PerfettoPbPackedMsgSfixed32 {
136 struct PerfettoPbMsg msg;
137 };
PerfettoPbPackedMsgSfixed32Append(struct PerfettoPbPackedMsgSfixed32 * buf,int32_t value)138 static inline void PerfettoPbPackedMsgSfixed32Append(
139 struct PerfettoPbPackedMsgSfixed32* buf,
140 int32_t value) {
141 uint32_t encoded;
142 memcpy(&encoded, &value, sizeof(encoded));
143 PerfettoPbMsgAppendFixed32(&buf->msg, encoded);
144 }
145
146 struct PerfettoPbPackedMsgDouble {
147 struct PerfettoPbMsg msg;
148 };
PerfettoPbPackedMsgDoubleAppend(struct PerfettoPbPackedMsgDouble * buf,double value)149 static inline void PerfettoPbPackedMsgDoubleAppend(
150 struct PerfettoPbPackedMsgDouble* buf,
151 double value) {
152 uint64_t encoded;
153 memcpy(&encoded, &value, sizeof(encoded));
154 PerfettoPbMsgAppendFixed64(&buf->msg, encoded);
155 }
156
157 struct PerfettoPbPackedMsgFloat {
158 struct PerfettoPbMsg msg;
159 };
PerfettoPbPackedMsgFloatAppend(struct PerfettoPbPackedMsgFloat * buf,float value)160 static inline void PerfettoPbPackedMsgFloatAppend(
161 struct PerfettoPbPackedMsgFloat* buf,
162 float value) {
163 uint32_t encoded;
164 memcpy(&encoded, &value, sizeof(encoded));
165 PerfettoPbMsgAppendFixed32(&buf->msg, encoded);
166 }
167
168 #endif // INCLUDE_PERFETTO_PUBLIC_PB_PACKED_H_
169