aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorScott James Remnant <keybuk@google.com>2022-03-23 17:05:08 -0700
committerCQ Bot Account <pigweed-scoped@luci-project-accounts.iam.gserviceaccount.com>2022-03-25 21:45:05 +0000
commit68e1a9f5e4b0d86745869cab593fc9e43d3296d7 (patch)
tree352fdfefaf3306a427cd23126345b94b76235cf1
parent75c7684dd24b4de1d2dab20ea6d920023b10dff4 (diff)
downloadpigweed-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.cc23
-rw-r--r--pw_protobuf/encoder_test.cc20
-rw-r--r--pw_protobuf/public/pw_protobuf/encoder.h20
-rw-r--r--pw_protobuf/pw_protobuf_test_protos/repeated.proto1
-rw-r--r--pw_protobuf/py/pw_protobuf/codegen_pwpb.py13
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