| #ifndef PROTOBUF_BENCHMARKS_UTIL_SCHEMA_PROTO2_TO_PROTO3_UTIL_H_ |
| #define PROTOBUF_BENCHMARKS_UTIL_SCHEMA_PROTO2_TO_PROTO3_UTIL_H_ |
| |
| #include "google/protobuf/message.h" |
| #include "google/protobuf/descriptor.h" |
| #include "google/protobuf/descriptor.pb.h" |
| |
| #include <sstream> |
| #include <algorithm> |
| |
| using google::protobuf::Descriptor; |
| using google::protobuf::DescriptorProto; |
| using google::protobuf::FileDescriptorProto; |
| using google::protobuf::FieldDescriptorProto; |
| using google::protobuf::Message; |
| using google::protobuf::EnumValueDescriptorProto; |
| |
| namespace google { |
| namespace protobuf { |
| namespace util { |
| |
| class SchemaGroupStripper { |
| |
| public: |
| static void StripFile(const FileDescriptor* old_file, |
| FileDescriptorProto *file) { |
| for (int i = file->mutable_message_type()->size() - 1; i >= 0; i--) { |
| if (IsMessageSet(old_file->message_type(i))) { |
| file->mutable_message_type()->DeleteSubrange(i, 1); |
| continue; |
| } |
| StripMessage(old_file->message_type(i), file->mutable_message_type(i)); |
| } |
| for (int i = file->mutable_extension()->size() - 1; i >= 0; i--) { |
| auto field = old_file->extension(i); |
| if (field->type() == FieldDescriptor::TYPE_GROUP || |
| IsMessageSet(field->message_type()) || |
| IsMessageSet(field->containing_type())) { |
| file->mutable_extension()->DeleteSubrange(i, 1); |
| } |
| } |
| } |
| |
| private: |
| static bool IsMessageSet(const Descriptor *descriptor) { |
| if (descriptor != nullptr |
| && descriptor->options().message_set_wire_format()) { |
| return true; |
| } |
| return false; |
| } |
| |
| static void StripMessage(const Descriptor *old_message, |
| DescriptorProto *new_message) { |
| for (int i = new_message->mutable_field()->size() - 1; i >= 0; i--) { |
| if (old_message->field(i)->type() == FieldDescriptor::TYPE_GROUP || |
| IsMessageSet(old_message->field(i)->message_type())) { |
| new_message->mutable_field()->DeleteSubrange(i, 1); |
| } |
| } |
| for (int i = new_message->mutable_extension()->size() - 1; i >= 0; i--) { |
| auto field_type_name = new_message->mutable_extension(i)->type_name(); |
| if (old_message->extension(i)->type() == FieldDescriptor::TYPE_GROUP || |
| IsMessageSet(old_message->extension(i)->containing_type()) || |
| IsMessageSet(old_message->extension(i)->message_type())) { |
| new_message->mutable_extension()->DeleteSubrange(i, 1); |
| } |
| } |
| for (int i = 0; i < new_message->mutable_nested_type()->size(); i++) { |
| StripMessage(old_message->nested_type(i), |
| new_message->mutable_nested_type(i)); |
| } |
| } |
| |
| }; |
| |
| class EnumScrubber { |
| |
| public: |
| EnumScrubber() |
| : total_added_(0) { |
| } |
| |
| void ScrubFile(FileDescriptorProto *file) { |
| for (int i = 0; i < file->enum_type_size(); i++) { |
| ScrubEnum(file->mutable_enum_type(i)); |
| } |
| for (int i = 0; i < file->mutable_message_type()->size(); i++) { |
| ScrubMessage(file->mutable_message_type(i)); |
| } |
| } |
| |
| private: |
| void ScrubEnum(EnumDescriptorProto *enum_type) { |
| if (enum_type->value(0).number() != 0) { |
| bool has_zero = false; |
| for (int j = 0; j < enum_type->value().size(); j++) { |
| if (enum_type->value(j).number() == 0) { |
| EnumValueDescriptorProto temp_enum_value; |
| temp_enum_value.CopyFrom(enum_type->value(j)); |
| enum_type->mutable_value(j)->CopyFrom(enum_type->value(0)); |
| enum_type->mutable_value(0)->CopyFrom(temp_enum_value); |
| has_zero = true; |
| break; |
| } |
| } |
| if (!has_zero) { |
| enum_type->mutable_value()->Add(); |
| for (int i = enum_type->mutable_value()->size() - 1; i > 0; i--) { |
| enum_type->mutable_value(i)->CopyFrom( |
| *enum_type->mutable_value(i - 1)); |
| } |
| enum_type->mutable_value(0)->set_number(0); |
| enum_type->mutable_value(0)->set_name("ADDED_ZERO_VALUE_" + |
| std::to_string(total_added_++)); |
| } |
| } |
| |
| } |
| |
| void ScrubMessage(DescriptorProto *message_type) { |
| for (int i = 0; i < message_type->mutable_enum_type()->size(); i++) { |
| ScrubEnum(message_type->mutable_enum_type(i)); |
| } |
| for (int i = 0; i < message_type->mutable_nested_type()->size(); i++) { |
| ScrubMessage(message_type->mutable_nested_type(i)); |
| } |
| } |
| |
| int total_added_; |
| }; |
| |
| class ExtensionStripper { |
| public: |
| static void StripFile(FileDescriptorProto *file) { |
| for (int i = 0; i < file->mutable_message_type()->size(); i++) { |
| StripMessage(file->mutable_message_type(i)); |
| } |
| file->mutable_extension()->Clear(); |
| } |
| private: |
| static void StripMessage(DescriptorProto *message_type) { |
| message_type->mutable_extension()->Clear(); |
| message_type->clear_extension_range(); |
| for (int i = 0; i < message_type->mutable_nested_type()->size(); i++) { |
| StripMessage(message_type->mutable_nested_type(i)); |
| } |
| } |
| }; |
| |
| |
| class FieldScrubber { |
| public: |
| static void ScrubFile(FileDescriptorProto *file) { |
| for (int i = 0; i < file->mutable_message_type()->size(); i++) { |
| ScrubMessage(file->mutable_message_type(i)); |
| } |
| for (int i = 0; i < file->mutable_extension()->size(); i++) { |
| file->mutable_extension(i)->clear_default_value(); |
| if (ShouldClearLabel(file->mutable_extension(i))) { |
| file->mutable_extension(i)->clear_label(); |
| } |
| } |
| } |
| private: |
| static bool ShouldClearLabel(const FieldDescriptorProto *field) { |
| return field->label() == FieldDescriptorProto::LABEL_REQUIRED; |
| } |
| |
| static void ScrubMessage(DescriptorProto *message_type) { |
| message_type->mutable_extension()->Clear(); |
| for (int i = 0; i < message_type->mutable_extension()->size(); i++) { |
| message_type->mutable_extension(i)->clear_default_value(); |
| if (ShouldClearLabel(message_type->mutable_extension(i))) { |
| message_type->mutable_extension(i)->clear_label(); |
| } |
| } |
| for (int i = 0; i < message_type->mutable_field()->size(); i++) { |
| message_type->mutable_field(i)->clear_default_value(); |
| if (ShouldClearLabel(message_type->mutable_field(i))) { |
| message_type->mutable_field(i)->clear_label(); |
| } |
| } |
| for (int i = 0; i < message_type->mutable_nested_type()->size(); i++) { |
| ScrubMessage(message_type->mutable_nested_type(i)); |
| } |
| } |
| }; |
| |
| } // namespace util |
| } // namespace protobuf |
| } // namespace google |
| |
| #endif // PROTOBUF_BENCHMARKS_UTIL_SCHEMA_PROTO2_TO_PROTO3_UTIL_H_ |