Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion smoke/generated/compat.protocyte.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -1809,7 +1809,7 @@ namespace protocyte_smoke::test::compat {
if (f_uint64_ != 0u) {
const auto st_size = ::protocyte::add_size(
total, ::protocyte::tag_size(static_cast<::protocyte::u32>(FieldNumber::f_uint64)) +
::protocyte::varint_size(static_cast<::protocyte::u64>(f_uint64_)));
::protocyte::varint_size(f_uint64_));
if (!st_size) {
return ::protocyte::unexpected(st_size.error());
}
Expand Down
6 changes: 3 additions & 3 deletions smoke/generated/example.protocyte.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -4630,7 +4630,7 @@ namespace test::ultimate {
{
const auto st_size = ::protocyte::add_size(
entry_payload, ::protocyte::tag_size(static_cast<::protocyte::u32>(EntryFieldNumber::key)) +
::protocyte::varint_size(static_cast<::protocyte::u64>(entry.key)));
::protocyte::varint_size(entry.key));
if (!st_size) {
return st_size.status();
}
Expand Down Expand Up @@ -4988,7 +4988,7 @@ namespace test::ultimate {
if (f_uint64_ != 0u) {
const auto st_size = ::protocyte::add_size(
total, ::protocyte::tag_size(static_cast<::protocyte::u32>(FieldNumber::f_uint64)) +
::protocyte::varint_size(static_cast<::protocyte::u64>(f_uint64_)));
::protocyte::varint_size(f_uint64_));
if (!st_size) {
return ::protocyte::unexpected(st_size.error());
}
Expand Down Expand Up @@ -5319,7 +5319,7 @@ namespace test::ultimate {
{
const auto st_size = ::protocyte::add_size(
entry_payload, ::protocyte::tag_size(static_cast<::protocyte::u32>(EntryFieldNumber::key)) +
::protocyte::varint_size(static_cast<::protocyte::u64>(entry.key)));
::protocyte::varint_size(entry.key));
if (!st_size) {
return ::protocyte::unexpected(st_size.error());
}
Expand Down
2 changes: 1 addition & 1 deletion smoke/generated/protocyte/runtime/runtime.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -3765,7 +3765,7 @@ namespace protocyte {
}

template<class Writer> Status write_uint64(Writer &writer, const u64 value) noexcept {
return write_varint_scalar(writer, value);
return write_varint(writer, value);
}

template<class Writer> Status write_bool(Writer &writer, const bool value) noexcept {
Expand Down
12 changes: 12 additions & 0 deletions smoke/src/host_smoke.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2554,6 +2554,18 @@ TEST_CASE("tag_size matches protobuf group sizing", "[smoke][runtime]") {
CHECK(protocyte::tag_size(large_field_number, protocyte::WireType::SGROUP) == single_tag_size * 2u);
}

TEST_CASE("write_uint64 emits canonical varint bytes", "[smoke][runtime]") {
std::array<protocyte::u8, 10u> encoded {};
protocyte::SliceWriter writer(encoded.data(), encoded.size());

require_success(protocyte::write_uint64(writer, 0x8000000000000000ull));

const std::array<protocyte::u8, 10u> expected {0x80u, 0x80u, 0x80u, 0x80u, 0x80u,
0x80u, 0x80u, 0x80u, 0x80u, 0x01u};
REQUIRE(writer.position() == expected.size());
for (protocyte::usize index {}; index < expected.size(); ++index) { CHECK(encoded[index] == expected[index]); }
}

TEST_CASE("length-delimited sizes reject values that do not fit usize", "[smoke][runtime]") {
if constexpr (sizeof(protocyte::usize) == sizeof(protocyte::u64)) {
SUCCEED("usize can represent every u64 length on this target");
Expand Down
6 changes: 6 additions & 0 deletions src/protocyte/cpp.py
Original file line number Diff line number Diff line change
Expand Up @@ -1916,10 +1916,16 @@ def _scalar_size(item: FieldModel, value: str) -> str:
width = _fixed_scalar_width(item)
if width is not None:
return width
return _varint_size_expr(item, value)


def _varint_size_expr(item: FieldModel, value: str) -> str:
if item.proto_type == FieldDescriptorProto.TYPE_SINT32:
return f"::protocyte::varint_size(::protocyte::encode_zigzag32({value}))"
if item.proto_type == FieldDescriptorProto.TYPE_SINT64:
return f"::protocyte::varint_size(::protocyte::encode_zigzag64({value}))"
if item.proto_type == FieldDescriptorProto.TYPE_UINT64:
return f"::protocyte::varint_size({value})"
return f"::protocyte::varint_size(static_cast<::protocyte::u64>({value}))"


Expand Down
2 changes: 1 addition & 1 deletion src/protocyte/runtime/runtime.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -3765,7 +3765,7 @@ namespace protocyte {
}

template<class Writer> Status write_uint64(Writer &writer, const u64 value) noexcept {
return write_varint_scalar(writer, value);
return write_varint(writer, value);
}

template<class Writer> Status write_bool(Writer &writer, const bool value) noexcept {
Expand Down
88 changes: 88 additions & 0 deletions tests/test_plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -1581,6 +1581,33 @@ def test_empty_message_comments_unused_writer_and_returns_zero_size() -> None:
assert "return ::protocyte::usize {};" in header


def test_generated_encoded_size_omits_redundant_uint64_varint_casts() -> None:
request = plugin_pb2.CodeGeneratorRequest()
request.file_to_generate.append("uint64_casts.proto")
request.proto_file.append(_uint64_casts_file())

response = generate_response(request)

assert not response.error
header = next(file.content for file in response.file if file.name == "uint64_casts.protocyte.hpp")
encoded_size_body = header.split(
"::protocyte::Result<::protocyte::usize> encoded_size() const noexcept {", maxsplit=1
)[1].split("\n};", maxsplit=1)[0]

assert "::protocyte::varint_size(version_)" in encoded_size_body
assert "::protocyte::varint_size(values_value)" in encoded_size_body
assert "::protocyte::varint_size(loose_values_value)" in encoded_size_body
assert "::protocyte::varint_size(choice.choice_value)" in encoded_size_body
assert "::protocyte::varint_size(entry.key)" in encoded_size_body
assert "::protocyte::varint_size(entry.value)" in encoded_size_body
assert "::protocyte::varint_size(static_cast<::protocyte::u64>(version_))" not in encoded_size_body
assert "::protocyte::varint_size(static_cast<::protocyte::u64>(values_value))" not in encoded_size_body
assert "::protocyte::varint_size(static_cast<::protocyte::u64>(loose_values_value))" not in encoded_size_body
assert "::protocyte::varint_size(static_cast<::protocyte::u64>(choice.choice_value))" not in encoded_size_body
assert "::protocyte::varint_size(static_cast<::protocyte::u64>(entry.key))" not in encoded_size_body
assert "::protocyte::varint_size(static_cast<::protocyte::u64>(entry.value))" not in encoded_size_body


def test_generated_header_keeps_runtime_status_globally_qualified() -> None:
request = plugin_pb2.CodeGeneratorRequest()
request.file_to_generate.append("namespaced.proto")
Expand Down Expand Up @@ -1688,6 +1715,67 @@ def _simple_file() -> descriptor_pb2.FileDescriptorProto:
return file


def _uint64_casts_file() -> descriptor_pb2.FileDescriptorProto:
file = descriptor_pb2.FileDescriptorProto()
file.name = "uint64_casts.proto"
file.package = "demo"
file.syntax = "proto3"

message = file.message_type.add()
message.name = "Uint64CastCases"

field = message.field.add()
field.name = "version"
field.number = 1
field.label = F.LABEL_OPTIONAL
field.type = F.TYPE_UINT64

field = message.field.add()
field.name = "values"
field.number = 2
field.label = F.LABEL_REPEATED
field.type = F.TYPE_UINT64
field.options.packed = True

field = message.field.add()
field.name = "loose_values"
field.number = 5
field.label = F.LABEL_REPEATED
field.type = F.TYPE_UINT64
field.options.packed = False

message.oneof_decl.add().name = "choice"
field = message.field.add()
field.name = "choice_value"
field.number = 3
field.label = F.LABEL_OPTIONAL
field.type = F.TYPE_UINT64
field.oneof_index = 0

entry = message.nested_type.add()
entry.name = "CountersEntry"
entry.options.map_entry = True
key = entry.field.add()
key.name = "key"
key.number = 1
key.label = F.LABEL_OPTIONAL
key.type = F.TYPE_UINT64
value = entry.field.add()
value.name = "value"
value.number = 2
value.label = F.LABEL_OPTIONAL
value.type = F.TYPE_UINT64

field = message.field.add()
field.name = "counters"
field.number = 4
field.label = F.LABEL_REPEATED
field.type = F.TYPE_MESSAGE
field.type_name = ".demo.Uint64CastCases.CountersEntry"

return file


def _constant_array_request() -> plugin_pb2.CodeGeneratorRequest:
request = plugin_pb2.CodeGeneratorRequest()
request.file_to_generate.append("arrays.proto")
Expand Down
Loading