• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #ifndef PROTOBUF_BENCHMARKS_UTIL_SCHEMA_PROTO2_TO_PROTO3_UTIL_H_
2 #define PROTOBUF_BENCHMARKS_UTIL_SCHEMA_PROTO2_TO_PROTO3_UTIL_H_
3 
4 #include "google/protobuf/message.h"
5 #include "google/protobuf/descriptor.h"
6 #include "google/protobuf/descriptor.pb.h"
7 
8 #include <sstream>
9 #include <algorithm>
10 
11 using google::protobuf::Descriptor;
12 using google::protobuf::DescriptorProto;
13 using google::protobuf::FileDescriptorProto;
14 using google::protobuf::FieldDescriptorProto;
15 using google::protobuf::Message;
16 using google::protobuf::EnumValueDescriptorProto;
17 
18 namespace google {
19 namespace protobuf {
20 namespace util {
21 
22 class SchemaGroupStripper {
23 
24  public:
StripFile(const FileDescriptor * old_file,FileDescriptorProto * file)25   static void StripFile(const FileDescriptor* old_file,
26                         FileDescriptorProto *file) {
27     for (int i = file->mutable_message_type()->size() - 1; i >= 0; i--) {
28       if (IsMessageSet(old_file->message_type(i))) {
29         file->mutable_message_type()->DeleteSubrange(i, 1);
30         continue;
31       }
32       StripMessage(old_file->message_type(i), file->mutable_message_type(i));
33     }
34     for (int i = file->mutable_extension()->size() - 1; i >= 0; i--) {
35       auto field = old_file->extension(i);
36       if (field->type() == FieldDescriptor::TYPE_GROUP ||
37           IsMessageSet(field->message_type()) ||
38           IsMessageSet(field->containing_type())) {
39         file->mutable_extension()->DeleteSubrange(i, 1);
40       }
41     }
42   }
43 
44  private:
IsMessageSet(const Descriptor * descriptor)45   static bool IsMessageSet(const Descriptor *descriptor) {
46     if (descriptor != nullptr
47         && descriptor->options().message_set_wire_format()) {
48       return true;
49     }
50     return false;
51   }
52 
StripMessage(const Descriptor * old_message,DescriptorProto * new_message)53   static void StripMessage(const Descriptor *old_message,
54                            DescriptorProto *new_message) {
55     for (int i = new_message->mutable_field()->size() - 1; i >= 0; i--) {
56       if (old_message->field(i)->type() == FieldDescriptor::TYPE_GROUP ||
57           IsMessageSet(old_message->field(i)->message_type())) {
58         new_message->mutable_field()->DeleteSubrange(i, 1);
59       }
60     }
61     for (int i = new_message->mutable_extension()->size() - 1; i >= 0; i--) {
62       auto field_type_name = new_message->mutable_extension(i)->type_name();
63       if (old_message->extension(i)->type() == FieldDescriptor::TYPE_GROUP ||
64           IsMessageSet(old_message->extension(i)->containing_type()) ||
65           IsMessageSet(old_message->extension(i)->message_type())) {
66         new_message->mutable_extension()->DeleteSubrange(i, 1);
67       }
68     }
69     for (int i = 0; i < new_message->mutable_nested_type()->size(); i++) {
70       StripMessage(old_message->nested_type(i),
71                    new_message->mutable_nested_type(i));
72     }
73   }
74 
75 };
76 
77 class EnumScrubber {
78 
79  public:
EnumScrubber()80   EnumScrubber()
81       : total_added_(0) {
82   }
83 
ScrubFile(FileDescriptorProto * file)84   void ScrubFile(FileDescriptorProto *file) {
85     for (int i = 0; i < file->enum_type_size(); i++) {
86       ScrubEnum(file->mutable_enum_type(i));
87     }
88     for (int i = 0; i < file->mutable_message_type()->size(); i++) {
89       ScrubMessage(file->mutable_message_type(i));
90     }
91   }
92 
93  private:
ScrubEnum(EnumDescriptorProto * enum_type)94   void ScrubEnum(EnumDescriptorProto *enum_type) {
95     if (enum_type->value(0).number() != 0) {
96       bool has_zero = false;
97       for (int j = 0; j < enum_type->value().size(); j++) {
98         if (enum_type->value(j).number() == 0) {
99           EnumValueDescriptorProto temp_enum_value;
100           temp_enum_value.CopyFrom(enum_type->value(j));
101           enum_type->mutable_value(j)->CopyFrom(enum_type->value(0));
102           enum_type->mutable_value(0)->CopyFrom(temp_enum_value);
103           has_zero = true;
104           break;
105         }
106       }
107       if (!has_zero) {
108         enum_type->mutable_value()->Add();
109         for (int i = enum_type->mutable_value()->size() - 1; i > 0; i--) {
110           enum_type->mutable_value(i)->CopyFrom(
111               *enum_type->mutable_value(i - 1));
112         }
113         enum_type->mutable_value(0)->set_number(0);
114         enum_type->mutable_value(0)->set_name("ADDED_ZERO_VALUE_" +
115                                               std::to_string(total_added_++));
116       }
117     }
118 
119   }
120 
ScrubMessage(DescriptorProto * message_type)121   void ScrubMessage(DescriptorProto *message_type) {
122     for (int i = 0; i < message_type->mutable_enum_type()->size(); i++) {
123       ScrubEnum(message_type->mutable_enum_type(i));
124     }
125     for (int i = 0; i < message_type->mutable_nested_type()->size(); i++) {
126       ScrubMessage(message_type->mutable_nested_type(i));
127     }
128   }
129 
130   int total_added_;
131 };
132 
133 class ExtensionStripper {
134  public:
StripFile(FileDescriptorProto * file)135   static void StripFile(FileDescriptorProto *file) {
136     for (int i = 0; i < file->mutable_message_type()->size(); i++) {
137       StripMessage(file->mutable_message_type(i));
138     }
139     file->mutable_extension()->Clear();
140   }
141  private:
StripMessage(DescriptorProto * message_type)142   static void StripMessage(DescriptorProto *message_type) {
143     message_type->mutable_extension()->Clear();
144     message_type->clear_extension_range();
145     for (int i = 0; i < message_type->mutable_nested_type()->size(); i++) {
146       StripMessage(message_type->mutable_nested_type(i));
147     }
148   }
149 };
150 
151 
152 class FieldScrubber {
153  public:
ScrubFile(FileDescriptorProto * file)154   static void ScrubFile(FileDescriptorProto *file) {
155     for (int i = 0; i < file->mutable_message_type()->size(); i++) {
156       ScrubMessage(file->mutable_message_type(i));
157     }
158     for (int i = 0; i < file->mutable_extension()->size(); i++) {
159       file->mutable_extension(i)->clear_default_value();
160       if (ShouldClearLabel(file->mutable_extension(i))) {
161         file->mutable_extension(i)->clear_label();
162       }
163     }
164   }
165  private:
ShouldClearLabel(const FieldDescriptorProto * field)166   static bool ShouldClearLabel(const FieldDescriptorProto *field) {
167     return field->label() == FieldDescriptorProto::LABEL_REQUIRED;
168   }
169 
ScrubMessage(DescriptorProto * message_type)170   static void ScrubMessage(DescriptorProto *message_type) {
171     message_type->mutable_extension()->Clear();
172     for (int i = 0; i < message_type->mutable_extension()->size(); i++) {
173       message_type->mutable_extension(i)->clear_default_value();
174       if (ShouldClearLabel(message_type->mutable_extension(i))) {
175         message_type->mutable_extension(i)->clear_label();
176       }
177     }
178     for (int i = 0; i < message_type->mutable_field()->size(); i++) {
179       message_type->mutable_field(i)->clear_default_value();
180       if (ShouldClearLabel(message_type->mutable_field(i))) {
181         message_type->mutable_field(i)->clear_label();
182       }
183     }
184     for (int i = 0; i < message_type->mutable_nested_type()->size(); i++) {
185       ScrubMessage(message_type->mutable_nested_type(i));
186     }
187   }
188 };
189 
190 }  // namespace util
191 }  // namespace protobuf
192 }  // namespace google
193 
194 #endif  // PROTOBUF_BENCHMARKS_UTIL_SCHEMA_PROTO2_TO_PROTO3_UTIL_H_
195