protoc-c: add string as bytes option

Allows treating proto strings as ProtobufCBinaryData to work around
limitations such as NULL characters in strings, which are allowed in
protobuf, but not allowed in 'char *' types.

Fixes #203
This commit is contained in:
Ilya Lipnitskiy 2021-03-20 17:35:21 -07:00
parent 6962695641
commit cebe3d03f9
No known key found for this signature in database
GPG Key ID: 435C02AAE7CF2014
4 changed files with 11 additions and 2 deletions

View File

@ -67,6 +67,8 @@ extend google.protobuf.MessageOptions {
}
message ProtobufCFieldOptions {
// Treat string as bytes in generated code
optional bool string_as_bytes = 1 [default = false];
}
extend google.protobuf.FieldOptions {

View File

@ -203,10 +203,14 @@ FieldGeneratorMap::FieldGeneratorMap(const Descriptor* descriptor)
}
FieldGenerator* FieldGeneratorMap::MakeGenerator(const FieldDescriptor* field) {
const ProtobufCFieldOptions opt = field->options().GetExtension(pb_c_field);
switch (field->type()) {
case FieldDescriptor::TYPE_MESSAGE:
return new MessageFieldGenerator(field);
case FieldDescriptor::TYPE_STRING:
if (opt.string_as_bytes())
return new BytesFieldGenerator(field);
else
return new StringFieldGenerator(field);
case FieldDescriptor::TYPE_BYTES:
return new BytesFieldGenerator(field);

View File

@ -463,6 +463,7 @@ GenerateMessageDescriptor(io::Printer* printer, bool gen_init) {
for (int i = 0; i < descriptor_->field_count(); i++) {
const FieldDescriptor *fd = descriptor_->field(i);
const ProtobufCFieldOptions opt = fd->options().GetExtension(pb_c_field);
if (fd->has_default_value()) {
bool already_defined = false;
@ -501,7 +502,7 @@ GenerateMessageDescriptor(io::Printer* printer, bool gen_init) {
GOOGLE_LOG(DFATAL) << "Messages can't have default values!";
break;
case FieldDescriptor::CPPTYPE_STRING:
if (fd->type() == FieldDescriptor::TYPE_BYTES)
if (fd->type() == FieldDescriptor::TYPE_BYTES || opt.string_as_bytes())
{
vars["field_dv_ctype"] = "ProtobufCBinaryData";
}

View File

@ -13,6 +13,8 @@ message SubMess {
repeated int32 rep = 4;
optional bytes bytes1 = 2 [default = "a \0 char"];
optional string str1 = 3 [default = "hello world\n"];
optional string str2 = 5 [default = "hello\0world\n",
(pb_c_field).string_as_bytes = true];
}
optional SubSubMess sub1 = 9;
optional SubSubMess sub2 = 10;