• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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