blob: 0079f6f1452e82ae4753807daae98b6f59bef6a1 [file] [log] [blame]
#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_