Skip to content

Commit

Permalink
Merge pull request Aiven-Open#986 from Aiven-Open/keejon/fix-protobuf…
Browse files Browse the repository at this point in the history
…-optionals

fix: proto3 optionals from base64 encoded proto descriptors
  • Loading branch information
eliax1996 authored Oct 31, 2024
2 parents 8e3d735 + 7a3c839 commit e6f39bf
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 3 deletions.
20 changes: 17 additions & 3 deletions src/karapace/protobuf/serialization.py
Original file line number Diff line number Diff line change
Expand Up @@ -93,17 +93,31 @@ def _deserialize_msg(msgtype: Any) -> MessageElement:
for nested_enum in msgtype.enum_type:
nested_types.append(_deserialize_enum(nested_enum))

one_ofs: list[OneOfElement] = [OneOfElement(oneof.name) for oneof in msgtype.oneof_decl]
one_ofs: list[OneOfElement | None] = [OneOfElement(oneof.name) for oneof in msgtype.oneof_decl]

for f in msgtype.field:
sf = _deserialize_field(f)
if f.HasField("oneof_index"):
is_oneof = f.HasField("oneof_index")
is_proto3_optional = f.HasField("oneof_index") and f.HasField("proto3_optional") and f.proto3_optional
if is_proto3_optional:
# Every proto3 optional field is placed into a one-field oneof, called a "synthetic" oneof,
# as it was not present in the source .proto file.
# This will make sure that we don't interpret those optionals as oneof.
one_ofs[f.oneof_index] = None
fields.append(sf)
elif is_oneof:
one_ofs[f.oneof_index].fields.append(sf)
else:
fields.append(sf)

one_ofs_filtered: list[OneOfElement] = [oneof for oneof in one_ofs if oneof is not None]
return MessageElement(
DEFAULT_LOCATION, msgtype.name, nested_types=nested_types, reserveds=reserveds, fields=fields, one_ofs=one_ofs
DEFAULT_LOCATION,
msgtype.name,
nested_types=nested_types,
reserveds=reserveds,
fields=fields,
one_ofs=one_ofs_filtered,
)


Expand Down
18 changes: 18 additions & 0 deletions tests/schemas/protobuf.py
Original file line number Diff line number Diff line change
Expand Up @@ -261,3 +261,21 @@
"lzdGVyLk1ldGFkYXRhEhYKDmNvbXBhbnlfbnVtYmVyGAIgASgJGhYKCE1ldGFkYXRhEgoK"
"AmlkGAEgASgJYgZwcm90bzM="
)

schema_protobuf_optionals_bin = (
"Cgp0ZXN0LnByb3RvIqYBCgpEaW1lbnNpb25zEhEKBHNpemUYASABKAFIAIgBARISCgV3aWR0aBgCIAEoAUgBiAEBEhMKBmhlaWdodBgDIAEo"
+ "AUgCiAEBEhMKBmxlbmd0aBgEIAEoAUgDiAEBEhMKBndlaWdodBgFIAEoAUgEiAEBQgcKBV9zaXplQggKBl93aWR0aEIJCgdfaGVpZ2h0Qg"
+ "kKB19sZW5ndGhCCQoHX3dlaWdodGIGcHJvdG8z"
)

schema_protobuf_optionals = """\
syntax = "proto3";
message Dimensions {
optional double size = 1;
optional double width = 2;
optional double height = 3;
optional double length = 4;
optional double weight = 5;
}
"""
4 changes: 4 additions & 0 deletions tests/unit/test_protobuf_binary_serialization.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
schema_protobuf_nested_message4_bin_protoc,
schema_protobuf_oneof,
schema_protobuf_oneof_bin,
schema_protobuf_optionals,
schema_protobuf_optionals_bin,
schema_protobuf_order_after,
schema_protobuf_order_after_bin,
schema_protobuf_plain,
Expand Down Expand Up @@ -89,6 +91,7 @@
(schema_protobuf_references, schema_protobuf_references_bin),
(schema_protobuf_references2, schema_protobuf_references2_bin),
(schema_protobuf_complex, schema_protobuf_complex_bin),
(schema_protobuf_optionals, schema_protobuf_optionals_bin),
],
)
def test_schema_deserialize(schema_plain, schema_serialized):
Expand Down Expand Up @@ -125,6 +128,7 @@ def test_protoc_serialized_schema_deserialize(schema_plain, schema_serialized):
schema_protobuf_references,
schema_protobuf_references2,
schema_protobuf_complex,
schema_protobuf_optionals,
],
)
def test_simple_schema_serialize(schema):
Expand Down

0 comments on commit e6f39bf

Please sign in to comment.