From 42fad84771c709841da3529e80e4e2257a10fff5 Mon Sep 17 00:00:00 2001 From: ergl Date: Mon, 7 Jun 2021 12:36:48 +0200 Subject: [PATCH] Codegen parse_from_stream for repeated primitives Also, rename pony_type_usage to ponny_inner type, it's more descriptive --- protobuf/_plugin/codegen_fields.pony | 16 ++--- protobuf/_plugin/codegen_writer.pony | 99 +++++++++++++++++++--------- protobuf/_plugin/gen_templates.pony | 35 ++++++++++ 3 files changed, 111 insertions(+), 39 deletions(-) diff --git a/protobuf/_plugin/codegen_fields.pony b/protobuf/_plugin/codegen_fields.pony index fa8c29a..4958e32 100644 --- a/protobuf/_plugin/codegen_fields.pony +++ b/protobuf/_plugin/codegen_fields.pony @@ -18,8 +18,8 @@ class val FieldMeta let uses_zigzag: Bool // The Pony type at the field declaration let pony_type_decl: String - // The Pony type at "read" / "write" time - let pony_type_usage: String + // If the Pony type is an Array, this contains the type of the elements + let pony_type_inner: String let default_assignment: String let proto_type: FieldProtoType let proto_label: FieldProtoLabel @@ -29,7 +29,7 @@ class val FieldMeta wire_type': TagKind, uses_zigzag': Bool, pony_type_decl': String, - pony_type_usage': String, + pony_type_inner': String, default_assignment': String, proto_type': FieldProtoType, proto_label': FieldProtoLabel) @@ -38,7 +38,7 @@ class val FieldMeta wire_type = wire_type' uses_zigzag = uses_zigzag' pony_type_decl = pony_type_decl' - pony_type_usage = pony_type_usage' + pony_type_inner = pony_type_inner' default_assignment = default_assignment' proto_type = proto_type' proto_label = proto_label' @@ -87,7 +87,7 @@ primitive CodeGenFields let wire_type, let needs_zigzag, let pony_type_decl, - let pony_type_usage, + let pony_type_inner, let default ) = field_type_tuple let proto_label = _get_proto_label(field) @@ -98,7 +98,7 @@ primitive CodeGenFields wire_type' = wire_type, uses_zigzag' = needs_zigzag, pony_type_decl' = pony_type_decl, - pony_type_usage' = pony_type_usage, + pony_type_inner' = pony_type_inner, default_assignment' = default, proto_type' = proto_type, proto_label' = proto_label @@ -147,7 +147,7 @@ primitive CodeGenFields let wire_type: TagKind, let needs_zigzag: Bool, let pony_type_decl: String, - let pony_type_usage: String, + let pony_type_inner: String, let default_value: String ) => // Everything went OK @@ -155,7 +155,7 @@ primitive CodeGenFields wire_type, needs_zigzag, pony_type_decl, - pony_type_usage, + pony_type_inner, default_value ) end diff --git a/protobuf/_plugin/codegen_writer.pony b/protobuf/_plugin/codegen_writer.pony index c00332d..b757147 100644 --- a/protobuf/_plugin/codegen_writer.pony +++ b/protobuf/_plugin/codegen_writer.pony @@ -97,7 +97,7 @@ class CodeGenWriter let tpl = TemplateValues tpl("field") = field_name tpl("number") = field_meta.number - tpl("type") = field_meta.pony_type_usage + tpl("type") = field_meta.pony_type_inner template_ctx.write_packed_varint.render(tpl)? else // FIXME(borja): Handle more packed values @@ -127,7 +127,7 @@ class CodeGenWriter tpl("tag_kind") = field_meta.wire_type.string() match field_meta.wire_type | VarintField => - tpl("type") = field_meta.pony_type_usage + tpl("type") = field_meta.pony_type_inner tpl("method") = if field_meta.uses_zigzag then "write_varint" @@ -135,10 +135,10 @@ class CodeGenWriter "write_varint_zigzag" end | Fixed32Field => - tpl("type") = field_meta.pony_type_usage + tpl("type") = field_meta.pony_type_inner tpl("method") = "write_fixed_32" | Fixed64Field => - tpl("type") = field_meta.pony_type_usage + tpl("type") = field_meta.pony_type_inner tpl("method") = "write_fixed_64" | DelimitedField => tpl("method") = "write_bytes" @@ -161,12 +161,12 @@ class CodeGenWriter => let tpl = TemplateValues tpl("field") = field_name - tpl("type") = field_meta.pony_type_usage + tpl("type") = field_meta.pony_type_inner if (field_meta.proto_type is MessageType) or (field_meta.proto_label is Repeated) or ((field_meta.wire_type is DelimitedField) and - (field_meta.pony_type_usage == "Array[U8]")) + (field_meta.pony_type_inner == "Array[U8]")) then tpl("needs_viewpoint") = "" end @@ -174,7 +174,7 @@ class CodeGenWriter // Use primed variable inside the optional clause inner_tpl("field") = field_name + "'" inner_tpl("number") = field_meta.number - inner_tpl("type") = field_meta.pony_type_usage + inner_tpl("type") = field_meta.pony_type_inner let inner_template = match field_meta.proto_type | MessageType => template_ctx.write_inner_message | EnumType => template_ctx.write_enum @@ -240,7 +240,7 @@ class CodeGenWriter | Required => match field_meta.proto_type | MessageType => - tpl("type") = field_meta.pony_type_usage + tpl("type") = field_meta.pony_type_inner template_ctx.initialized_required_message_clause.render(tpl)? else // Both enums and primitive types go through the same steps @@ -252,7 +252,7 @@ class CodeGenWriter | MessageType => // Although the field is optional, the underlying message // might need checking - tpl("type") = field_meta.pony_type_usage + tpl("type") = field_meta.pony_type_inner template_ctx.initialized_message_clause.render(tpl)? else error @@ -304,7 +304,7 @@ class CodeGenWriter | PrimitiveType => match field_meta.wire_type | VarintField => - tpl("method_type") = field_meta.pony_type_usage + tpl("method_type") = field_meta.pony_type_inner tpl("method") = if field_meta.uses_zigzag then "packed_varint_zigzag" @@ -328,7 +328,7 @@ class CodeGenWriter let tpl = TemplateValues tpl("name") = field_name tpl("number") = field_meta.number - tpl("type") = field_meta.pony_type_usage + tpl("type") = field_meta.pony_type_inner match field_meta.proto_type | MessageType => tpl("needs_viewpoint") = "" @@ -344,12 +344,12 @@ class CodeGenWriter | DelimitedField => tpl("method") = "delimited" // TODO(borja): This is a hack, find a better way - if field_meta.pony_type_usage == "Array[U8]" then + if field_meta.pony_type_inner == "Array[U8]" then tpl("needs_viewpoint") = "" end tpl("needs_name_arg") = "" | VarintField => - tpl("method_type") = field_meta.pony_type_usage + tpl("method_type") = field_meta.pony_type_inner tpl("method") = if field_meta.uses_zigzag then "varint_zigzag" @@ -413,15 +413,15 @@ class CodeGenWriter | PrimitiveType => match field_meta.wire_type | VarintField => - tpl("type") = field_meta.pony_type_usage + tpl("type") = field_meta.pony_type_inner if field_meta.uses_zigzag then tpl("needs_zigzag") = "" end // This is for the default case where data arrives unpacked tpl("varint_kind") = GenTypes.varint_kind(field_meta.uses_zigzag, - field_meta.pony_type_usage) + field_meta.pony_type_inner) let conv_type = GenTypes.convtype(VarintField, field_meta.uses_zigzag, - field_meta.pony_type_usage) + field_meta.pony_type_inner) match conv_type | None => None | let conv_type': String => @@ -453,15 +453,52 @@ class CodeGenWriter tpl("number") = field_meta.number tpl("wire_type") = field_meta.wire_type.string() let template = match field_meta.proto_type + | PrimitiveType => + match field_meta.wire_type + | DelimitedField => + if field_meta.pony_type_inner == "Array[U8]" then + template_ctx.read_repeated_bytes + else + template_ctx.read_repeated_string + end + | VarintField => + tpl("varint_kind") = GenTypes.varint_kind(field_meta.uses_zigzag, + field_meta.pony_type_inner) + let conv_type = GenTypes.convtype(VarintField, field_meta.uses_zigzag, + field_meta.pony_type_inner) + match conv_type + | None => None + | let conv_type': String => + tpl("conv_type") = conv_type' + end + template_ctx.read_repeated_varint + else + tpl("fixed_kind") = + if + (field_meta.pony_type_inner == "F32") or + (field_meta.pony_type_inner == "F64") then + "float" + else + "integer" + end + tpl("fixed_size") = + if field_meta.wire_type is Fixed32Field then "32" else "64" end + // Do we need a cast between types? + let conv_type = GenTypes.convtype(field_meta.wire_type, false, + field_meta.pony_type_inner) + match conv_type + | None => None + | let conv_type': String => + tpl("conv_type") = conv_type' + end + template_ctx.read_repeated_fixed + end + | EnumType => + tpl("enum_builder") = GenNames.enum_builder(field_meta.pony_type_inner) + template_ctx.read_repeated_enum | MessageType => - tpl("type") = field_meta.pony_type_usage + tpl("type") = field_meta.pony_type_inner template_ctx.read_repeated_inner_message - | EnumType => - // TODO - error - | PrimitiveType => - // TODO - error end template.render(tpl)? @@ -478,24 +515,24 @@ class CodeGenWriter tpl("wire_type") = field_meta.wire_type.string() let template = match field_meta.proto_type | MessageType => - tpl("type") = field_meta.pony_type_usage + tpl("type") = field_meta.pony_type_inner template_ctx.read_inner_message | EnumType => - tpl("enum_builder") = GenNames.enum_builder(field_meta.pony_type_usage) + tpl("enum_builder") = GenNames.enum_builder(field_meta.pony_type_inner) template_ctx.read_enum | PrimitiveType => match field_meta.wire_type | DelimitedField => - if field_meta.pony_type_usage == "Array[U8]" then + if field_meta.pony_type_inner == "Array[U8]" then template_ctx.read_bytes else template_ctx.read_string end | VarintField => tpl("varint_kind") = GenTypes.varint_kind(field_meta.uses_zigzag, - field_meta.pony_type_usage) + field_meta.pony_type_inner) let conv_type = GenTypes.convtype(VarintField, field_meta.uses_zigzag, - field_meta.pony_type_usage) + field_meta.pony_type_inner) match conv_type | None => None | let conv_type': String => @@ -505,8 +542,8 @@ class CodeGenWriter else tpl("fixed_kind") = if - (field_meta.pony_type_usage == "F32") or - (field_meta.pony_type_usage == "F64") then + (field_meta.pony_type_inner == "F32") or + (field_meta.pony_type_inner == "F64") then "float" else "integer" @@ -515,7 +552,7 @@ class CodeGenWriter if field_meta.wire_type is Fixed32Field then "32" else "64" end // Do we need a cast between types? let conv_type = GenTypes.convtype(field_meta.wire_type, false, - field_meta.pony_type_usage) + field_meta.pony_type_inner) match conv_type | None => None | let conv_type': String => diff --git a/protobuf/_plugin/gen_templates.pony b/protobuf/_plugin/gen_templates.pony index b561833..7148d70 100644 --- a/protobuf/_plugin/gen_templates.pony +++ b/protobuf/_plugin/gen_templates.pony @@ -31,6 +31,11 @@ class val GenTemplate let read_packed_varint: Template let read_inner_message: Template let read_repeated_inner_message: Template + let read_repeated_bytes: Template + let read_repeated_string: Template + let read_repeated_enum: Template + let read_repeated_varint: Template + let read_repeated_fixed: Template // write_to_stream let write_bytes: Template @@ -231,6 +236,36 @@ class val GenTemplate {{name}}.push(v)""" )? + read_repeated_bytes = Template.parse( + """ + | ({{number}}, {{wire_type}}) => + {{name}}.push(reader.read_bytes()?)""" + )? + + read_repeated_string = Template.parse( + """ + | ({{number}}, {{wire_type}}) => + {{name}}.push(reader.read_string()?)""" + )? + + read_repeated_enum = Template.parse( + """ + | ({{number}}, {{wire_type}}) => + {{name}}.push({{enum_builder}}.from_i32(reader.read_varint_32()?.i32()))""" + )? + + read_repeated_varint = Template.parse( + """ + | ({{number}}, {{wire_type}}) => + {{name}}.push(reader.read_varint_{{varint_kind}}()?{{if conv_type}}.{{conv_type}}(){{end}})""" + )? + + read_repeated_fixed = Template.parse( + """ + | ({{number}}, {{wire_type}}) => + {{name}}.push(reader.read_fixed_{{fixed_size}}_{{fixed_kind}}()?{{if conv_type}}.{{conv_type}}(){{end}})""" + )? + write_optional_clause = Template.parse( """ match {{field}}