• 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 #ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_MESSAGE_SERIALIZATION_H__
9 #define GOOGLE_PROTOBUF_COMPILER_JAVA_MESSAGE_SERIALIZATION_H__
10 
11 #include <algorithm>
12 #include <cstddef>
13 #include <vector>
14 
15 #include "absl/types/span.h"
16 #include "google/protobuf/compiler/java/generator_common.h"
17 #include "google/protobuf/descriptor.h"
18 #include "google/protobuf/io/printer.h"
19 
20 namespace google {
21 namespace protobuf {
22 namespace compiler {
23 namespace java {
24 
25 // Generates code to serialize a single extension range.
26 void GenerateSerializeExtensionRange(io::Printer* printer,
27                                      const Descriptor::ExtensionRange* range);
28 
29 // Generates code to serialize all fields and extension ranges for the specified
30 // message descriptor, sorting serialization calls in increasing order by field
31 // number.
GenerateSerializeFieldsAndExtensions(io::Printer * printer,const std::vector<const FieldGenerator * > & field_generators,const Descriptor * descriptor,const FieldDescriptor ** sorted_fields)32 inline void GenerateSerializeFieldsAndExtensions(
33     io::Printer* printer,
34     const std::vector<const FieldGenerator*>& field_generators,
35     const Descriptor* descriptor, const FieldDescriptor** sorted_fields) {
36   std::vector<const Descriptor::ExtensionRange*> sorted_extensions;
37   sorted_extensions.reserve(descriptor->extension_range_count());
38   for (int i = 0; i < descriptor->extension_range_count(); ++i) {
39     sorted_extensions.push_back(descriptor->extension_range(i));
40   }
41   std::sort(sorted_extensions.begin(), sorted_extensions.end(),
42             ExtensionRangeOrdering());
43 
44   std::size_t range_idx = 0;
45 
46   // Merge the fields and the extension ranges, both sorted by field number.
47   for (int i = 0; i < descriptor->field_count(); ++i) {
48     const FieldDescriptor* field = sorted_fields[i];
49 
50     // Collapse all extension ranges up until the next field. This leads to
51     // shorter and more efficient codegen for messages containing a large
52     // number of extension ranges without fields in between them.
53     const Descriptor::ExtensionRange* range = nullptr;
54     while (range_idx < sorted_extensions.size() &&
55            sorted_extensions[range_idx]->end_number() <= field->number()) {
56       range = sorted_extensions[range_idx++];
57     }
58 
59     if (range != nullptr) {
60       GenerateSerializeExtensionRange(printer, range);
61     }
62     size_t idx = static_cast<size_t>(field->index());
63     field_generators[idx]->GenerateSerializationCode(printer);
64   }
65 
66   // After serializing all fields, serialize any remaining extensions via a
67   // single writeUntil call.
68   if (range_idx < sorted_extensions.size()) {
69     GenerateSerializeExtensionRange(printer, sorted_extensions.back());
70   }
71 }
72 
73 }  // namespace java
74 }  // namespace compiler
75 }  // namespace protobuf
76 }  // namespace google
77 
78 #endif  // GOOGLE_PROTOBUF_COMPILER_JAVA_MESSAGE_SERIALIZATION_H__
79