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