diff options
author | Scott James Remnant <keybuk@google.com> | 2022-03-23 17:05:08 -0700 |
---|---|---|
committer | CQ Bot Account <pigweed-scoped@luci-project-accounts.iam.gserviceaccount.com> | 2022-03-25 21:45:05 +0000 |
commit | 68e1a9f5e4b0d86745869cab593fc9e43d3296d7 (patch) | |
tree | 352fdfefaf3306a427cd23126345b94b76235cf1 | |
parent | 75c7684dd24b4de1d2dab20ea6d920023b10dff4 (diff) | |
download | pigweed-68e1a9f5e4b0d86745869cab593fc9e43d3296d7.tar.gz |
pw_protobuf: Support encoding packed bool fields
Change-Id: I21b0f2b82f8761afa94216cebfa7ef7c4fe6e0d6
Reviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/88962
Pigweed-Auto-Submit: Scott James Remnant <keybuk@google.com>
Reviewed-by: Armando Montanez <amontanez@google.com>
Commit-Queue: Auto-Submit <auto-submit@pigweed.google.com.iam.gserviceaccount.com>
-rw-r--r-- | pw_protobuf/codegen_encoder_test.cc | 23 | ||||
-rw-r--r-- | pw_protobuf/encoder_test.cc | 20 | ||||
-rw-r--r-- | pw_protobuf/public/pw_protobuf/encoder.h | 20 | ||||
-rw-r--r-- | pw_protobuf/pw_protobuf_test_protos/repeated.proto | 1 | ||||
-rw-r--r-- | pw_protobuf/py/pw_protobuf/codegen_pwpb.py | 13 |
5 files changed, 73 insertions, 4 deletions
diff --git a/pw_protobuf/codegen_encoder_test.cc b/pw_protobuf/codegen_encoder_test.cc index 6c0866bc9..2787681e3 100644 --- a/pw_protobuf/codegen_encoder_test.cc +++ b/pw_protobuf/codegen_encoder_test.cc @@ -320,6 +320,29 @@ TEST(CodegenRepeated, PackedScalar) { 0); } +TEST(CodegenRepeated, PackedBool) { + std::byte encode_buffer[32]; + + stream::MemoryWriter writer(encode_buffer); + RepeatedTest::StreamEncoder repeated_test(writer, ByteSpan()); + constexpr bool values[] = {true, false, true, true, false}; + repeated_test.WriteBools(std::span(values)) + .IgnoreError(); // TODO(pwbug/387): Handle Status properly + + // clang-format off + constexpr uint8_t expected_proto[] = { + // bools[], v={true, false, true, true, false} + 0x3a, 0x05, 0x01, 0x00, 0x01, 0x01, 0x00, + }; + // clang-format on + + ConstByteSpan result = writer.WrittenData(); + ASSERT_EQ(repeated_test.status(), OkStatus()); + EXPECT_EQ(result.size(), sizeof(expected_proto)); + EXPECT_EQ(std::memcmp(result.data(), expected_proto, sizeof(expected_proto)), + 0); +} + TEST(CodegenRepeated, NonScalar) { std::byte encode_buffer[32]; diff --git a/pw_protobuf/encoder_test.cc b/pw_protobuf/encoder_test.cc index 1ab005aca..3c01c5570 100644 --- a/pw_protobuf/encoder_test.cc +++ b/pw_protobuf/encoder_test.cc @@ -307,6 +307,26 @@ TEST(StreamEncoder, PackedVarintInsufficientSpace) { EXPECT_EQ(encoder.status(), Status::ResourceExhausted()); } +TEST(StreamEncoder, PackedBool) { + std::byte encode_buffer[32]; + MemoryEncoder encoder(encode_buffer); + + // repeated bool values = 1; + constexpr bool values[] = {true, false, true, true, false}; + encoder.WritePackedBool(1, values) + .IgnoreError(); // TODO(pwbug/387): Handle Status properly + + constexpr uint8_t encoded_proto[] = { + 0x0a, 0x05, 0x01, 0x00, 0x01, 0x01, 0x00}; + // key size v[0] v[1] v[2] v[3] v[4] + + ASSERT_EQ(encoder.status(), OkStatus()); + ConstByteSpan result(encoder); + EXPECT_EQ(result.size(), sizeof(encoded_proto)); + EXPECT_EQ(std::memcmp(result.data(), encoded_proto, sizeof(encoded_proto)), + 0); +} + TEST(StreamEncoder, PackedFixed) { std::byte encode_buffer[32]; MemoryEncoder encoder(encode_buffer); diff --git a/pw_protobuf/public/pw_protobuf/encoder.h b/pw_protobuf/public/pw_protobuf/encoder.h index c3d68ad6b..41117db28 100644 --- a/pw_protobuf/public/pw_protobuf/encoder.h +++ b/pw_protobuf/public/pw_protobuf/encoder.h @@ -275,6 +275,19 @@ class StreamEncoder { return WriteUint32(field_number, static_cast<uint32_t>(value)); } + // Writes a repeated bool using packed encoding. + // + // Precondition: Encoder has no active child encoder. + Status WritePackedBool(uint32_t field_number, std::span<const bool> values) { + static_assert(sizeof(bool) == sizeof(uint8_t), + "bool must be same size as uint8_t"); + return WritePackedVarints( + field_number, + std::span(reinterpret_cast<const uint8_t*>(values.data()), + values.size()), + VarintEncodeType::kNormal); + } + // Writes a proto fixed32 key-value pair. // // Precondition: Encoder has no active child encoder. @@ -531,12 +544,13 @@ class StreamEncoder { Status WritePackedVarints(uint32_t field_number, std::span<T> values, VarintEncodeType encode_type) { - static_assert(std::is_same<T, const uint32_t>::value || + static_assert(std::is_same<T, const uint8_t>::value || + std::is_same<T, const uint32_t>::value || std::is_same<T, const int32_t>::value || std::is_same<T, const uint64_t>::value || std::is_same<T, const int64_t>::value, - "Packed varints must be of type uint32_t, int32_t, uint64_t, " - "or int64_t"); + "Packed varints must be of type bool, uint32_t, int32_t, " + "uint64_t, or int64_t"); size_t payload_size = 0; for (T val : values) { diff --git a/pw_protobuf/pw_protobuf_test_protos/repeated.proto b/pw_protobuf/pw_protobuf_test_protos/repeated.proto index 49fbbd204..590d2e00c 100644 --- a/pw_protobuf/pw_protobuf_test_protos/repeated.proto +++ b/pw_protobuf/pw_protobuf_test_protos/repeated.proto @@ -22,6 +22,7 @@ message RepeatedTest { repeated double doubles = 4; repeated Struct structs = 5; repeated fixed32 fixed32s = 6; + repeated bool bools = 7; }; message Struct { diff --git a/pw_protobuf/py/pw_protobuf/codegen_pwpb.py b/pw_protobuf/py/pw_protobuf/codegen_pwpb.py index a7ef3cab0..ae54bd88f 100644 --- a/pw_protobuf/py/pw_protobuf/codegen_pwpb.py +++ b/pw_protobuf/py/pw_protobuf/codegen_pwpb.py @@ -929,6 +929,15 @@ class BoolWriteMethod(WriteMethod): return 'WriteBool' +class PackedBoolWriteMethod(PackedWriteMethod): + """Method which writes a packed list of bools.""" + def params(self) -> List[Tuple[str, str]]: + return [('std::span<const bool>', 'values')] + + def _encoder_fn(self) -> str: + return 'WritePackedBool' + + class BoolReadMethod(ReadMethod): """Method which reads a proto bool value.""" def _result_type(self) -> str: @@ -1061,7 +1070,9 @@ PROTO_FIELD_WRITE_METHODS: Dict[int, List] = { [Uint64WriteMethod, PackedUint64WriteMethod], descriptor_pb2.FieldDescriptorProto.TYPE_FIXED64: [Fixed64WriteMethod, PackedFixed64WriteMethod], - descriptor_pb2.FieldDescriptorProto.TYPE_BOOL: [BoolWriteMethod], + descriptor_pb2.FieldDescriptorProto.TYPE_BOOL: [ + BoolWriteMethod, PackedBoolWriteMethod + ], descriptor_pb2.FieldDescriptorProto.TYPE_BYTES: [BytesWriteMethod], descriptor_pb2.FieldDescriptorProto.TYPE_STRING: [ StringLenWriteMethod, StringWriteMethod |