Protobuf: added runtime checks for wire types

This commit is contained in:
dsavvinov
2016-07-21 17:48:10 +03:00
parent 74a22ed4f9
commit b223b4f9ae
6 changed files with 64 additions and 11 deletions
@@ -290,22 +290,26 @@ void ClassGenerator::generateParseMethods(io::Printer *printer) const {
for (int i = 0; i < properties.size(); ++i) {
vars["fieldNumber"] = std::to_string(properties[i]->getFieldNumber());
vars["kotlinFunSuffix"] = properties[i]->getKotlinFunctionSuffix();
vars["kotlinWireType"] = properties[i]->getWireType();
vars["dl"] = "$";
printer->Print(vars, "$fieldNumber$ -> ");
// code for serialization arrays and messages consists of more than one line and needs enclosing brackets
if (properties[i]->getProtoLabel() == FieldDescriptor::LABEL_REPEATED
|| properties[i]->getProtoType() == FieldDescriptor::TYPE_MESSAGE) {
printer->Print("{\n");
printer->Indent();
}
printer->Print("{\n");
printer->Indent();
// check that wire type of that field is equal to expected
printer->Print(vars, "if (wireType != $kotlinWireType$) {\n");
printer->Indent();
printer->Print(vars, "throw InvalidProtocolBufferException(\""
"Error: Field number $fieldNumber$ has wire type $kotlinWireType$"
" but read $dl${wireType.toString()}\")");
printer->Outdent();
printer->Print("}\n");
properties[i]->generateSerializationCode(printer, /* isRead = */ true, /* noTag = */ true);
if (properties[i]->getProtoLabel() == FieldDescriptor::LABEL_REPEATED
|| properties[i]->getProtoType() == FieldDescriptor::TYPE_MESSAGE) {
printer->Outdent();
printer->Print("}\n");
}
printer->Outdent();
printer->Print("}\n");
}
// TODO: add parsing of unknown fields
@@ -582,6 +582,13 @@ FieldGenerator FieldGenerator::getUnderlyingTypeGenerator() const {
return *this;
}
string FieldGenerator::getWireType() const {
if (descriptor->label() == FieldDescriptor::LABEL_REPEATED) {
return "WireType.LENGTH_DELIMITED";
}
return name_resolving::protobufTypeToKotlinWireType(descriptor->type());
}
} // namespace kotlin
} // namespace compiler
@@ -81,6 +81,8 @@ public:
/* Return function name in enum namespace that converts from enum to Int */
string getEnumFromIntConverter() const;
string getWireType() const;
void generateCode(io::Printer * printer, bool isBuilder) const;
void generateSerializationCode(io::Printer * printer, bool isRead = false, bool noTag = false) const;
void generateSizeEstimationCode(io::Printer * printer, string varName, bool noTag = false) const;
@@ -156,6 +156,44 @@ string protobufTypeToKotlinFunctionSuffix(FieldDescriptor::Type type) {
}
}
string protobufTypeToKotlinWireType(FieldDescriptor::Type type) {
switch (type) {
case FieldDescriptor::TYPE_DOUBLE:
return "WireType.FIX_64";
case FieldDescriptor::TYPE_FLOAT:
return "WireType.FIX_32";
case FieldDescriptor::TYPE_INT64:
return "WireType.VARINT";
case FieldDescriptor::TYPE_UINT64:
return "WireType.VARINT";
case FieldDescriptor::TYPE_INT32:
return "WireType.VARINT";
case FieldDescriptor::TYPE_FIXED64:
return "WireType.FIX_64";
case FieldDescriptor::TYPE_FIXED32:
return "WireType.FIX_32";
case FieldDescriptor::TYPE_BOOL:
return "WireType.VARINT";
case FieldDescriptor::TYPE_STRING:
return "WireType.LENGTH_DELIMITED";
case FieldDescriptor::TYPE_MESSAGE:
return "WireType.LENGTH_DELIMITED";
case FieldDescriptor::TYPE_BYTES:
return "WireType.LENGTH_DELIMITED";
case FieldDescriptor::TYPE_UINT32:
return "WireType.VARINT";
case FieldDescriptor::TYPE_ENUM:
return "WireType.VARINT";
case FieldDescriptor::TYPE_SFIXED32:
return "WireType.FIX_32";
case FieldDescriptor::TYPE_SFIXED64:
return "WireType.FIX_64";
case FieldDescriptor::TYPE_SINT32:
return "WireType.VARINT";
case FieldDescriptor::TYPE_SINT64:
return "WireType.VARINT";
}
}
} // namespace name_resolving
NameResolver::NameResolver() {
@@ -41,6 +41,8 @@ std::string protobufTypeToInitValue(FieldDescriptor::Type type);
std::string protobufToKotlinType(FieldDescriptor::Type type);
std::string protobufTypeToKotlinWireType(FieldDescriptor::Type type);
/**
* Converts one of protobuf wire types to corresponding Kotlin type with proper
* naming, so it could be used as suffix after read/write, resulting in function