#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 #include 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_