1 // Protocol Buffers - Google's data interchange format
2 // Copyright 2023 Google LLC. All rights reserved.
3 //
4 // Use of this source code is governed by a BSD-style
5 // license that can be found in the LICENSE file or at
6 // https://developers.google.com/open-source/licenses/bsd
7
8 #include "google/protobuf/compiler/hpb/gen_repeated_fields.h"
9
10 #include <string>
11 #include <vector>
12
13 #include "google/protobuf/descriptor.pb.h"
14 #include "absl/strings/string_view.h"
15 #include "google/protobuf/compiler/hpb/gen_accessors.h"
16 #include "google/protobuf/compiler/hpb/gen_enums.h"
17 #include "google/protobuf/compiler/hpb/gen_extensions.h"
18 #include "google/protobuf/compiler/hpb/gen_utils.h"
19 #include "google/protobuf/compiler/hpb/names.h"
20 #include "google/protobuf/compiler/hpb/output.h"
21 #include "google/protobuf/descriptor.h"
22 #include "upb_generator/c/names.h"
23 #include "upb_generator/common.h"
24 #include "upb_generator/file_layout.h"
25
26 namespace google::protobuf::hpb_generator {
27
28 namespace protobuf = ::proto2;
29
30 // Adds using accessors to reuse base Access class members from a Proxy/CProxy.
WriteRepeatedFieldUsingAccessors(const protobuf::FieldDescriptor * field,absl::string_view class_name,absl::string_view resolved_field_name,Output & output,bool read_only)31 void WriteRepeatedFieldUsingAccessors(const protobuf::FieldDescriptor* field,
32 absl::string_view class_name,
33 absl::string_view resolved_field_name,
34 Output& output, bool read_only) {
35 if (field->cpp_type() == protobuf::FieldDescriptor::CPPTYPE_MESSAGE) {
36 output(
37 R"cc(
38 using $0Access::$1;
39 using $0Access::$1_size;
40 )cc",
41 class_name, resolved_field_name);
42 if (!read_only) {
43 output(
44 R"cc(
45 using $0Access::add_$1;
46 using $0Access::mutable_$1;
47 )cc",
48 class_name, resolved_field_name);
49 }
50 } else {
51 output(
52 R"cc(
53 using $0Access::$1;
54 using $0Access::$1_size;
55 )cc",
56 class_name, resolved_field_name);
57 if (!read_only) {
58 output(
59 R"cc(
60 using $0Access::add_$1;
61 using $0Access::mutable_$1;
62 using $0Access::resize_$1;
63 using $0Access::set_$1;
64 )cc",
65 class_name, resolved_field_name);
66 }
67 }
68 }
69
WriteRepeatedFieldsInMessageHeader(const protobuf::Descriptor * desc,const protobuf::FieldDescriptor * field,absl::string_view resolved_field_name,absl::string_view resolved_upbc_name,Output & output)70 void WriteRepeatedFieldsInMessageHeader(const protobuf::Descriptor* desc,
71 const protobuf::FieldDescriptor* field,
72 absl::string_view resolved_field_name,
73 absl::string_view resolved_upbc_name,
74 Output& output) {
75 output(
76 R"cc(
77 inline size_t $1_size() const {
78 size_t len;
79 $0_$2(msg_, &len);
80 return len;
81 }
82 )cc",
83 MessageName(desc), resolved_field_name, resolved_upbc_name);
84
85 if (field->cpp_type() == protobuf::FieldDescriptor::CPPTYPE_MESSAGE) {
86 output(
87 R"cc(
88 $1 $2(size_t index) const;
89 const ::hpb::RepeatedField<const $4>::CProxy $2() const;
90 ::hpb::Ptr<::hpb::RepeatedField<$4>> mutable_$2();
91 absl::StatusOr<$0> add_$2();
92 $0 mutable_$2(size_t index) const;
93 )cc",
94 MessagePtrConstType(field, /* const */ false), // $0
95 MessagePtrConstType(field, /* const */ true), // $1
96 resolved_field_name, // $2
97 resolved_upbc_name, // $3
98 MessageBaseType(field, /* maybe_const */ false) // $4
99 );
100 } else if (field->cpp_type() == protobuf::FieldDescriptor::CPPTYPE_STRING) {
101 output(
102 R"cc(
103 $0 $1(size_t index) const;
104 const ::hpb::RepeatedField<$0>::CProxy $1() const;
105 ::hpb::Ptr<::hpb::RepeatedField<$0>> mutable_$1();
106 bool add_$1($0 val);
107 void set_$1(size_t index, $0 val);
108 bool resize_$1(size_t len);
109 )cc",
110 CppConstType(field), resolved_field_name);
111 } else {
112 output(
113 R"cc(
114 $0 $1(size_t index) const;
115 const ::hpb::RepeatedField<$0>::CProxy $1() const;
116 ::hpb::Ptr<::hpb::RepeatedField<$0>> mutable_$1();
117 bool add_$1($0 val);
118 void set_$1(size_t index, $0 val);
119 bool resize_$1(size_t len);
120 )cc",
121 CppConstType(field), resolved_field_name);
122 }
123 }
124
WriteRepeatedMessageAccessor(const protobuf::Descriptor * message,const protobuf::FieldDescriptor * field,const absl::string_view resolved_field_name,const absl::string_view class_name,Output & output)125 void WriteRepeatedMessageAccessor(const protobuf::Descriptor* message,
126 const protobuf::FieldDescriptor* field,
127 const absl::string_view resolved_field_name,
128 const absl::string_view class_name,
129 Output& output) {
130 const char arena_expression[] = "arena_";
131 absl::string_view upbc_name = field->name();
132 output(
133 R"cc(
134 $1 $0::$2(size_t index) const {
135 size_t len;
136 auto* ptr = $3_$5(msg_, &len);
137 assert(index < len);
138 return ::hpb::interop::upb::MakeCHandle<$4>(
139 (upb_Message*)*(ptr + index), arena_);
140 }
141 )cc",
142 class_name, MessagePtrConstType(field, /* is_const */ true),
143 resolved_field_name, MessageName(message),
144 MessageBaseType(field, /* maybe_const */ false), upbc_name);
145 output(
146 R"cc(
147 absl::StatusOr<$1> $0::add_$2() {
148 auto new_msg = $3_add_$6(msg_, $5);
149 if (!new_msg) {
150 return ::hpb::MessageAllocationError();
151 }
152 return hpb::interop::upb::MakeHandle<$4>((upb_Message*)new_msg, $5);
153 }
154 )cc",
155 class_name, MessagePtrConstType(field, /* const */ false),
156 resolved_field_name, MessageName(message),
157 MessageBaseType(field, /* maybe_const */ false), arena_expression,
158 upbc_name);
159 output(
160 R"cc(
161 $1 $0::mutable_$2(size_t index) const {
162 size_t len;
163 auto* ptr = $3_$6(msg_, &len);
164 assert(index < len);
165 return hpb::interop::upb::MakeHandle<$4>((upb_Message*)*(ptr + index), $5);
166 }
167 )cc",
168 class_name, MessagePtrConstType(field, /* is_const */ false),
169 resolved_field_name, MessageName(message),
170 MessageBaseType(field, /* maybe_const */ false), arena_expression,
171 upbc_name);
172 output(
173 R"cc(
174 const ::hpb::RepeatedField<const $1>::CProxy $0::$2() const {
175 size_t size;
176 const upb_Array* arr = _$3_$4_$5(msg_, &size);
177 return ::hpb::RepeatedField<const $1>::CProxy(arr, arena_);
178 };
179 ::hpb::Ptr<::hpb::RepeatedField<$1>> $0::mutable_$2() {
180 size_t size;
181 upb_Array* arr = _$3_$4_$6(msg_, &size, arena_);
182 return ::hpb::RepeatedField<$1>::Proxy(arr, arena_);
183 }
184 )cc",
185 class_name, // $0
186 MessageBaseType(field, /* maybe_const */ false), // $1
187 resolved_field_name, // $2
188 MessageName(message), // $3
189 upbc_name, // $4
190 upb::generator::kRepeatedFieldArrayGetterPostfix, // $5
191 upb::generator::kRepeatedFieldMutableArrayGetterPostfix // $6
192 );
193 }
194
WriteRepeatedStringAccessor(const protobuf::Descriptor * message,const protobuf::FieldDescriptor * field,const absl::string_view resolved_field_name,const absl::string_view class_name,Output & output)195 void WriteRepeatedStringAccessor(const protobuf::Descriptor* message,
196 const protobuf::FieldDescriptor* field,
197 const absl::string_view resolved_field_name,
198 const absl::string_view class_name,
199 Output& output) {
200 absl::string_view upbc_name = field->name();
201 output(
202 R"cc(
203 $1 $0::$2(size_t index) const {
204 size_t len;
205 auto* ptr = $3_mutable_$4(msg_, &len);
206 assert(index < len);
207 return hpb::interop::upb::FromUpbStringView(*(ptr + index));
208 }
209 )cc",
210 class_name, CppConstType(field), resolved_field_name,
211 MessageName(message), upbc_name);
212 output(
213 R"cc(
214 bool $0::resize_$1(size_t len) {
215 return $2_resize_$3(msg_, len, arena_);
216 }
217 )cc",
218 class_name, resolved_field_name, MessageName(message), upbc_name);
219 output(
220 R"cc(
221 bool $0::add_$2($1 val) {
222 return $3_add_$4(msg_,
223 hpb::interop::upb::CopyToUpbStringView(val, arena_),
224 arena_);
225 }
226 )cc",
227 class_name, CppConstType(field), resolved_field_name,
228 MessageName(message), upbc_name);
229 output(
230 R"cc(
231 void $0::set_$2(size_t index, $1 val) {
232 size_t len;
233 auto* ptr = $3_mutable_$4(msg_, &len);
234 assert(index < len);
235 *(ptr + index) = hpb::interop::upb::CopyToUpbStringView(val, arena_);
236 }
237 )cc",
238 class_name, CppConstType(field), resolved_field_name,
239 MessageName(message), upbc_name);
240 output(
241 R"cc(
242 const ::hpb::RepeatedField<$1>::CProxy $0::$2() const {
243 size_t size;
244 const upb_Array* arr = _$3_$4_$5(msg_, &size);
245 return ::hpb::RepeatedField<$1>::CProxy(arr, arena_);
246 };
247 ::hpb::Ptr<::hpb::RepeatedField<$1>> $0::mutable_$2() {
248 size_t size;
249 upb_Array* arr = _$3_$4_$6(msg_, &size, arena_);
250 return ::hpb::RepeatedField<$1>::Proxy(arr, arena_);
251 }
252 )cc",
253 class_name, // $0
254 CppConstType(field), // $1
255 resolved_field_name, // $2
256 MessageName(message), // $3
257 upbc_name, // $4
258 upb::generator::kRepeatedFieldArrayGetterPostfix, // $5
259 upb::generator::kRepeatedFieldMutableArrayGetterPostfix // $6
260 );
261 }
262
WriteRepeatedScalarAccessor(const protobuf::Descriptor * message,const protobuf::FieldDescriptor * field,const absl::string_view resolved_field_name,const absl::string_view class_name,Output & output)263 void WriteRepeatedScalarAccessor(const protobuf::Descriptor* message,
264 const protobuf::FieldDescriptor* field,
265 const absl::string_view resolved_field_name,
266 const absl::string_view class_name,
267 Output& output) {
268 absl::string_view upbc_name = field->name();
269 output(
270 R"cc(
271 $1 $0::$2(size_t index) const {
272 size_t len;
273 auto* ptr = $3_mutable_$4(msg_, &len);
274 assert(index < len);
275 return *(ptr + index);
276 }
277 )cc",
278 class_name, CppConstType(field), resolved_field_name,
279 MessageName(message), upbc_name);
280 output(
281 R"cc(
282 bool $0::resize_$1(size_t len) {
283 return $2_resize_$3(msg_, len, arena_);
284 }
285 )cc",
286 class_name, resolved_field_name, MessageName(message), upbc_name);
287 output(
288 R"cc(
289 bool $0::add_$2($1 val) { return $3_add_$4(msg_, val, arena_); }
290 )cc",
291 class_name, CppConstType(field), resolved_field_name,
292 MessageName(message), upbc_name);
293 output(
294 R"cc(
295 void $0::set_$2(size_t index, $1 val) {
296 size_t len;
297 auto* ptr = $3_mutable_$4(msg_, &len);
298 assert(index < len);
299 *(ptr + index) = val;
300 }
301 )cc",
302 class_name, CppConstType(field), resolved_field_name,
303 MessageName(message), upbc_name);
304 output(
305 R"cc(
306 const ::hpb::RepeatedField<$1>::CProxy $0::$2() const {
307 size_t size;
308 const upb_Array* arr = _$3_$4_$5(msg_, &size);
309 return ::hpb::RepeatedField<$1>::CProxy(arr, arena_);
310 };
311 ::hpb::Ptr<::hpb::RepeatedField<$1>> $0::mutable_$2() {
312 size_t size;
313 upb_Array* arr = _$3_$4_$6(msg_, &size, arena_);
314 return ::hpb::RepeatedField<$1>::Proxy(arr, arena_);
315 }
316 )cc",
317 class_name, // $0
318 CppConstType(field), // $1
319 resolved_field_name, // $2
320 MessageName(message), // $3
321 upbc_name, // $4
322 upb::generator::kRepeatedFieldArrayGetterPostfix, // $5
323 upb::generator::kRepeatedFieldMutableArrayGetterPostfix // $6
324 );
325 }
326
327 } // namespace protobuf
328 } // namespace google::hpb_generator
329