1 // Protocol Buffers - Google's data interchange format
2 // Copyright 2008 Google Inc. 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 // Author: kenton@google.com (Kenton Varda)
9 // Based on original Protocol Buffers design by
10 // Sanjay Ghemawat, Jeff Dean, and others.
11
12 #include <cstddef>
13 #include <memory>
14 #include <string>
15 #include <vector>
16
17 #include "absl/log/absl_check.h"
18 #include "absl/log/absl_log.h"
19 #include "absl/memory/memory.h"
20 #include "absl/types/optional.h"
21 #include "google/protobuf/compiler/cpp/field.h"
22 #include "google/protobuf/compiler/cpp/field_generators/generators.h"
23 #include "google/protobuf/compiler/cpp/helpers.h"
24 #include "google/protobuf/compiler/cpp/options.h"
25 #include "google/protobuf/descriptor.h"
26 #include "google/protobuf/descriptor.pb.h"
27 #include "google/protobuf/io/printer.h"
28 #include "google/protobuf/wire_format.h"
29
30 namespace google {
31 namespace protobuf {
32 namespace compiler {
33 namespace cpp {
34 namespace {
35 using ::google::protobuf::internal::WireFormat;
36 using ::google::protobuf::internal::WireFormatLite;
37 using Sub = ::google::protobuf::io::Printer::Sub;
38 using Semantic = ::google::protobuf::io::AnnotationCollector::Semantic;
39
40 // For encodings with fixed sizes, returns that size in bytes.
FixedSize(FieldDescriptor::Type type)41 absl::optional<size_t> FixedSize(FieldDescriptor::Type type) {
42 switch (type) {
43 case FieldDescriptor::TYPE_INT32:
44 case FieldDescriptor::TYPE_INT64:
45 case FieldDescriptor::TYPE_UINT32:
46 case FieldDescriptor::TYPE_UINT64:
47 case FieldDescriptor::TYPE_SINT32:
48 case FieldDescriptor::TYPE_SINT64:
49 case FieldDescriptor::TYPE_ENUM:
50 case FieldDescriptor::TYPE_STRING:
51 case FieldDescriptor::TYPE_BYTES:
52 case FieldDescriptor::TYPE_GROUP:
53 case FieldDescriptor::TYPE_MESSAGE:
54 return absl::nullopt;
55
56 case FieldDescriptor::TYPE_FIXED32:
57 return WireFormatLite::kFixed32Size;
58 case FieldDescriptor::TYPE_FIXED64:
59 return WireFormatLite::kFixed64Size;
60 case FieldDescriptor::TYPE_SFIXED32:
61 return WireFormatLite::kSFixed32Size;
62 case FieldDescriptor::TYPE_SFIXED64:
63 return WireFormatLite::kSFixed64Size;
64 case FieldDescriptor::TYPE_FLOAT:
65 return WireFormatLite::kFloatSize;
66 case FieldDescriptor::TYPE_DOUBLE:
67 return WireFormatLite::kDoubleSize;
68 case FieldDescriptor::TYPE_BOOL:
69 return WireFormatLite::kBoolSize;
70
71 // No default because we want the compiler to complain if any new
72 // types are added.
73 }
74
75 ABSL_LOG(FATAL) << "Can't get here.";
76 return absl::nullopt;
77 }
78
Vars(const FieldDescriptor * field,const Options & options)79 std::vector<Sub> Vars(const FieldDescriptor* field, const Options& options) {
80 bool cold = ShouldSplit(field, options);
81 return {
82 {"Type", PrimitiveTypeName(options, field->cpp_type())},
83 {"kDefault", DefaultValue(options, field)},
84 {"_field_cached_byte_size_", MakeVarintCachedSizeFieldName(field, cold)},
85 };
86 }
87
88 class SingularPrimitive final : public FieldGeneratorBase {
89 public:
SingularPrimitive(const FieldDescriptor * field,const Options & opts,MessageSCCAnalyzer * scc)90 SingularPrimitive(const FieldDescriptor* field, const Options& opts,
91 MessageSCCAnalyzer* scc)
92 : FieldGeneratorBase(field, opts, scc), opts_(&opts) {}
93 ~SingularPrimitive() override = default;
94
MakeVars() const95 std::vector<Sub> MakeVars() const override { return Vars(field_, *opts_); }
96
GeneratePrivateMembers(io::Printer * p) const97 void GeneratePrivateMembers(io::Printer* p) const override {
98 p->Emit(R"cc(
99 $Type$ $name$_;
100 )cc");
101 }
102
GenerateClearingCode(io::Printer * p) const103 void GenerateClearingCode(io::Printer* p) const override {
104 p->Emit(R"cc(
105 $field_$ = $kDefault$;
106 )cc");
107 }
108
GenerateMergingCode(io::Printer * p) const109 void GenerateMergingCode(io::Printer* p) const override {
110 p->Emit(R"cc(
111 _this->$field_$ = from.$field_$;
112 )cc");
113 }
114
GenerateSwappingCode(io::Printer * p) const115 void GenerateSwappingCode(io::Printer* p) const override {
116 if (is_oneof()) {
117 // Don't print any swapping code. Swapping the union will swap this field.
118 return;
119 }
120
121 p->Emit(R"cc(
122 //~ A `using std::swap;` is already present in this function.
123 swap($field_$, other->$field_$);
124 )cc");
125 }
126
GenerateConstructorCode(io::Printer * p) const127 void GenerateConstructorCode(io::Printer* p) const override {
128 if (!is_oneof()) {
129 return;
130 }
131
132 p->Emit(R"cc(
133 $pkg$::_$Msg$_default_instance_.$field_$ = $kDefault$;
134 )cc");
135 }
136
GenerateCopyConstructorCode(io::Printer * p) const137 void GenerateCopyConstructorCode(io::Printer* p) const override {
138 p->Emit(R"cc(
139 _this->$field_$ = from.$field_$;
140 )cc");
141 }
142
GenerateConstexprAggregateInitializer(io::Printer * p) const143 void GenerateConstexprAggregateInitializer(io::Printer* p) const override {
144 p->Emit(R"cc(
145 /*decltype($field_$)*/ $kDefault$,
146 )cc");
147 }
148
GenerateAggregateInitializer(io::Printer * p) const149 void GenerateAggregateInitializer(io::Printer* p) const override {
150 p->Emit(R"cc(
151 decltype($field_$){$kDefault$},
152 )cc");
153 }
154
GenerateCopyAggregateInitializer(io::Printer * p) const155 void GenerateCopyAggregateInitializer(io::Printer* p) const override {
156 p->Emit(R"cc(
157 decltype($field_$){},
158 )cc");
159 }
160
161 void GenerateAccessorDeclarations(io::Printer* p) const override;
162 void GenerateInlineAccessorDefinitions(io::Printer* p) const override;
163 void GenerateSerializeWithCachedSizesToArray(io::Printer* p) const override;
164 void GenerateByteSize(io::Printer* p) const override;
165
166 private:
167 const Options* opts_;
168 };
169
GenerateAccessorDeclarations(io::Printer * p) const170 void SingularPrimitive::GenerateAccessorDeclarations(io::Printer* p) const {
171 auto v = p->WithVars(
172 AnnotatedAccessors(field_, {"", "_internal_", "_internal_set_"}));
173 auto vs = p->WithVars(AnnotatedAccessors(field_, {"set_"}, Semantic::kSet));
174 p->Emit(R"cc(
175 $DEPRECATED$ $Type$ $name$() const;
176 $DEPRECATED$ void $set_name$($Type$ value);
177
178 private:
179 $Type$ $_internal_name$() const;
180 void $_internal_set_name$($Type$ value);
181
182 public:
183 )cc");
184 }
185
GenerateInlineAccessorDefinitions(io::Printer * p) const186 void SingularPrimitive::GenerateInlineAccessorDefinitions(
187 io::Printer* p) const {
188 p->Emit(R"cc(
189 inline $Type$ $Msg$::$name$() const {
190 $WeakDescriptorSelfPin$;
191 $annotate_get$;
192 // @@protoc_insertion_point(field_get:$pkg.Msg.field$)
193 return _internal_$name_internal$();
194 }
195 )cc");
196
197 if (is_oneof()) {
198 p->Emit(R"cc(
199 inline void $Msg$::set_$name$($Type$ value) {
200 $WeakDescriptorSelfPin$;
201 $PrepareSplitMessageForWrite$;
202 if ($not_has_field$) {
203 clear_$oneof_name$();
204 set_has_$name_internal$();
205 }
206 $field_$ = value;
207 $annotate_set$;
208 // @@protoc_insertion_point(field_set:$pkg.Msg.field$)
209 }
210 inline $Type$ $Msg$::_internal_$name_internal$() const {
211 if ($has_field$) {
212 return $field_$;
213 }
214 return $kDefault$;
215 }
216 )cc");
217 } else {
218 p->Emit(R"cc(
219 inline void $Msg$::set_$name$($Type$ value) {
220 $WeakDescriptorSelfPin$;
221 $PrepareSplitMessageForWrite$;
222 _internal_set_$name_internal$(value);
223 $set_hasbit$;
224 $annotate_set$;
225 // @@protoc_insertion_point(field_set:$pkg.Msg.field$)
226 }
227 inline $Type$ $Msg$::_internal_$name_internal$() const {
228 $TsanDetectConcurrentRead$;
229 return $field_$;
230 }
231 inline void $Msg$::_internal_set_$name_internal$($Type$ value) {
232 $TsanDetectConcurrentMutation$;
233 $field_$ = value;
234 }
235 )cc");
236 }
237 }
238
GenerateSerializeWithCachedSizesToArray(io::Printer * p) const239 void SingularPrimitive::GenerateSerializeWithCachedSizesToArray(
240 io::Printer* p) const {
241 if ((field_->number() < 16) &&
242 (field_->type() == FieldDescriptor::TYPE_INT32 ||
243 field_->type() == FieldDescriptor::TYPE_INT64 ||
244 field_->type() == FieldDescriptor::TYPE_ENUM)) {
245 // Call special non-inlined routine with tag number hardcoded as a
246 // template parameter that handles the EnsureSpace and the writing
247 // of the tag+value to the array
248 p->Emit(R"cc(
249 target = ::$proto_ns$::internal::WireFormatLite::
250 Write$declared_type$ToArrayWithField<$number$>(
251 stream, this_._internal_$name$(), target);
252 )cc");
253 } else {
254 p->Emit(R"cc(
255 target = stream->EnsureSpace(target);
256 target = ::_pbi::WireFormatLite::Write$DeclaredType$ToArray(
257 $number$, this_._internal_$name$(), target);
258 )cc");
259 }
260 }
261
GenerateByteSize(io::Printer * p) const262 void SingularPrimitive::GenerateByteSize(io::Printer* p) const {
263 size_t tag_size = WireFormat::TagSize(field_->number(), field_->type());
264
265 auto fixed_size = FixedSize(field_->type());
266 if (fixed_size.has_value()) {
267 p->Emit({{"kFixedBytes", tag_size + *fixed_size}}, R"cc(
268 total_size += $kFixedBytes$;
269 )cc");
270 return;
271 }
272
273 // Adding one is very common and it turns out it can be done for
274 // free inside of WireFormatLite, so we can save an instruction here.
275 if (tag_size == 1) {
276 p->Emit(R"cc(
277 total_size += ::_pbi::WireFormatLite::$DeclaredType$SizePlusOne(
278 this_._internal_$name$());
279 )cc");
280 return;
281 }
282
283 p->Emit(R"cc(
284 total_size += $kTagBytes$ + ::_pbi::WireFormatLite::$DeclaredType$Size(
285 this_._internal_$name$());
286 )cc");
287 }
288
289 class RepeatedPrimitive final : public FieldGeneratorBase {
290 public:
RepeatedPrimitive(const FieldDescriptor * field,const Options & opts,MessageSCCAnalyzer * scc)291 RepeatedPrimitive(const FieldDescriptor* field, const Options& opts,
292 MessageSCCAnalyzer* scc)
293 : FieldGeneratorBase(field, opts, scc), opts_(&opts) {}
294 ~RepeatedPrimitive() override = default;
295
MakeVars() const296 std::vector<Sub> MakeVars() const override { return Vars(field_, *opts_); }
297
GenerateClearingCode(io::Printer * p) const298 void GenerateClearingCode(io::Printer* p) const override {
299 if (should_split()) {
300 p->Emit("$field_$.ClearIfNotDefault();\n");
301 } else {
302 p->Emit("$field_$.Clear();\n");
303 }
304 }
305
GenerateMergingCode(io::Printer * p) const306 void GenerateMergingCode(io::Printer* p) const override {
307 // TODO: experiment with simplifying this to be
308 // `if (!from.empty()) { body(); }` for both split and non-split cases.
309 auto body = [&] {
310 p->Emit(R"cc(
311 _this->_internal_mutable_$name$()->MergeFrom(from._internal_$name$());
312 )cc");
313 };
314 if (!should_split()) {
315 body();
316 } else {
317 p->Emit({{"body", body}}, R"cc(
318 if (!from.$field_$.IsDefault()) {
319 $body$;
320 }
321 )cc");
322 }
323 }
324
GenerateSwappingCode(io::Printer * p) const325 void GenerateSwappingCode(io::Printer* p) const override {
326 ABSL_CHECK(!should_split());
327 p->Emit(R"cc(
328 $field_$.InternalSwap(&other->$field_$);
329 )cc");
330 }
331
GenerateDestructorCode(io::Printer * p) const332 void GenerateDestructorCode(io::Printer* p) const override {
333 if (should_split()) {
334 p->Emit(R"cc(
335 this_.$field_$.DeleteIfNotDefault();
336 )cc");
337 }
338 }
339
GenerateConstructorCode(io::Printer * p) const340 void GenerateConstructorCode(io::Printer* p) const override {}
341
GenerateCopyConstructorCode(io::Printer * p) const342 void GenerateCopyConstructorCode(io::Printer* p) const override {
343 if (should_split()) {
344 p->Emit(R"cc(
345 if (!from._internal_$name$().empty()) {
346 _internal_mutable_$name$()->MergeFrom(from._internal_$name$());
347 }
348 )cc");
349 }
350 }
351
GenerateConstexprAggregateInitializer(io::Printer * p) const352 void GenerateConstexprAggregateInitializer(io::Printer* p) const override {
353 p->Emit(R"cc(
354 /*decltype($field_$)*/ {},
355 )cc");
356 GenerateCacheSizeInitializer(p);
357 }
358
GenerateAggregateInitializer(io::Printer * p) const359 void GenerateAggregateInitializer(io::Printer* p) const override {
360 ABSL_CHECK(!should_split());
361 p->Emit(R"cc(
362 decltype($field_$){arena},
363 )cc");
364 GenerateCacheSizeInitializer(p);
365 }
366
GenerateCopyAggregateInitializer(io::Printer * p) const367 void GenerateCopyAggregateInitializer(io::Printer* p) const override {
368 ABSL_CHECK(!should_split());
369 p->Emit(R"cc(
370 decltype($field_$){from.$field_$},
371 )cc");
372 GenerateCacheSizeInitializer(p);
373 }
374
GenerateMemberConstexprConstructor(io::Printer * p) const375 void GenerateMemberConstexprConstructor(io::Printer* p) const override {
376 p->Emit("$name$_{}");
377 if (HasCachedSize()) {
378 p->Emit(",\n_$name$_cached_byte_size_{0}");
379 }
380 }
381
GenerateMemberConstructor(io::Printer * p) const382 void GenerateMemberConstructor(io::Printer* p) const override {
383 p->Emit("$name$_{visibility, arena}");
384 if (HasCachedSize()) {
385 p->Emit(",\n_$name$_cached_byte_size_{0}");
386 }
387 }
388
GenerateMemberCopyConstructor(io::Printer * p) const389 void GenerateMemberCopyConstructor(io::Printer* p) const override {
390 p->Emit("$name$_{visibility, arena, from.$name$_}");
391 if (HasCachedSize()) {
392 p->Emit(",\n_$name$_cached_byte_size_{0}");
393 }
394 }
395
GenerateOneofCopyConstruct(io::Printer * p) const396 void GenerateOneofCopyConstruct(io::Printer* p) const override {
397 ABSL_LOG(FATAL) << "Not supported";
398 }
399
400 void GeneratePrivateMembers(io::Printer* p) const override;
401 void GenerateAccessorDeclarations(io::Printer* p) const override;
402 void GenerateInlineAccessorDefinitions(io::Printer* p) const override;
403 void GenerateSerializeWithCachedSizesToArray(io::Printer* p) const override;
404 void GenerateByteSize(io::Printer* p) const override;
405
406 private:
HasCachedSize() const407 bool HasCachedSize() const {
408 bool is_packed_varint =
409 field_->is_packed() && !FixedSize(field_->type()).has_value();
410 return is_packed_varint && HasGeneratedMethods(field_->file(), *opts_) &&
411 !should_split();
412 }
413
GenerateCacheSizeInitializer(io::Printer * p) const414 void GenerateCacheSizeInitializer(io::Printer* p) const {
415 if (!HasCachedSize()) return;
416 // std::atomic has no move constructor, which prevents explicit aggregate
417 // initialization pre-C++17.
418 p->Emit(R"cc(
419 /* $_field_cached_byte_size_$ = */ {0},
420 )cc");
421 }
422
423 const Options* opts_;
424 };
425
GeneratePrivateMembers(io::Printer * p) const426 void RepeatedPrimitive::GeneratePrivateMembers(io::Printer* p) const {
427 if (should_split()) {
428 p->Emit(R"cc(
429 $pbi$::RawPtr<$pb$::RepeatedField<$Type$>> $name$_;
430 )cc");
431 } else {
432 p->Emit(R"cc(
433 $pb$::RepeatedField<$Type$> $name$_;
434 )cc");
435 }
436
437 if (HasCachedSize()) {
438 p->Emit({{"_cached_size_", MakeVarintCachedSizeName(field_)}},
439 R"cc(
440 $pbi$::CachedSize $_cached_size_$;
441 )cc");
442 }
443 }
444
GenerateAccessorDeclarations(io::Printer * p) const445 void RepeatedPrimitive::GenerateAccessorDeclarations(io::Printer* p) const {
446 auto v = p->WithVars(
447 AnnotatedAccessors(field_, {"", "_internal_", "_internal_mutable_"}));
448 auto vs =
449 p->WithVars(AnnotatedAccessors(field_, {"set_", "add_"}, Semantic::kSet));
450 auto va =
451 p->WithVars(AnnotatedAccessors(field_, {"mutable_"}, Semantic::kAlias));
452 p->Emit(R"cc(
453 $DEPRECATED$ $Type$ $name$(int index) const;
454 $DEPRECATED$ void $set_name$(int index, $Type$ value);
455 $DEPRECATED$ void $add_name$($Type$ value);
456 $DEPRECATED$ const $pb$::RepeatedField<$Type$>& $name$() const;
457 $DEPRECATED$ $pb$::RepeatedField<$Type$>* $mutable_name$();
458
459 private:
460 const $pb$::RepeatedField<$Type$>& $_internal_name$() const;
461 $pb$::RepeatedField<$Type$>* $_internal_mutable_name$();
462
463 public:
464 )cc");
465 }
466
GenerateInlineAccessorDefinitions(io::Printer * p) const467 void RepeatedPrimitive::GenerateInlineAccessorDefinitions(
468 io::Printer* p) const {
469 p->Emit(R"cc(
470 inline $Type$ $Msg$::$name$(int index) const {
471 $WeakDescriptorSelfPin$;
472 $annotate_get$;
473 // @@protoc_insertion_point(field_get:$pkg.Msg.field$)
474 return _internal_$name_internal$().Get(index);
475 }
476 )cc");
477 p->Emit(R"cc(
478 inline void $Msg$::set_$name$(int index, $Type$ value) {
479 $WeakDescriptorSelfPin$;
480 $annotate_set$;
481 _internal_mutable_$name_internal$()->Set(index, value);
482 // @@protoc_insertion_point(field_set:$pkg.Msg.field$)
483 }
484 )cc");
485 p->Emit(R"cc(
486 inline void $Msg$::add_$name$($Type$ value) {
487 $WeakDescriptorSelfPin$;
488 $TsanDetectConcurrentMutation$;
489 _internal_mutable_$name_internal$()->Add(value);
490 $annotate_add$;
491 // @@protoc_insertion_point(field_add:$pkg.Msg.field$)
492 }
493 )cc");
494 p->Emit(R"cc(
495 inline const $pb$::RepeatedField<$Type$>& $Msg$::$name$() const
496 ABSL_ATTRIBUTE_LIFETIME_BOUND {
497 $WeakDescriptorSelfPin$;
498 $annotate_list$;
499 // @@protoc_insertion_point(field_list:$pkg.Msg.field$)
500 return _internal_$name_internal$();
501 }
502 )cc");
503 p->Emit(R"cc(
504 inline $pb$::RepeatedField<$Type$>* $Msg$::mutable_$name$()
505 ABSL_ATTRIBUTE_LIFETIME_BOUND {
506 $WeakDescriptorSelfPin$;
507 $annotate_mutable_list$;
508 // @@protoc_insertion_point(field_mutable_list:$pkg.Msg.field$)
509 $TsanDetectConcurrentMutation$;
510 return _internal_mutable_$name_internal$();
511 }
512 )cc");
513
514 if (should_split()) {
515 p->Emit(R"cc(
516 inline const $pb$::RepeatedField<$Type$>&
517 $Msg$::_internal_$name_internal$() const {
518 $TsanDetectConcurrentRead$;
519 return *$field_$;
520 }
521 inline $pb$::RepeatedField<$Type$>* $Msg$::_internal_mutable_$name_internal$() {
522 $TsanDetectConcurrentRead$;
523 $PrepareSplitMessageForWrite$;
524 if ($field_$.IsDefault()) {
525 $field_$.Set($pb$::Arena::Create<$pb$::RepeatedField<$Type$>>(GetArena()));
526 }
527 return $field_$.Get();
528 }
529 )cc");
530 } else {
531 p->Emit(R"cc(
532 inline const $pb$::RepeatedField<$Type$>&
533 $Msg$::_internal_$name_internal$() const {
534 $TsanDetectConcurrentRead$;
535 return $field_$;
536 }
537 inline $pb$::RepeatedField<$Type$>* $Msg$::_internal_mutable_$name_internal$() {
538 $TsanDetectConcurrentRead$;
539 return &$field_$;
540 }
541 )cc");
542 }
543 }
544
GenerateSerializeWithCachedSizesToArray(io::Printer * p) const545 void RepeatedPrimitive::GenerateSerializeWithCachedSizesToArray(
546 io::Printer* p) const {
547 if (!field_->is_packed()) {
548 p->Emit(R"cc(
549 for (int i = 0, n = this_._internal_$name$_size(); i < n; ++i) {
550 target = stream->EnsureSpace(target);
551 target = ::_pbi::WireFormatLite::Write$DeclaredType$ToArray(
552 $number$, this_._internal_$name$().Get(i), target);
553 }
554 )cc");
555 return;
556 }
557
558 if (FixedSize(field_->type()).has_value()) {
559 p->Emit(R"cc(
560 if (this_._internal_$name$_size() > 0) {
561 target = stream->WriteFixedPacked($number$, this_._internal_$name$(), target);
562 }
563 )cc");
564 return;
565 }
566
567 p->Emit(
568 {
569 {"byte_size",
570 [&] {
571 if (HasCachedSize()) {
572 p->Emit(R"cc(this_.$_field_cached_byte_size_$.Get();)cc");
573 } else {
574 p->Emit(R"cc(
575 ::_pbi::WireFormatLite::$DeclaredType$Size(
576 this_._internal_$name$());
577 )cc");
578 }
579 }},
580 },
581 R"cc(
582 {
583 int byte_size = $byte_size$;
584 if (byte_size > 0) {
585 target = stream->Write$DeclaredType$Packed(
586 $number$, this_._internal_$name$(), byte_size, target);
587 }
588 }
589 )cc");
590 }
591
GenerateByteSize(io::Printer * p) const592 void RepeatedPrimitive::GenerateByteSize(io::Printer* p) const {
593 if (HasCachedSize()) {
594 ABSL_CHECK(field_->is_packed());
595 p->Emit(
596 R"cc(
597 total_size +=
598 ::_pbi::WireFormatLite::$DeclaredType$SizeWithPackedTagSize(
599 this_._internal_$name$(), $kTagBytes$,
600 this_.$_field_cached_byte_size_$);
601 )cc");
602 return;
603 }
604 p->Emit(
605 {
606 {"data_size",
607 [&] {
608 auto fixed_size = FixedSize(field_->type());
609 if (fixed_size.has_value()) {
610 p->Emit({{"kFixed", *fixed_size}}, R"cc(
611 std::size_t{$kFixed$} *
612 ::_pbi::FromIntSize(this_._internal_$name$_size());
613 )cc");
614 } else {
615 p->Emit(R"cc(
616 ::_pbi::WireFormatLite::$DeclaredType$Size(
617 this_._internal_$name$());
618 )cc");
619 }
620 }},
621 {"tag_size",
622 [&] {
623 if (field_->is_packed()) {
624 p->Emit(R"cc(
625 data_size == 0
626 ? 0
627 : $kTagBytes$ + ::_pbi::WireFormatLite::Int32Size(
628 static_cast<int32_t>(data_size));
629 )cc");
630 } else {
631 p->Emit(R"cc(
632 std::size_t{$kTagBytes$} *
633 ::_pbi::FromIntSize(this_._internal_$name$_size());
634 )cc");
635 }
636 }},
637 },
638 R"cc(
639 std::size_t data_size = $data_size$;
640 std::size_t tag_size = $tag_size$;
641 total_size += tag_size + data_size;
642 )cc");
643 }
644 } // namespace
645
MakeSinguarPrimitiveGenerator(const FieldDescriptor * desc,const Options & options,MessageSCCAnalyzer * scc)646 std::unique_ptr<FieldGeneratorBase> MakeSinguarPrimitiveGenerator(
647 const FieldDescriptor* desc, const Options& options,
648 MessageSCCAnalyzer* scc) {
649 return absl::make_unique<SingularPrimitive>(desc, options, scc);
650 }
651
MakeRepeatedPrimitiveGenerator(const FieldDescriptor * desc,const Options & options,MessageSCCAnalyzer * scc)652 std::unique_ptr<FieldGeneratorBase> MakeRepeatedPrimitiveGenerator(
653 const FieldDescriptor* desc, const Options& options,
654 MessageSCCAnalyzer* scc) {
655 return absl::make_unique<RepeatedPrimitive>(desc, options, scc);
656 }
657
658 } // namespace cpp
659 } // namespace compiler
660 } // namespace protobuf
661 } // namespace google
662