diff --git a/cmd/protoc-gen-tarantool/internal/gen/inline.go b/cmd/protoc-gen-tarantool/internal/gen/inline.go index 17408cb65a6a1c3cbb4590f9eaec2912c8ede496..a14801529e0f901d4faf50072f48dcf0c6a2ffac 100644 --- a/cmd/protoc-gen-tarantool/internal/gen/inline.go +++ b/cmd/protoc-gen-tarantool/internal/gen/inline.go @@ -114,10 +114,18 @@ emitInlineEncodeMap(w, f, tag, file, selfPath, imports, prefix) case f.Desc.IsList(): emitInlineEncodeRepeated(w, f, tag, fname, file, selfPath, imports, prefix) case f.Message != nil: + // Split the length-delimited payload into separate `out` slots: + // emit the tag, then `varint(#body)`, then the body. This avoids + // the per-field `varint(#body) .. body` string concatenation that + // `wire.encode_len` would do. `table.concat` at the end of + // `_encode` joins everything in one pass — same final bytes, + // one fewer allocation per nested-message field. ref := typeRef(file, f.Message.Desc, selfPath, imports, "_encode", prefix) w.line(" if %s then", gate) + w.line(" local _b = %s(v)", ref) w.line(" n = n + 1; out[n] = %s", tag) - w.line(" n = n + 1; out[n] = wire.encode_len(%s(v))", ref) + w.line(" n = n + 1; out[n] = wire.encode_varint(#_b)") + w.line(" n = n + 1; out[n] = _b") w.line(" end") case f.Enum != nil: enumLocal := typeRef(file, f.Enum.Desc, selfPath, imports, "", prefix) @@ -149,8 +157,18 @@ w.line(" if v ~= nil and %s then", scalarNotDefaultExpr(st, "v")) } else { w.line(" if %s then", gate) } - w.line(" n = n + 1; out[n] = %s", tag) - w.line(" n = n + 1; out[n] = wire.encode_%s(v)", st) + if st == "string" || st == "bytes" { + // Length-delimited scalar: same split rationale as nested + // messages above. `encode_string` / `encode_bytes` would + // concatenate the length prefix and body — emit them as + // separate `out` slots instead and let table.concat join. + w.line(" n = n + 1; out[n] = %s", tag) + w.line(" n = n + 1; out[n] = wire.encode_varint(#v)") + w.line(" n = n + 1; out[n] = v") + } else { + w.line(" n = n + 1; out[n] = %s", tag) + w.line(" n = n + 1; out[n] = wire.encode_%s(v)", st) + } w.line(" end") } } @@ -162,8 +180,10 @@ ref := typeRef(file, f.Message.Desc, selfPath, imports, "_encode", prefix) w.line(" if v ~= nil and #v > 0 then") w.line(" local _tag = %s", tag) w.line(" for _i = 1, #v do") + w.line(" local _b = %s(v[_i])", ref) w.line(" n = n + 1; out[n] = _tag") - w.line(" n = n + 1; out[n] = wire.encode_len(%s(v[_i]))", ref) + w.line(" n = n + 1; out[n] = wire.encode_varint(#_b)") + w.line(" n = n + 1; out[n] = _b") w.line(" end") w.line(" end") case f.Enum != nil: @@ -180,8 +200,10 @@ w.line(" if nv == nil then error(\"unknown enum value '\" .. elem .. \"' for %s\", 0) end", fullName) w.line(" end") w.line(" m = m + 1; parts[m] = wire.encode_int32(nv)") w.line(" end") + w.line(" local _b = table.concat(parts)") w.line(" n = n + 1; out[n] = %s", tag) - w.line(" n = n + 1; out[n] = wire.encode_len(table.concat(parts))") + w.line(" n = n + 1; out[n] = wire.encode_varint(#_b)") + w.line(" n = n + 1; out[n] = _b") w.line(" end") default: st := scalarName(f.Desc.Kind()) @@ -192,8 +214,20 @@ w.line(" local parts, m = {}, 0") w.line(" for _i = 1, #v do") w.line(" m = m + 1; parts[m] = wire.encode_%s(v[_i])", st) w.line(" end") + w.line(" local _b = table.concat(parts)") w.line(" n = n + 1; out[n] = %s", tag) - w.line(" n = n + 1; out[n] = wire.encode_len(table.concat(parts))") + w.line(" n = n + 1; out[n] = wire.encode_varint(#_b)") + w.line(" n = n + 1; out[n] = _b") + w.line(" end") + } else if st == "string" || st == "bytes" { + w.line(" if v ~= nil and #v > 0 then") + w.line(" local _tag = %s", tag) + w.line(" for _i = 1, #v do") + w.line(" local _b = v[_i]") + w.line(" n = n + 1; out[n] = _tag") + w.line(" n = n + 1; out[n] = wire.encode_varint(#_b)") + w.line(" n = n + 1; out[n] = _b") + w.line(" end") w.line(" end") } else { w.line(" if v ~= nil and #v > 0 then") diff --git a/examples/expected/full/conformance/conformance_pb.lua b/examples/expected/full/conformance/conformance_pb.lua index 150c6b8d088b0475e2e569c044741d6543f4e870..12439fb41ac9f9dd9caca5745154b08d6dba85b0 100644 --- a/examples/expected/full/conformance/conformance_pb.lua +++ b/examples/expected/full/conformance/conformance_pb.lua @@ -145,19 +145,22 @@ -- field 1: name v = t.name if v ~= nil and v ~= '' then n = n + 1; out[n] = "\x0a" - n = n + 1; out[n] = wire.encode_string(v) + n = n + 1; out[n] = wire.encode_varint(#v) + n = n + 1; out[n] = v end -- field 2: failure_message v = t.failure_message if v ~= nil and v ~= '' then n = n + 1; out[n] = "\x12" - n = n + 1; out[n] = wire.encode_string(v) + n = n + 1; out[n] = wire.encode_varint(#v) + n = n + 1; out[n] = v end -- field 3: matched_name v = t.matched_name if v ~= nil and v ~= '' then n = n + 1; out[n] = "\x1a" - n = n + 1; out[n] = wire.encode_string(v) + n = n + 1; out[n] = wire.encode_varint(#v) + n = n + 1; out[n] = v end local _uf = t._unknown_fields if _uf ~= nil and _uf ~= '' then n = n + 1; out[n] = _uf end @@ -224,8 +227,10 @@ v = t.test if v ~= nil and #v > 0 then local _tag = "\x12" for _i = 1, #v do + local _b = M.TestStatus_encode(v[_i]) n = n + 1; out[n] = _tag - n = n + 1; out[n] = wire.encode_len(M.TestStatus_encode(v[_i])) + n = n + 1; out[n] = wire.encode_varint(#_b) + n = n + 1; out[n] = _b end end local _uf = t._unknown_fields @@ -291,25 +296,29 @@ -- field 1: protobuf_payload v = t.protobuf_payload if _of_payload == "protobuf_payload" then n = n + 1; out[n] = "\x0a" - n = n + 1; out[n] = wire.encode_bytes(v) + n = n + 1; out[n] = wire.encode_varint(#v) + n = n + 1; out[n] = v end -- field 2: json_payload v = t.json_payload if _of_payload == "json_payload" then n = n + 1; out[n] = "\x12" - n = n + 1; out[n] = wire.encode_string(v) + n = n + 1; out[n] = wire.encode_varint(#v) + n = n + 1; out[n] = v end -- field 7: jspb_payload v = t.jspb_payload if _of_payload == "jspb_payload" then n = n + 1; out[n] = "\x3a" - n = n + 1; out[n] = wire.encode_string(v) + n = n + 1; out[n] = wire.encode_varint(#v) + n = n + 1; out[n] = v end -- field 8: text_payload v = t.text_payload if _of_payload == "text_payload" then n = n + 1; out[n] = "\x42" - n = n + 1; out[n] = wire.encode_string(v) + n = n + 1; out[n] = wire.encode_varint(#v) + n = n + 1; out[n] = v end -- field 3: requested_output_format v = t.requested_output_format @@ -328,7 +337,8 @@ -- field 4: message_type v = t.message_type if v ~= nil and v ~= '' then n = n + 1; out[n] = "\x22" - n = n + 1; out[n] = wire.encode_string(v) + n = n + 1; out[n] = wire.encode_varint(#v) + n = n + 1; out[n] = v end -- field 5: test_category v = t.test_category @@ -346,8 +356,10 @@ end -- field 6: jspb_encoding_options v = t.jspb_encoding_options if v ~= nil or type(v) == 'cdata' then + local _b = M.JspbEncodingConfig_encode(v) n = n + 1; out[n] = "\x32" - n = n + 1; out[n] = wire.encode_len(M.JspbEncodingConfig_encode(v)) + n = n + 1; out[n] = wire.encode_varint(#_b) + n = n + 1; out[n] = _b end -- field 9: print_unknown_fields v = t.print_unknown_fields @@ -470,55 +482,64 @@ -- field 1: parse_error v = t.parse_error if _of_result == "parse_error" then n = n + 1; out[n] = "\x0a" - n = n + 1; out[n] = wire.encode_string(v) + n = n + 1; out[n] = wire.encode_varint(#v) + n = n + 1; out[n] = v end -- field 6: serialize_error v = t.serialize_error if _of_result == "serialize_error" then n = n + 1; out[n] = "\x32" - n = n + 1; out[n] = wire.encode_string(v) + n = n + 1; out[n] = wire.encode_varint(#v) + n = n + 1; out[n] = v end -- field 9: timeout_error v = t.timeout_error if _of_result == "timeout_error" then n = n + 1; out[n] = "\x4a" - n = n + 1; out[n] = wire.encode_string(v) + n = n + 1; out[n] = wire.encode_varint(#v) + n = n + 1; out[n] = v end -- field 2: runtime_error v = t.runtime_error if _of_result == "runtime_error" then n = n + 1; out[n] = "\x12" - n = n + 1; out[n] = wire.encode_string(v) + n = n + 1; out[n] = wire.encode_varint(#v) + n = n + 1; out[n] = v end -- field 3: protobuf_payload v = t.protobuf_payload if _of_result == "protobuf_payload" then n = n + 1; out[n] = "\x1a" - n = n + 1; out[n] = wire.encode_bytes(v) + n = n + 1; out[n] = wire.encode_varint(#v) + n = n + 1; out[n] = v end -- field 4: json_payload v = t.json_payload if _of_result == "json_payload" then n = n + 1; out[n] = "\x22" - n = n + 1; out[n] = wire.encode_string(v) + n = n + 1; out[n] = wire.encode_varint(#v) + n = n + 1; out[n] = v end -- field 5: skipped v = t.skipped if _of_result == "skipped" then n = n + 1; out[n] = "\x2a" - n = n + 1; out[n] = wire.encode_string(v) + n = n + 1; out[n] = wire.encode_varint(#v) + n = n + 1; out[n] = v end -- field 7: jspb_payload v = t.jspb_payload if _of_result == "jspb_payload" then n = n + 1; out[n] = "\x3a" - n = n + 1; out[n] = wire.encode_string(v) + n = n + 1; out[n] = wire.encode_varint(#v) + n = n + 1; out[n] = v end -- field 8: text_payload v = t.text_payload if _of_result == "text_payload" then n = n + 1; out[n] = "\x42" - n = n + 1; out[n] = wire.encode_string(v) + n = n + 1; out[n] = wire.encode_varint(#v) + n = n + 1; out[n] = v end local _uf = t._unknown_fields if _uf ~= nil and _uf ~= '' then n = n + 1; out[n] = _uf end diff --git a/examples/expected/full/hello/hello_pb.lua b/examples/expected/full/hello/hello_pb.lua index 0bfef1adae3efafd1a829d4f21bd5afe406671b6..1ac6a88a2d490ea66a5dc6dba6791ab0871dbb95 100644 --- a/examples/expected/full/hello/hello_pb.lua +++ b/examples/expected/full/hello/hello_pb.lua @@ -172,7 +172,8 @@ -- field 2: text v = t.text if _of_outcome == "text" then n = n + 1; out[n] = "\x12" - n = n + 1; out[n] = wire.encode_string(v) + n = n + 1; out[n] = wire.encode_varint(#v) + n = n + 1; out[n] = v end -- field 3: code v = t.code @@ -183,8 +184,10 @@ end -- field 4: details v = t.details if _of_outcome == "details" then + local _b = M.Address_encode(v) n = n + 1; out[n] = "\x22" - n = n + 1; out[n] = wire.encode_len(M.Address_encode(v)) + n = n + 1; out[n] = wire.encode_varint(#_b) + n = n + 1; out[n] = _b end local _uf = t._unknown_fields if _uf ~= nil and _uf ~= '' then n = n + 1; out[n] = _uf end @@ -265,7 +268,8 @@ -- field 1: name v = t.name if v ~= nil and v ~= '' then n = n + 1; out[n] = "\x0a" - n = n + 1; out[n] = wire.encode_string(v) + n = n + 1; out[n] = wire.encode_varint(#v) + n = n + 1; out[n] = v end local _uf = t._unknown_fields if _uf ~= nil and _uf ~= '' then n = n + 1; out[n] = _uf end @@ -323,7 +327,8 @@ -- field 1: greeting v = t.greeting if v ~= nil and v ~= '' then n = n + 1; out[n] = "\x0a" - n = n + 1; out[n] = wire.encode_string(v) + n = n + 1; out[n] = wire.encode_varint(#v) + n = n + 1; out[n] = v end local _uf = t._unknown_fields if _uf ~= nil and _uf ~= '' then n = n + 1; out[n] = _uf end @@ -381,73 +386,96 @@ -- field 1: title v = t.title if v ~= nil and v ~= '' then n = n + 1; out[n] = "\x0a" - n = n + 1; out[n] = wire.encode_string(v) + n = n + 1; out[n] = wire.encode_varint(#v) + n = n + 1; out[n] = v end -- field 2: created_at v = t.created_at if v ~= nil or type(v) == 'cdata' then + local _b = pb.wkt.Timestamp_encode(v) n = n + 1; out[n] = "\x12" - n = n + 1; out[n] = wire.encode_len(pb.wkt.Timestamp_encode(v)) + n = n + 1; out[n] = wire.encode_varint(#_b) + n = n + 1; out[n] = _b end -- field 3: duration v = t.duration if v ~= nil or type(v) == 'cdata' then + local _b = pb.wkt.Duration_encode(v) n = n + 1; out[n] = "\x1a" - n = n + 1; out[n] = wire.encode_len(pb.wkt.Duration_encode(v)) + n = n + 1; out[n] = wire.encode_varint(#_b) + n = n + 1; out[n] = _b end -- field 4: ack v = t.ack if v ~= nil or type(v) == 'cdata' then + local _b = pb.wkt.Empty_encode(v) n = n + 1; out[n] = "\x22" - n = n + 1; out[n] = wire.encode_len(pb.wkt.Empty_encode(v)) + n = n + 1; out[n] = wire.encode_varint(#_b) + n = n + 1; out[n] = _b end -- field 5: retry_count v = t.retry_count if v ~= nil or type(v) == 'cdata' then + local _b = pb.wkt.Int32Value_encode(v) n = n + 1; out[n] = "\x2a" - n = n + 1; out[n] = wire.encode_len(pb.wkt.Int32Value_encode(v)) + n = n + 1; out[n] = wire.encode_varint(#_b) + n = n + 1; out[n] = _b end -- field 6: note v = t.note if v ~= nil or type(v) == 'cdata' then + local _b = pb.wkt.StringValue_encode(v) n = n + 1; out[n] = "\x32" - n = n + 1; out[n] = wire.encode_len(pb.wkt.StringValue_encode(v)) + n = n + 1; out[n] = wire.encode_varint(#_b) + n = n + 1; out[n] = _b end -- field 7: is_admin v = t.is_admin if v ~= nil or type(v) == 'cdata' then + local _b = pb.wkt.BoolValue_encode(v) n = n + 1; out[n] = "\x3a" - n = n + 1; out[n] = wire.encode_len(pb.wkt.BoolValue_encode(v)) + n = n + 1; out[n] = wire.encode_varint(#_b) + n = n + 1; out[n] = _b end -- field 8: payload v = t.payload if v ~= nil or type(v) == 'cdata' then + local _b = pb.wkt.Struct_encode(v) n = n + 1; out[n] = "\x42" - n = n + 1; out[n] = wire.encode_len(pb.wkt.Struct_encode(v)) + n = n + 1; out[n] = wire.encode_varint(#_b) + n = n + 1; out[n] = _b end -- field 9: attribute v = t.attribute if v ~= nil or type(v) == 'cdata' then + local _b = pb.wkt.Value_encode(v) n = n + 1; out[n] = "\x4a" - n = n + 1; out[n] = wire.encode_len(pb.wkt.Value_encode(v)) + n = n + 1; out[n] = wire.encode_varint(#_b) + n = n + 1; out[n] = _b end -- field 10: tags v = t.tags if v ~= nil or type(v) == 'cdata' then + local _b = pb.wkt.ListValue_encode(v) n = n + 1; out[n] = "\x52" - n = n + 1; out[n] = wire.encode_len(pb.wkt.ListValue_encode(v)) + n = n + 1; out[n] = wire.encode_varint(#_b) + n = n + 1; out[n] = _b end -- field 11: extension v = t.extension if v ~= nil or type(v) == 'cdata' then + local _b = pb.wkt.Any_encode(v) n = n + 1; out[n] = "\x5a" - n = n + 1; out[n] = wire.encode_len(pb.wkt.Any_encode(v)) + n = n + 1; out[n] = wire.encode_varint(#_b) + n = n + 1; out[n] = _b end -- field 12: update_mask v = t.update_mask if v ~= nil or type(v) == 'cdata' then + local _b = pb.wkt.FieldMask_encode(v) n = n + 1; out[n] = "\x62" - n = n + 1; out[n] = wire.encode_len(pb.wkt.FieldMask_encode(v)) + n = n + 1; out[n] = wire.encode_varint(#_b) + n = n + 1; out[n] = _b end local _uf = t._unknown_fields if _uf ~= nil and _uf ~= '' then n = n + 1; out[n] = _uf end @@ -549,13 +577,15 @@ -- field 1: street v = t.street if v ~= nil and v ~= '' then n = n + 1; out[n] = "\x0a" - n = n + 1; out[n] = wire.encode_string(v) + n = n + 1; out[n] = wire.encode_varint(#v) + n = n + 1; out[n] = v end -- field 2: city v = t.city if v ~= nil and v ~= '' then n = n + 1; out[n] = "\x12" - n = n + 1; out[n] = wire.encode_string(v) + n = n + 1; out[n] = wire.encode_varint(#v) + n = n + 1; out[n] = v end -- field 3: zip v = t.zip @@ -567,7 +597,8 @@ -- field 4: apartment v = t.apartment if v ~= nil then n = n + 1; out[n] = "\x22" - n = n + 1; out[n] = wire.encode_string(v) + n = n + 1; out[n] = wire.encode_varint(#v) + n = n + 1; out[n] = v end local _uf = t._unknown_fields if _uf ~= nil and _uf ~= '' then n = n + 1; out[n] = _uf end @@ -642,7 +673,8 @@ -- field 1: name v = t.name if v ~= nil and v ~= '' then n = n + 1; out[n] = "\x0a" - n = n + 1; out[n] = wire.encode_string(v) + n = n + 1; out[n] = wire.encode_varint(#v) + n = n + 1; out[n] = v end -- field 2: age v = t.age @@ -655,8 +687,10 @@ v = t.emails if v ~= nil and #v > 0 then local _tag = "\x1a" for _i = 1, #v do + local _b = v[_i] n = n + 1; out[n] = _tag - n = n + 1; out[n] = wire.encode_string(v[_i]) + n = n + 1; out[n] = wire.encode_varint(#_b) + n = n + 1; out[n] = _b end end -- field 4: status @@ -675,16 +709,20 @@ end -- field 5: address v = t.address if v ~= nil or type(v) == 'cdata' then + local _b = M.Address_encode(v) n = n + 1; out[n] = "\x2a" - n = n + 1; out[n] = wire.encode_len(M.Address_encode(v)) + n = n + 1; out[n] = wire.encode_varint(#_b) + n = n + 1; out[n] = _b end -- field 6: friends v = t.friends if v ~= nil and #v > 0 then local _tag = "\x32" for _i = 1, #v do + local _b = M.Person_encode(v[_i]) n = n + 1; out[n] = _tag - n = n + 1; out[n] = wire.encode_len(M.Person_encode(v[_i])) + n = n + 1; out[n] = wire.encode_varint(#_b) + n = n + 1; out[n] = _b end end -- field 7: lucky_numbers @@ -694,14 +732,17 @@ local parts, m = {}, 0 for _i = 1, #v do m = m + 1; parts[m] = wire.encode_int32(v[_i]) end + local _b = table.concat(parts) n = n + 1; out[n] = "\x3a" - n = n + 1; out[n] = wire.encode_len(table.concat(parts)) + n = n + 1; out[n] = wire.encode_varint(#_b) + n = n + 1; out[n] = _b end -- field 8: avatar v = t.avatar if v ~= nil and v ~= '' then n = n + 1; out[n] = "\x42" - n = n + 1; out[n] = wire.encode_bytes(v) + n = n + 1; out[n] = wire.encode_varint(#v) + n = n + 1; out[n] = v end -- field 9: user_id v = t.user_id diff --git a/examples/expected/full/protobuf_test_messages/proto3/test_messages_proto3_pb.lua b/examples/expected/full/protobuf_test_messages/proto3/test_messages_proto3_pb.lua index 18c58a2d178b1c30849435b8805b7a6c83f37e91..759e89fa99d95fe5c4e866c30d811a0275d63fde 100644 --- a/examples/expected/full/protobuf_test_messages/proto3/test_messages_proto3_pb.lua +++ b/examples/expected/full/protobuf_test_messages/proto3/test_messages_proto3_pb.lua @@ -513,25 +513,31 @@ -- field 14: optional_string v = t.optional_string if v ~= nil and v ~= '' then n = n + 1; out[n] = "\x72" - n = n + 1; out[n] = wire.encode_string(v) + n = n + 1; out[n] = wire.encode_varint(#v) + n = n + 1; out[n] = v end -- field 15: optional_bytes v = t.optional_bytes if v ~= nil and v ~= '' then n = n + 1; out[n] = "\x7a" - n = n + 1; out[n] = wire.encode_bytes(v) + n = n + 1; out[n] = wire.encode_varint(#v) + n = n + 1; out[n] = v end -- field 18: optional_nested_message v = t.optional_nested_message if v ~= nil or type(v) == 'cdata' then + local _b = M.TestAllTypesProto3_NestedMessage_encode(v) n = n + 1; out[n] = "\x92\x01" - n = n + 1; out[n] = wire.encode_len(M.TestAllTypesProto3_NestedMessage_encode(v)) + n = n + 1; out[n] = wire.encode_varint(#_b) + n = n + 1; out[n] = _b end -- field 19: optional_foreign_message v = t.optional_foreign_message if v ~= nil or type(v) == 'cdata' then + local _b = M.ForeignMessage_encode(v) n = n + 1; out[n] = "\x9a\x01" - n = n + 1; out[n] = wire.encode_len(M.ForeignMessage_encode(v)) + n = n + 1; out[n] = wire.encode_varint(#_b) + n = n + 1; out[n] = _b end -- field 21: optional_nested_enum v = t.optional_nested_enum @@ -576,19 +582,23 @@ -- field 24: optional_string_piece v = t.optional_string_piece if v ~= nil and v ~= '' then n = n + 1; out[n] = "\xc2\x01" - n = n + 1; out[n] = wire.encode_string(v) + n = n + 1; out[n] = wire.encode_varint(#v) + n = n + 1; out[n] = v end -- field 25: optional_cord v = t.optional_cord if v ~= nil and v ~= '' then n = n + 1; out[n] = "\xca\x01" - n = n + 1; out[n] = wire.encode_string(v) + n = n + 1; out[n] = wire.encode_varint(#v) + n = n + 1; out[n] = v end -- field 27: recursive_message v = t.recursive_message if v ~= nil or type(v) == 'cdata' then + local _b = M.TestAllTypesProto3_encode(v) n = n + 1; out[n] = "\xda\x01" - n = n + 1; out[n] = wire.encode_len(M.TestAllTypesProto3_encode(v)) + n = n + 1; out[n] = wire.encode_varint(#_b) + n = n + 1; out[n] = _b end -- field 31: repeated_int32 v = t.repeated_int32 @@ -597,8 +607,10 @@ local parts, m = {}, 0 for _i = 1, #v do m = m + 1; parts[m] = wire.encode_int32(v[_i]) end + local _b = table.concat(parts) n = n + 1; out[n] = "\xfa\x01" - n = n + 1; out[n] = wire.encode_len(table.concat(parts)) + n = n + 1; out[n] = wire.encode_varint(#_b) + n = n + 1; out[n] = _b end -- field 32: repeated_int64 v = t.repeated_int64 @@ -607,8 +619,10 @@ local parts, m = {}, 0 for _i = 1, #v do m = m + 1; parts[m] = wire.encode_int64(v[_i]) end + local _b = table.concat(parts) n = n + 1; out[n] = "\x82\x02" - n = n + 1; out[n] = wire.encode_len(table.concat(parts)) + n = n + 1; out[n] = wire.encode_varint(#_b) + n = n + 1; out[n] = _b end -- field 33: repeated_uint32 v = t.repeated_uint32 @@ -617,8 +631,10 @@ local parts, m = {}, 0 for _i = 1, #v do m = m + 1; parts[m] = wire.encode_uint32(v[_i]) end + local _b = table.concat(parts) n = n + 1; out[n] = "\x8a\x02" - n = n + 1; out[n] = wire.encode_len(table.concat(parts)) + n = n + 1; out[n] = wire.encode_varint(#_b) + n = n + 1; out[n] = _b end -- field 34: repeated_uint64 v = t.repeated_uint64 @@ -627,8 +643,10 @@ local parts, m = {}, 0 for _i = 1, #v do m = m + 1; parts[m] = wire.encode_uint64(v[_i]) end + local _b = table.concat(parts) n = n + 1; out[n] = "\x92\x02" - n = n + 1; out[n] = wire.encode_len(table.concat(parts)) + n = n + 1; out[n] = wire.encode_varint(#_b) + n = n + 1; out[n] = _b end -- field 35: repeated_sint32 v = t.repeated_sint32 @@ -637,8 +655,10 @@ local parts, m = {}, 0 for _i = 1, #v do m = m + 1; parts[m] = wire.encode_sint32(v[_i]) end + local _b = table.concat(parts) n = n + 1; out[n] = "\x9a\x02" - n = n + 1; out[n] = wire.encode_len(table.concat(parts)) + n = n + 1; out[n] = wire.encode_varint(#_b) + n = n + 1; out[n] = _b end -- field 36: repeated_sint64 v = t.repeated_sint64 @@ -647,8 +667,10 @@ local parts, m = {}, 0 for _i = 1, #v do m = m + 1; parts[m] = wire.encode_sint64(v[_i]) end + local _b = table.concat(parts) n = n + 1; out[n] = "\xa2\x02" - n = n + 1; out[n] = wire.encode_len(table.concat(parts)) + n = n + 1; out[n] = wire.encode_varint(#_b) + n = n + 1; out[n] = _b end -- field 37: repeated_fixed32 v = t.repeated_fixed32 @@ -657,8 +679,10 @@ local parts, m = {}, 0 for _i = 1, #v do m = m + 1; parts[m] = wire.encode_fixed32(v[_i]) end + local _b = table.concat(parts) n = n + 1; out[n] = "\xaa\x02" - n = n + 1; out[n] = wire.encode_len(table.concat(parts)) + n = n + 1; out[n] = wire.encode_varint(#_b) + n = n + 1; out[n] = _b end -- field 38: repeated_fixed64 v = t.repeated_fixed64 @@ -667,8 +691,10 @@ local parts, m = {}, 0 for _i = 1, #v do m = m + 1; parts[m] = wire.encode_fixed64(v[_i]) end + local _b = table.concat(parts) n = n + 1; out[n] = "\xb2\x02" - n = n + 1; out[n] = wire.encode_len(table.concat(parts)) + n = n + 1; out[n] = wire.encode_varint(#_b) + n = n + 1; out[n] = _b end -- field 39: repeated_sfixed32 v = t.repeated_sfixed32 @@ -677,8 +703,10 @@ local parts, m = {}, 0 for _i = 1, #v do m = m + 1; parts[m] = wire.encode_sfixed32(v[_i]) end + local _b = table.concat(parts) n = n + 1; out[n] = "\xba\x02" - n = n + 1; out[n] = wire.encode_len(table.concat(parts)) + n = n + 1; out[n] = wire.encode_varint(#_b) + n = n + 1; out[n] = _b end -- field 40: repeated_sfixed64 v = t.repeated_sfixed64 @@ -687,8 +715,10 @@ local parts, m = {}, 0 for _i = 1, #v do m = m + 1; parts[m] = wire.encode_sfixed64(v[_i]) end + local _b = table.concat(parts) n = n + 1; out[n] = "\xc2\x02" - n = n + 1; out[n] = wire.encode_len(table.concat(parts)) + n = n + 1; out[n] = wire.encode_varint(#_b) + n = n + 1; out[n] = _b end -- field 41: repeated_float v = t.repeated_float @@ -697,8 +727,10 @@ local parts, m = {}, 0 for _i = 1, #v do m = m + 1; parts[m] = wire.encode_float(v[_i]) end + local _b = table.concat(parts) n = n + 1; out[n] = "\xca\x02" - n = n + 1; out[n] = wire.encode_len(table.concat(parts)) + n = n + 1; out[n] = wire.encode_varint(#_b) + n = n + 1; out[n] = _b end -- field 42: repeated_double v = t.repeated_double @@ -707,8 +739,10 @@ local parts, m = {}, 0 for _i = 1, #v do m = m + 1; parts[m] = wire.encode_double(v[_i]) end + local _b = table.concat(parts) n = n + 1; out[n] = "\xd2\x02" - n = n + 1; out[n] = wire.encode_len(table.concat(parts)) + n = n + 1; out[n] = wire.encode_varint(#_b) + n = n + 1; out[n] = _b end -- field 43: repeated_bool v = t.repeated_bool @@ -717,16 +751,20 @@ local parts, m = {}, 0 for _i = 1, #v do m = m + 1; parts[m] = wire.encode_bool(v[_i]) end + local _b = table.concat(parts) n = n + 1; out[n] = "\xda\x02" - n = n + 1; out[n] = wire.encode_len(table.concat(parts)) + n = n + 1; out[n] = wire.encode_varint(#_b) + n = n + 1; out[n] = _b end -- field 44: repeated_string v = t.repeated_string if v ~= nil and #v > 0 then local _tag = "\xe2\x02" for _i = 1, #v do + local _b = v[_i] n = n + 1; out[n] = _tag - n = n + 1; out[n] = wire.encode_string(v[_i]) + n = n + 1; out[n] = wire.encode_varint(#_b) + n = n + 1; out[n] = _b end end -- field 45: repeated_bytes @@ -734,8 +772,10 @@ v = t.repeated_bytes if v ~= nil and #v > 0 then local _tag = "\xea\x02" for _i = 1, #v do + local _b = v[_i] n = n + 1; out[n] = _tag - n = n + 1; out[n] = wire.encode_bytes(v[_i]) + n = n + 1; out[n] = wire.encode_varint(#_b) + n = n + 1; out[n] = _b end end -- field 48: repeated_nested_message @@ -743,8 +783,10 @@ v = t.repeated_nested_message if v ~= nil and #v > 0 then local _tag = "\x82\x03" for _i = 1, #v do + local _b = M.TestAllTypesProto3_NestedMessage_encode(v[_i]) n = n + 1; out[n] = _tag - n = n + 1; out[n] = wire.encode_len(M.TestAllTypesProto3_NestedMessage_encode(v[_i])) + n = n + 1; out[n] = wire.encode_varint(#_b) + n = n + 1; out[n] = _b end end -- field 49: repeated_foreign_message @@ -752,8 +794,10 @@ v = t.repeated_foreign_message if v ~= nil and #v > 0 then local _tag = "\x8a\x03" for _i = 1, #v do + local _b = M.ForeignMessage_encode(v[_i]) n = n + 1; out[n] = _tag - n = n + 1; out[n] = wire.encode_len(M.ForeignMessage_encode(v[_i])) + n = n + 1; out[n] = wire.encode_varint(#_b) + n = n + 1; out[n] = _b end end -- field 51: repeated_nested_enum @@ -769,8 +813,10 @@ if nv == nil then error("unknown enum value '" .. elem .. "' for protobuf_test_messages.proto3.TestAllTypesProto3.NestedEnum", 0) end end m = m + 1; parts[m] = wire.encode_int32(nv) end + local _b = table.concat(parts) n = n + 1; out[n] = "\x9a\x03" - n = n + 1; out[n] = wire.encode_len(table.concat(parts)) + n = n + 1; out[n] = wire.encode_varint(#_b) + n = n + 1; out[n] = _b end -- field 52: repeated_foreign_enum v = t.repeated_foreign_enum @@ -785,16 +831,20 @@ if nv == nil then error("unknown enum value '" .. elem .. "' for protobuf_test_messages.proto3.ForeignEnum", 0) end end m = m + 1; parts[m] = wire.encode_int32(nv) end + local _b = table.concat(parts) n = n + 1; out[n] = "\xa2\x03" - n = n + 1; out[n] = wire.encode_len(table.concat(parts)) + n = n + 1; out[n] = wire.encode_varint(#_b) + n = n + 1; out[n] = _b end -- field 54: repeated_string_piece v = t.repeated_string_piece if v ~= nil and #v > 0 then local _tag = "\xb2\x03" for _i = 1, #v do + local _b = v[_i] n = n + 1; out[n] = _tag - n = n + 1; out[n] = wire.encode_string(v[_i]) + n = n + 1; out[n] = wire.encode_varint(#_b) + n = n + 1; out[n] = _b end end -- field 55: repeated_cord @@ -802,8 +852,10 @@ v = t.repeated_cord if v ~= nil and #v > 0 then local _tag = "\xba\x03" for _i = 1, #v do + local _b = v[_i] n = n + 1; out[n] = _tag - n = n + 1; out[n] = wire.encode_string(v[_i]) + n = n + 1; out[n] = wire.encode_varint(#_b) + n = n + 1; out[n] = _b end end -- field 75: packed_int32 @@ -813,8 +865,10 @@ local parts, m = {}, 0 for _i = 1, #v do m = m + 1; parts[m] = wire.encode_int32(v[_i]) end + local _b = table.concat(parts) n = n + 1; out[n] = "\xda\x04" - n = n + 1; out[n] = wire.encode_len(table.concat(parts)) + n = n + 1; out[n] = wire.encode_varint(#_b) + n = n + 1; out[n] = _b end -- field 76: packed_int64 v = t.packed_int64 @@ -823,8 +877,10 @@ local parts, m = {}, 0 for _i = 1, #v do m = m + 1; parts[m] = wire.encode_int64(v[_i]) end + local _b = table.concat(parts) n = n + 1; out[n] = "\xe2\x04" - n = n + 1; out[n] = wire.encode_len(table.concat(parts)) + n = n + 1; out[n] = wire.encode_varint(#_b) + n = n + 1; out[n] = _b end -- field 77: packed_uint32 v = t.packed_uint32 @@ -833,8 +889,10 @@ local parts, m = {}, 0 for _i = 1, #v do m = m + 1; parts[m] = wire.encode_uint32(v[_i]) end + local _b = table.concat(parts) n = n + 1; out[n] = "\xea\x04" - n = n + 1; out[n] = wire.encode_len(table.concat(parts)) + n = n + 1; out[n] = wire.encode_varint(#_b) + n = n + 1; out[n] = _b end -- field 78: packed_uint64 v = t.packed_uint64 @@ -843,8 +901,10 @@ local parts, m = {}, 0 for _i = 1, #v do m = m + 1; parts[m] = wire.encode_uint64(v[_i]) end + local _b = table.concat(parts) n = n + 1; out[n] = "\xf2\x04" - n = n + 1; out[n] = wire.encode_len(table.concat(parts)) + n = n + 1; out[n] = wire.encode_varint(#_b) + n = n + 1; out[n] = _b end -- field 79: packed_sint32 v = t.packed_sint32 @@ -853,8 +913,10 @@ local parts, m = {}, 0 for _i = 1, #v do m = m + 1; parts[m] = wire.encode_sint32(v[_i]) end + local _b = table.concat(parts) n = n + 1; out[n] = "\xfa\x04" - n = n + 1; out[n] = wire.encode_len(table.concat(parts)) + n = n + 1; out[n] = wire.encode_varint(#_b) + n = n + 1; out[n] = _b end -- field 80: packed_sint64 v = t.packed_sint64 @@ -863,8 +925,10 @@ local parts, m = {}, 0 for _i = 1, #v do m = m + 1; parts[m] = wire.encode_sint64(v[_i]) end + local _b = table.concat(parts) n = n + 1; out[n] = "\x82\x05" - n = n + 1; out[n] = wire.encode_len(table.concat(parts)) + n = n + 1; out[n] = wire.encode_varint(#_b) + n = n + 1; out[n] = _b end -- field 81: packed_fixed32 v = t.packed_fixed32 @@ -873,8 +937,10 @@ local parts, m = {}, 0 for _i = 1, #v do m = m + 1; parts[m] = wire.encode_fixed32(v[_i]) end + local _b = table.concat(parts) n = n + 1; out[n] = "\x8a\x05" - n = n + 1; out[n] = wire.encode_len(table.concat(parts)) + n = n + 1; out[n] = wire.encode_varint(#_b) + n = n + 1; out[n] = _b end -- field 82: packed_fixed64 v = t.packed_fixed64 @@ -883,8 +949,10 @@ local parts, m = {}, 0 for _i = 1, #v do m = m + 1; parts[m] = wire.encode_fixed64(v[_i]) end + local _b = table.concat(parts) n = n + 1; out[n] = "\x92\x05" - n = n + 1; out[n] = wire.encode_len(table.concat(parts)) + n = n + 1; out[n] = wire.encode_varint(#_b) + n = n + 1; out[n] = _b end -- field 83: packed_sfixed32 v = t.packed_sfixed32 @@ -893,8 +961,10 @@ local parts, m = {}, 0 for _i = 1, #v do m = m + 1; parts[m] = wire.encode_sfixed32(v[_i]) end + local _b = table.concat(parts) n = n + 1; out[n] = "\x9a\x05" - n = n + 1; out[n] = wire.encode_len(table.concat(parts)) + n = n + 1; out[n] = wire.encode_varint(#_b) + n = n + 1; out[n] = _b end -- field 84: packed_sfixed64 v = t.packed_sfixed64 @@ -903,8 +973,10 @@ local parts, m = {}, 0 for _i = 1, #v do m = m + 1; parts[m] = wire.encode_sfixed64(v[_i]) end + local _b = table.concat(parts) n = n + 1; out[n] = "\xa2\x05" - n = n + 1; out[n] = wire.encode_len(table.concat(parts)) + n = n + 1; out[n] = wire.encode_varint(#_b) + n = n + 1; out[n] = _b end -- field 85: packed_float v = t.packed_float @@ -913,8 +985,10 @@ local parts, m = {}, 0 for _i = 1, #v do m = m + 1; parts[m] = wire.encode_float(v[_i]) end + local _b = table.concat(parts) n = n + 1; out[n] = "\xaa\x05" - n = n + 1; out[n] = wire.encode_len(table.concat(parts)) + n = n + 1; out[n] = wire.encode_varint(#_b) + n = n + 1; out[n] = _b end -- field 86: packed_double v = t.packed_double @@ -923,8 +997,10 @@ local parts, m = {}, 0 for _i = 1, #v do m = m + 1; parts[m] = wire.encode_double(v[_i]) end + local _b = table.concat(parts) n = n + 1; out[n] = "\xb2\x05" - n = n + 1; out[n] = wire.encode_len(table.concat(parts)) + n = n + 1; out[n] = wire.encode_varint(#_b) + n = n + 1; out[n] = _b end -- field 87: packed_bool v = t.packed_bool @@ -933,8 +1009,10 @@ local parts, m = {}, 0 for _i = 1, #v do m = m + 1; parts[m] = wire.encode_bool(v[_i]) end + local _b = table.concat(parts) n = n + 1; out[n] = "\xba\x05" - n = n + 1; out[n] = wire.encode_len(table.concat(parts)) + n = n + 1; out[n] = wire.encode_varint(#_b) + n = n + 1; out[n] = _b end -- field 88: packed_nested_enum v = t.packed_nested_enum @@ -949,8 +1027,10 @@ if nv == nil then error("unknown enum value '" .. elem .. "' for protobuf_test_messages.proto3.TestAllTypesProto3.NestedEnum", 0) end end m = m + 1; parts[m] = wire.encode_int32(nv) end + local _b = table.concat(parts) n = n + 1; out[n] = "\xc2\x05" - n = n + 1; out[n] = wire.encode_len(table.concat(parts)) + n = n + 1; out[n] = wire.encode_varint(#_b) + n = n + 1; out[n] = _b end -- field 89: unpacked_int32 v = t.unpacked_int32 @@ -1082,8 +1162,10 @@ if nv == nil then error("unknown enum value '" .. elem .. "' for protobuf_test_messages.proto3.TestAllTypesProto3.NestedEnum", 0) end end m = m + 1; parts[m] = wire.encode_int32(nv) end + local _b = table.concat(parts) n = n + 1; out[n] = "\xb0\x06" - n = n + 1; out[n] = wire.encode_len(table.concat(parts)) + n = n + 1; out[n] = wire.encode_varint(#_b) + n = n + 1; out[n] = _b end -- field 56: map_int32_int32 v = t.map_int32_int32 @@ -1446,20 +1528,24 @@ end -- field 112: oneof_nested_message v = t.oneof_nested_message if _of_oneof_field == "oneof_nested_message" then + local _b = M.TestAllTypesProto3_NestedMessage_encode(v) n = n + 1; out[n] = "\x82\x07" - n = n + 1; out[n] = wire.encode_len(M.TestAllTypesProto3_NestedMessage_encode(v)) + n = n + 1; out[n] = wire.encode_varint(#_b) + n = n + 1; out[n] = _b end -- field 113: oneof_string v = t.oneof_string if _of_oneof_field == "oneof_string" then n = n + 1; out[n] = "\x8a\x07" - n = n + 1; out[n] = wire.encode_string(v) + n = n + 1; out[n] = wire.encode_varint(#v) + n = n + 1; out[n] = v end -- field 114: oneof_bytes v = t.oneof_bytes if _of_oneof_field == "oneof_bytes" then n = n + 1; out[n] = "\x92\x07" - n = n + 1; out[n] = wire.encode_bytes(v) + n = n + 1; out[n] = wire.encode_varint(#v) + n = n + 1; out[n] = v end -- field 115: oneof_bool v = t.oneof_bool @@ -1510,64 +1596,84 @@ end -- field 201: optional_bool_wrapper v = t.optional_bool_wrapper if v ~= nil or type(v) == 'cdata' then + local _b = pb.wkt.BoolValue_encode(v) n = n + 1; out[n] = "\xca\x0c" - n = n + 1; out[n] = wire.encode_len(pb.wkt.BoolValue_encode(v)) + n = n + 1; out[n] = wire.encode_varint(#_b) + n = n + 1; out[n] = _b end -- field 202: optional_int32_wrapper v = t.optional_int32_wrapper if v ~= nil or type(v) == 'cdata' then + local _b = pb.wkt.Int32Value_encode(v) n = n + 1; out[n] = "\xd2\x0c" - n = n + 1; out[n] = wire.encode_len(pb.wkt.Int32Value_encode(v)) + n = n + 1; out[n] = wire.encode_varint(#_b) + n = n + 1; out[n] = _b end -- field 203: optional_int64_wrapper v = t.optional_int64_wrapper if v ~= nil or type(v) == 'cdata' then + local _b = pb.wkt.Int64Value_encode(v) n = n + 1; out[n] = "\xda\x0c" - n = n + 1; out[n] = wire.encode_len(pb.wkt.Int64Value_encode(v)) + n = n + 1; out[n] = wire.encode_varint(#_b) + n = n + 1; out[n] = _b end -- field 204: optional_uint32_wrapper v = t.optional_uint32_wrapper if v ~= nil or type(v) == 'cdata' then + local _b = pb.wkt.UInt32Value_encode(v) n = n + 1; out[n] = "\xe2\x0c" - n = n + 1; out[n] = wire.encode_len(pb.wkt.UInt32Value_encode(v)) + n = n + 1; out[n] = wire.encode_varint(#_b) + n = n + 1; out[n] = _b end -- field 205: optional_uint64_wrapper v = t.optional_uint64_wrapper if v ~= nil or type(v) == 'cdata' then + local _b = pb.wkt.UInt64Value_encode(v) n = n + 1; out[n] = "\xea\x0c" - n = n + 1; out[n] = wire.encode_len(pb.wkt.UInt64Value_encode(v)) + n = n + 1; out[n] = wire.encode_varint(#_b) + n = n + 1; out[n] = _b end -- field 206: optional_float_wrapper v = t.optional_float_wrapper if v ~= nil or type(v) == 'cdata' then + local _b = pb.wkt.FloatValue_encode(v) n = n + 1; out[n] = "\xf2\x0c" - n = n + 1; out[n] = wire.encode_len(pb.wkt.FloatValue_encode(v)) + n = n + 1; out[n] = wire.encode_varint(#_b) + n = n + 1; out[n] = _b end -- field 207: optional_double_wrapper v = t.optional_double_wrapper if v ~= nil or type(v) == 'cdata' then + local _b = pb.wkt.DoubleValue_encode(v) n = n + 1; out[n] = "\xfa\x0c" - n = n + 1; out[n] = wire.encode_len(pb.wkt.DoubleValue_encode(v)) + n = n + 1; out[n] = wire.encode_varint(#_b) + n = n + 1; out[n] = _b end -- field 208: optional_string_wrapper v = t.optional_string_wrapper if v ~= nil or type(v) == 'cdata' then + local _b = pb.wkt.StringValue_encode(v) n = n + 1; out[n] = "\x82\x0d" - n = n + 1; out[n] = wire.encode_len(pb.wkt.StringValue_encode(v)) + n = n + 1; out[n] = wire.encode_varint(#_b) + n = n + 1; out[n] = _b end -- field 209: optional_bytes_wrapper v = t.optional_bytes_wrapper if v ~= nil or type(v) == 'cdata' then + local _b = pb.wkt.BytesValue_encode(v) n = n + 1; out[n] = "\x8a\x0d" - n = n + 1; out[n] = wire.encode_len(pb.wkt.BytesValue_encode(v)) + n = n + 1; out[n] = wire.encode_varint(#_b) + n = n + 1; out[n] = _b end -- field 211: repeated_bool_wrapper v = t.repeated_bool_wrapper if v ~= nil and #v > 0 then local _tag = "\x9a\x0d" for _i = 1, #v do + local _b = pb.wkt.BoolValue_encode(v[_i]) n = n + 1; out[n] = _tag - n = n + 1; out[n] = wire.encode_len(pb.wkt.BoolValue_encode(v[_i])) + n = n + 1; out[n] = wire.encode_varint(#_b) + n = n + 1; out[n] = _b end end -- field 212: repeated_int32_wrapper @@ -1575,8 +1681,10 @@ v = t.repeated_int32_wrapper if v ~= nil and #v > 0 then local _tag = "\xa2\x0d" for _i = 1, #v do + local _b = pb.wkt.Int32Value_encode(v[_i]) n = n + 1; out[n] = _tag - n = n + 1; out[n] = wire.encode_len(pb.wkt.Int32Value_encode(v[_i])) + n = n + 1; out[n] = wire.encode_varint(#_b) + n = n + 1; out[n] = _b end end -- field 213: repeated_int64_wrapper @@ -1584,8 +1692,10 @@ v = t.repeated_int64_wrapper if v ~= nil and #v > 0 then local _tag = "\xaa\x0d" for _i = 1, #v do + local _b = pb.wkt.Int64Value_encode(v[_i]) n = n + 1; out[n] = _tag - n = n + 1; out[n] = wire.encode_len(pb.wkt.Int64Value_encode(v[_i])) + n = n + 1; out[n] = wire.encode_varint(#_b) + n = n + 1; out[n] = _b end end -- field 214: repeated_uint32_wrapper @@ -1593,8 +1703,10 @@ v = t.repeated_uint32_wrapper if v ~= nil and #v > 0 then local _tag = "\xb2\x0d" for _i = 1, #v do + local _b = pb.wkt.UInt32Value_encode(v[_i]) n = n + 1; out[n] = _tag - n = n + 1; out[n] = wire.encode_len(pb.wkt.UInt32Value_encode(v[_i])) + n = n + 1; out[n] = wire.encode_varint(#_b) + n = n + 1; out[n] = _b end end -- field 215: repeated_uint64_wrapper @@ -1602,8 +1714,10 @@ v = t.repeated_uint64_wrapper if v ~= nil and #v > 0 then local _tag = "\xba\x0d" for _i = 1, #v do + local _b = pb.wkt.UInt64Value_encode(v[_i]) n = n + 1; out[n] = _tag - n = n + 1; out[n] = wire.encode_len(pb.wkt.UInt64Value_encode(v[_i])) + n = n + 1; out[n] = wire.encode_varint(#_b) + n = n + 1; out[n] = _b end end -- field 216: repeated_float_wrapper @@ -1611,8 +1725,10 @@ v = t.repeated_float_wrapper if v ~= nil and #v > 0 then local _tag = "\xc2\x0d" for _i = 1, #v do + local _b = pb.wkt.FloatValue_encode(v[_i]) n = n + 1; out[n] = _tag - n = n + 1; out[n] = wire.encode_len(pb.wkt.FloatValue_encode(v[_i])) + n = n + 1; out[n] = wire.encode_varint(#_b) + n = n + 1; out[n] = _b end end -- field 217: repeated_double_wrapper @@ -1620,8 +1736,10 @@ v = t.repeated_double_wrapper if v ~= nil and #v > 0 then local _tag = "\xca\x0d" for _i = 1, #v do + local _b = pb.wkt.DoubleValue_encode(v[_i]) n = n + 1; out[n] = _tag - n = n + 1; out[n] = wire.encode_len(pb.wkt.DoubleValue_encode(v[_i])) + n = n + 1; out[n] = wire.encode_varint(#_b) + n = n + 1; out[n] = _b end end -- field 218: repeated_string_wrapper @@ -1629,8 +1747,10 @@ v = t.repeated_string_wrapper if v ~= nil and #v > 0 then local _tag = "\xd2\x0d" for _i = 1, #v do + local _b = pb.wkt.StringValue_encode(v[_i]) n = n + 1; out[n] = _tag - n = n + 1; out[n] = wire.encode_len(pb.wkt.StringValue_encode(v[_i])) + n = n + 1; out[n] = wire.encode_varint(#_b) + n = n + 1; out[n] = _b end end -- field 219: repeated_bytes_wrapper @@ -1638,45 +1758,59 @@ v = t.repeated_bytes_wrapper if v ~= nil and #v > 0 then local _tag = "\xda\x0d" for _i = 1, #v do + local _b = pb.wkt.BytesValue_encode(v[_i]) n = n + 1; out[n] = _tag - n = n + 1; out[n] = wire.encode_len(pb.wkt.BytesValue_encode(v[_i])) + n = n + 1; out[n] = wire.encode_varint(#_b) + n = n + 1; out[n] = _b end end -- field 301: optional_duration v = t.optional_duration if v ~= nil or type(v) == 'cdata' then + local _b = pb.wkt.Duration_encode(v) n = n + 1; out[n] = "\xea\x12" - n = n + 1; out[n] = wire.encode_len(pb.wkt.Duration_encode(v)) + n = n + 1; out[n] = wire.encode_varint(#_b) + n = n + 1; out[n] = _b end -- field 302: optional_timestamp v = t.optional_timestamp if v ~= nil or type(v) == 'cdata' then + local _b = pb.wkt.Timestamp_encode(v) n = n + 1; out[n] = "\xf2\x12" - n = n + 1; out[n] = wire.encode_len(pb.wkt.Timestamp_encode(v)) + n = n + 1; out[n] = wire.encode_varint(#_b) + n = n + 1; out[n] = _b end -- field 303: optional_field_mask v = t.optional_field_mask if v ~= nil or type(v) == 'cdata' then + local _b = pb.wkt.FieldMask_encode(v) n = n + 1; out[n] = "\xfa\x12" - n = n + 1; out[n] = wire.encode_len(pb.wkt.FieldMask_encode(v)) + n = n + 1; out[n] = wire.encode_varint(#_b) + n = n + 1; out[n] = _b end -- field 304: optional_struct v = t.optional_struct if v ~= nil or type(v) == 'cdata' then + local _b = pb.wkt.Struct_encode(v) n = n + 1; out[n] = "\x82\x13" - n = n + 1; out[n] = wire.encode_len(pb.wkt.Struct_encode(v)) + n = n + 1; out[n] = wire.encode_varint(#_b) + n = n + 1; out[n] = _b end -- field 305: optional_any v = t.optional_any if v ~= nil or type(v) == 'cdata' then + local _b = pb.wkt.Any_encode(v) n = n + 1; out[n] = "\x8a\x13" - n = n + 1; out[n] = wire.encode_len(pb.wkt.Any_encode(v)) + n = n + 1; out[n] = wire.encode_varint(#_b) + n = n + 1; out[n] = _b end -- field 306: optional_value v = t.optional_value if v ~= nil or type(v) == 'cdata' then + local _b = pb.wkt.Value_encode(v) n = n + 1; out[n] = "\x92\x13" - n = n + 1; out[n] = wire.encode_len(pb.wkt.Value_encode(v)) + n = n + 1; out[n] = wire.encode_varint(#_b) + n = n + 1; out[n] = _b end -- field 307: optional_null_value v = t.optional_null_value @@ -1694,16 +1828,20 @@ end -- field 308: optional_empty v = t.optional_empty if v ~= nil or type(v) == 'cdata' then + local _b = pb.wkt.Empty_encode(v) n = n + 1; out[n] = "\xa2\x13" - n = n + 1; out[n] = wire.encode_len(pb.wkt.Empty_encode(v)) + n = n + 1; out[n] = wire.encode_varint(#_b) + n = n + 1; out[n] = _b end -- field 311: repeated_duration v = t.repeated_duration if v ~= nil and #v > 0 then local _tag = "\xba\x13" for _i = 1, #v do + local _b = pb.wkt.Duration_encode(v[_i]) n = n + 1; out[n] = _tag - n = n + 1; out[n] = wire.encode_len(pb.wkt.Duration_encode(v[_i])) + n = n + 1; out[n] = wire.encode_varint(#_b) + n = n + 1; out[n] = _b end end -- field 312: repeated_timestamp @@ -1711,8 +1849,10 @@ v = t.repeated_timestamp if v ~= nil and #v > 0 then local _tag = "\xc2\x13" for _i = 1, #v do + local _b = pb.wkt.Timestamp_encode(v[_i]) n = n + 1; out[n] = _tag - n = n + 1; out[n] = wire.encode_len(pb.wkt.Timestamp_encode(v[_i])) + n = n + 1; out[n] = wire.encode_varint(#_b) + n = n + 1; out[n] = _b end end -- field 313: repeated_fieldmask @@ -1720,8 +1860,10 @@ v = t.repeated_fieldmask if v ~= nil and #v > 0 then local _tag = "\xca\x13" for _i = 1, #v do + local _b = pb.wkt.FieldMask_encode(v[_i]) n = n + 1; out[n] = _tag - n = n + 1; out[n] = wire.encode_len(pb.wkt.FieldMask_encode(v[_i])) + n = n + 1; out[n] = wire.encode_varint(#_b) + n = n + 1; out[n] = _b end end -- field 324: repeated_struct @@ -1729,8 +1871,10 @@ v = t.repeated_struct if v ~= nil and #v > 0 then local _tag = "\xa2\x14" for _i = 1, #v do + local _b = pb.wkt.Struct_encode(v[_i]) n = n + 1; out[n] = _tag - n = n + 1; out[n] = wire.encode_len(pb.wkt.Struct_encode(v[_i])) + n = n + 1; out[n] = wire.encode_varint(#_b) + n = n + 1; out[n] = _b end end -- field 315: repeated_any @@ -1738,8 +1882,10 @@ v = t.repeated_any if v ~= nil and #v > 0 then local _tag = "\xda\x13" for _i = 1, #v do + local _b = pb.wkt.Any_encode(v[_i]) n = n + 1; out[n] = _tag - n = n + 1; out[n] = wire.encode_len(pb.wkt.Any_encode(v[_i])) + n = n + 1; out[n] = wire.encode_varint(#_b) + n = n + 1; out[n] = _b end end -- field 316: repeated_value @@ -1747,8 +1893,10 @@ v = t.repeated_value if v ~= nil and #v > 0 then local _tag = "\xe2\x13" for _i = 1, #v do + local _b = pb.wkt.Value_encode(v[_i]) n = n + 1; out[n] = _tag - n = n + 1; out[n] = wire.encode_len(pb.wkt.Value_encode(v[_i])) + n = n + 1; out[n] = wire.encode_varint(#_b) + n = n + 1; out[n] = _b end end -- field 317: repeated_list_value @@ -1756,8 +1904,10 @@ v = t.repeated_list_value if v ~= nil and #v > 0 then local _tag = "\xea\x13" for _i = 1, #v do + local _b = pb.wkt.ListValue_encode(v[_i]) n = n + 1; out[n] = _tag - n = n + 1; out[n] = wire.encode_len(pb.wkt.ListValue_encode(v[_i])) + n = n + 1; out[n] = wire.encode_varint(#_b) + n = n + 1; out[n] = _b end end -- field 318: repeated_empty @@ -1765,8 +1915,10 @@ v = t.repeated_empty if v ~= nil and #v > 0 then local _tag = "\xf2\x13" for _i = 1, #v do + local _b = pb.wkt.Empty_encode(v[_i]) n = n + 1; out[n] = _tag - n = n + 1; out[n] = wire.encode_len(pb.wkt.Empty_encode(v[_i])) + n = n + 1; out[n] = wire.encode_varint(#_b) + n = n + 1; out[n] = _b end end -- field 401: fieldname1 @@ -3569,8 +3721,10 @@ end -- field 2: corecursive v = t.corecursive if v ~= nil or type(v) == 'cdata' then + local _b = M.TestAllTypesProto3_encode(v) n = n + 1; out[n] = "\x12" - n = n + 1; out[n] = wire.encode_len(M.TestAllTypesProto3_encode(v)) + n = n + 1; out[n] = wire.encode_varint(#_b) + n = n + 1; out[n] = _b end local _uf = t._unknown_fields if _uf ~= nil and _uf ~= '' then n = n + 1; out[n] = _uf end diff --git a/runtime/pb/codec.lua b/runtime/pb/codec.lua index d0d635477b885eae7d7b7e49d9088009008c6267..3bc4eb58fd561b29eca7b3fa63abaa3b03939cad 100644 --- a/runtime/pb/codec.lua +++ b/runtime/pb/codec.lua @@ -271,6 +271,12 @@ local handler = scalar[f.proto_type] if not handler then return nil end local encode_value = handler.encode + -- Split length-prefix emission: emit `tag → varint(#payload) + -- → payload` as three separate `out` slots instead of letting + -- `wire.encode_len` concatenate the prefix and body. Saves the + -- per-field string allocation; table.concat at the end joins + -- everything in one pass. Mirror of the inline.go codegen + -- change for full mode. if f.packed and handler.packable then local tag_bytes = wire.encode_tag(f.id, wire.WIRE_LEN) return function(data, out) @@ -283,12 +289,32 @@ for i = 1, nv do parts[i] = encode_value(v[i]) end local payload = table.concat(parts) local n = #out out[n + 1] = tag_bytes - out[n + 2] = wire.encode_len(payload) + out[n + 2] = wire.encode_varint(#payload) + out[n + 3] = payload + end + end + + -- Unpacked repeated string/bytes: split each element's length + -- prefix from its body, same rationale as above. + if f.proto_type == 'string' or f.proto_type == 'bytes' then + local tag_bytes = wire.encode_tag(f.id, handler.wire) + return function(data, out) + local v = data[fname] + if v == nil then return end + local nv = #v + if nv == 0 then return end + local n = #out + for i = 1, nv do + local s = v[i] + n = n + 1; out[n] = tag_bytes + n = n + 1; out[n] = wire.encode_varint(#s) + n = n + 1; out[n] = s + end end end - -- Unpacked repeated scalar (also covers string/bytes — LEN - -- wire type, which is non-packable by proto3 rules). + -- Unpacked repeated numeric/bool scalar: not length-delimited, + -- emit tag + encoded value per element. local tag_bytes = wire.encode_tag(f.id, handler.wire) return function(data, out) local v = data[fname] @@ -313,8 +339,10 @@ local nv = #v if nv == 0 then return end local n = #out for i = 1, nv do + local body = encode_msg(sub_desc, v[i]) n = n + 1; out[n] = tag_bytes - n = n + 1; out[n] = wire.encode_len(encode_msg(sub_desc, v[i])) + n = n + 1; out[n] = wire.encode_varint(#body) + n = n + 1; out[n] = body end end end @@ -333,9 +361,11 @@ local parts = {} for i = 1, nv do parts[i] = wire.encode_varint(encode_enum_value(enum_desc, v[i])) end + local payload = table.concat(parts) local n = #out out[n + 1] = tag_bytes - out[n + 2] = wire.encode_len(table.concat(parts)) + out[n + 2] = wire.encode_varint(#payload) + out[n + 3] = payload end end local tag_bytes = wire.encode_tag(f.id, wire.WIRE_VARINT) @@ -383,12 +413,17 @@ end end if proto_type == 'string' or proto_type == 'bytes' then + -- Split: emit tag + varint(#v) + v as three separate `out` + -- slots, avoiding the per-field `varint(#v) .. v` concat + -- that `encode_value` (== wire.encode_string/bytes) would + -- do. See packed/repeated writers above for the rationale. return function(data, out) local v = data[fname] if v == nil or v == '' then return end local n = #out out[n + 1] = tag_bytes - out[n + 2] = encode_value(v) + out[n + 2] = wire.encode_varint(#v) + out[n + 3] = v end end if proto_type == 'bool' then @@ -438,9 +473,11 @@ -- google.protobuf.Value uses box.NULL as the canonical -- null_value sentinel — its sub_desc.encode handles it. Only -- treat the field as absent if it's actually nil (no cdata). if v == nil and type(v) ~= 'cdata' then return end + local body = encode_msg(sub_desc, v) local n = #out out[n + 1] = tag_bytes - out[n + 2] = wire.encode_len(encode_msg(sub_desc, v)) + out[n + 2] = wire.encode_varint(#body) + out[n + 3] = body end end diff --git a/runtime/pb/wire.lua b/runtime/pb/wire.lua index 40eedb77ce6546a93b6dba614a59cca094ceea2a..6a9f58a49d67483a7a4719ddd01d443ebc435c80 100644 --- a/runtime/pb/wire.lua +++ b/runtime/pb/wire.lua @@ -84,14 +84,59 @@ -- string.char(n) call with no cdata allocation, no `out` table, no -- table.concat. Covers most length prefixes for short strings, many -- enum ordinals, and most small int values in typical RPC payloads. -- --- We deliberately do NOT extend the fast path to 2-4 byte values: --- growing the function past the LuaJIT inline budget makes parent --- traces stop inlining it, which costs more (~30% bench regression --- on 1-byte-dominant workloads) than the rare multi-byte case gains. -local function encode_varint(n) - if type(n) == 'number' and n >= 0 and n < 0x80 then - return string.char(n) +-- The outer function is kept tiny on purpose — adding 2/3/4-byte +-- branches to `encode_varint` itself pushes it past LuaJIT's inline +-- budget so parent traces stop inlining it, regressing the +-- 1-byte-dominant workloads by ~30%. Multi-byte Lua-number fast paths +-- live in `encode_varint_slow` below, which is not inlined into hot +-- traces anyway — so its size doesn't matter. +local encode_varint_slow + +-- encode_varint_slow: handles every input that doesn't fit the +-- 1-byte fast path in `encode_varint`. Three layers, falling through: +-- +-- 1. Non-negative Lua numbers < 2^28 are encoded via `bit.rshift` / +-- `bit.band` / `string.char` — bit ops on Lua numbers operate as +-- uint32 and don't allocate cdata. Values up to 4 bytes covered. +-- 2. Non-negative Lua numbers in [2^28, 2^53) are still exact in +-- double precision but exceed uint32 — emit one byte through bit +-- ops, then recurse with `n / 128` on the smaller residue. +-- 3. Everything else (cdata uint64/int64, negative Lua numbers — the +-- latter get sign-extended to 10-byte varints) goes through the +-- uint64 cdata loop. Pre-change measurement: 18x slower than the +-- 1-byte fast path; the Lua-number paths above bring 2-byte to +-- ~2x of the fast path instead. +encode_varint_slow = function(n) + if type(n) == 'number' and n >= 0 then + if n < 0x4000 then -- 2-byte + return string.char( + bit.bor(bit.band(n, 0x7f), 0x80), + bit.rshift(n, 7)) + end + if n < 0x200000 then -- 3-byte + return string.char( + bit.bor(bit.band(n, 0x7f), 0x80), + bit.bor(bit.band(bit.rshift(n, 7), 0x7f), 0x80), + bit.rshift(n, 14)) + end + if n < 0x10000000 then -- 4-byte (< 2^28, fits in uint32) + return string.char( + bit.bor(bit.band(n, 0x7f), 0x80), + bit.bor(bit.band(bit.rshift(n, 7), 0x7f), 0x80), + bit.bor(bit.band(bit.rshift(n, 14), 0x7f), 0x80), + bit.rshift(n, 21)) + end + -- 2^28 <= n < 2^53: still exact in double, but past uint32. + -- Emit one byte via Lua-number bit op, then recurse on the + -- residue (which is now < n/128 and may now fit a fast path). + if n < 2^53 then + return string.char(bit.bor(bit.band(n, 0x7f), 0x80)) + .. encode_varint_slow(math.floor(n / 128)) + end end + -- Fallback: uint64 cdata path. Reached by cdata inputs, negative + -- Lua numbers (sign-extended to 10-byte varint), and the (rare) + -- case of a Lua number larger than 2^53. n = to_uint64(n) local out = {} local i = 1 @@ -102,6 +147,13 @@ i = i + 1 end out[i] = string.char(tonumber(n)) return table.concat(out) +end + +local function encode_varint(n) + if type(n) == 'number' and n >= 0 and n < 0x80 then + return string.char(n) + end + return encode_varint_slow(n) end M.encode_varint = encode_varint