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