pw_protobuf: Fixed bug when using proto package without prefix pw.*
When generating code using the pw protobuf plugin if the .proto does
not contain 'package pw.*;' then namespace pw is not added. This
results in errors around span<> not being found.
Changing all strings in the code generator from regex 'span<(.*)>' to
'std::span<$1>' solves this problem. A regression test proto has been
added to prevent this problem in future.
Change-Id: I5fa2f750a3ff562b7e28da667b8148a04a6fc579
Reviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/12620
Reviewed-by: Wyatt Hepler <hepler@google.com>
Commit-Queue: Wyatt Hepler <hepler@google.com>
diff --git a/pw_protobuf/BUILD.gn b/pw_protobuf/BUILD.gn
index a34c0c8..5a4e800 100644
--- a/pw_protobuf/BUILD.gn
+++ b/pw_protobuf/BUILD.gn
@@ -101,6 +101,7 @@
"pw_protobuf_protos/test_protos/full_test.proto",
"pw_protobuf_protos/test_protos/imported.proto",
"pw_protobuf_protos/test_protos/importer.proto",
+ "pw_protobuf_protos/test_protos/non_pw_package.proto",
"pw_protobuf_protos/test_protos/proto2.proto",
"pw_protobuf_protos/test_protos/repeated.proto",
]
diff --git a/pw_protobuf/codegen_test.cc b/pw_protobuf/codegen_test.cc
index 273b170..1001a86 100644
--- a/pw_protobuf/codegen_test.cc
+++ b/pw_protobuf/codegen_test.cc
@@ -11,6 +11,7 @@
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
// License for the specific language governing permissions and limitations under
// the License.
+#include <span>
#include "gtest/gtest.h"
#include "pw_protobuf/encoder.h"
@@ -24,6 +25,7 @@
// low-level encoder.
#include "pw_protobuf_protos/test_protos/full_test.pwpb.h"
#include "pw_protobuf_protos/test_protos/importer.pwpb.h"
+#include "pw_protobuf_protos/test_protos/non_pw_package.pwpb.h"
#include "pw_protobuf_protos/test_protos/proto2.pwpb.h"
#include "pw_protobuf_protos/test_protos/repeated.pwpb.h"
@@ -295,5 +297,18 @@
EXPECT_EQ(encoder.Encode(&proto), Status::OK);
}
+TEST(Codegen, NonPigweedPackage) {
+ using namespace non::pigweed::package::name;
+ std::byte encode_buffer[64];
+ std::array<const int64_t, 2> repeated = {0, 1};
+ NestedEncoder<1, 2> encoder(encode_buffer);
+ Packed::Encoder packed(&encoder);
+ packed.WriteRep(std::span<const int64_t>(repeated));
+ packed.WritePacked("packed");
+
+ span<const std::byte> proto;
+ EXPECT_EQ(encoder.Encode(&proto), Status::OK);
+}
+
} // namespace
} // namespace pw::protobuf
diff --git a/pw_protobuf/pw_protobuf_protos/test_protos/non_pw_package.proto b/pw_protobuf/pw_protobuf_protos/test_protos/non_pw_package.proto
new file mode 100644
index 0000000..ddc11ff
--- /dev/null
+++ b/pw_protobuf/pw_protobuf_protos/test_protos/non_pw_package.proto
@@ -0,0 +1,26 @@
+// Copyright 2020 The Pigweed Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License"); you may not
+// use this file except in compliance with the License. You may obtain a copy of
+// the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+// License for the specific language governing permissions and limitations under
+// the License.
+syntax = "proto3";
+
+// Test that non-pigweed packages work as expected when generating code. Pigweed
+// packages start with `package pw.*` which results in some implicit
+// namespacing in generated code.
+package non.pigweed.package.name;
+
+// Packed has both a repeated and length delimited messaged type. This should
+// result in a span being generated in the corresponding *pwpb.h file.
+message Packed {
+ string packed = 1;
+ repeated int64 rep = 2;
+}
diff --git a/pw_protobuf/py/pw_protobuf/codegen_pwpb.py b/pw_protobuf/py/pw_protobuf/codegen_pwpb.py
index 5fb6661..b9760fa 100644
--- a/pw_protobuf/py/pw_protobuf/codegen_pwpb.py
+++ b/pw_protobuf/py/pw_protobuf/codegen_pwpb.py
@@ -207,7 +207,7 @@
class PackedDoubleMethod(PackedMethod):
"""Method which writes a packed list of doubles."""
def params(self) -> List[Tuple[str, str]]:
- return [('span<const double>', 'values')]
+ return [('std::span<const double>', 'values')]
def _encoder_fn(self) -> str:
return 'WritePackedDouble'
@@ -225,7 +225,7 @@
class PackedFloatMethod(PackedMethod):
"""Method which writes a packed list of floats."""
def params(self) -> List[Tuple[str, str]]:
- return [('span<const float>', 'values')]
+ return [('std::span<const float>', 'values')]
def _encoder_fn(self) -> str:
return 'WritePackedFloat'
@@ -243,7 +243,7 @@
class PackedInt32Method(PackedMethod):
"""Method which writes a packed list of int32."""
def params(self) -> List[Tuple[str, str]]:
- return [('span<const int32_t>', 'values')]
+ return [('std::span<const int32_t>', 'values')]
def _encoder_fn(self) -> str:
return 'WritePackedInt32'
@@ -261,7 +261,7 @@
class PackedSint32Method(PackedMethod):
"""Method which writes a packed list of sint32."""
def params(self) -> List[Tuple[str, str]]:
- return [('span<const int32_t>', 'values')]
+ return [('std::span<const int32_t>', 'values')]
def _encoder_fn(self) -> str:
return 'WritePackedSint32'
@@ -279,7 +279,7 @@
class PackedSfixed32Method(PackedMethod):
"""Method which writes a packed list of sfixed32."""
def params(self) -> List[Tuple[str, str]]:
- return [('span<const int32_t>', 'values')]
+ return [('std::span<const int32_t>', 'values')]
def _encoder_fn(self) -> str:
return 'WritePackedSfixed32'
@@ -297,7 +297,7 @@
class PackedInt64Method(PackedMethod):
"""Method which writes a proto int64 value."""
def params(self) -> List[Tuple[str, str]]:
- return [('span<const int64_t>', 'values')]
+ return [('std::span<const int64_t>', 'values')]
def _encoder_fn(self) -> str:
return 'WritePackedInt64'
@@ -315,7 +315,7 @@
class PackedSint64Method(PackedMethod):
"""Method which writes a proto sint64 value."""
def params(self) -> List[Tuple[str, str]]:
- return [('span<const int64_t>', 'values')]
+ return [('std::span<const int64_t>', 'values')]
def _encoder_fn(self) -> str:
return 'WritePackedSint64'
@@ -333,7 +333,7 @@
class PackedSfixed64Method(PackedMethod):
"""Method which writes a proto sfixed64 value."""
def params(self) -> List[Tuple[str, str]]:
- return [('span<const int64_t>', 'values')]
+ return [('std::span<const int64_t>', 'values')]
def _encoder_fn(self) -> str:
return 'WritePackedSfixed4'
@@ -351,7 +351,7 @@
class PackedUint32Method(PackedMethod):
"""Method which writes a proto uint32 value."""
def params(self) -> List[Tuple[str, str]]:
- return [('span<const uint32_t>', 'values')]
+ return [('std::span<const uint32_t>', 'values')]
def _encoder_fn(self) -> str:
return 'WritePackedUint32'
@@ -369,7 +369,7 @@
class PackedFixed32Method(PackedMethod):
"""Method which writes a proto fixed32 value."""
def params(self) -> List[Tuple[str, str]]:
- return [('span<const uint32_t>', 'values')]
+ return [('std::span<const uint32_t>', 'values')]
def _encoder_fn(self) -> str:
return 'WritePackedFixed32'
@@ -387,7 +387,7 @@
class PackedUint64Method(PackedMethod):
"""Method which writes a proto uint64 value."""
def params(self) -> List[Tuple[str, str]]:
- return [('span<const uint64_t>', 'values')]
+ return [('std::span<const uint64_t>', 'values')]
def _encoder_fn(self) -> str:
return 'WritePackedUint64'
@@ -405,7 +405,7 @@
class PackedFixed64Method(PackedMethod):
"""Method which writes a proto fixed64 value."""
def params(self) -> List[Tuple[str, str]]:
- return [('span<const uint64_t>', 'values')]
+ return [('std::span<const uint64_t>', 'values')]
def _encoder_fn(self) -> str:
return 'WritePackedFixed64'
@@ -423,7 +423,7 @@
class BytesMethod(WriteMethod):
"""Method which writes a proto bytes value."""
def params(self) -> List[Tuple[str, str]]:
- return [('span<const std::byte>', 'value')]
+ return [('std::span<const std::byte>', 'value')]
def _encoder_fn(self) -> str:
return 'WriteBytes'
@@ -682,7 +682,8 @@
output.write_line(f'// on {datetime.now()}')
output.write_line('#pragma once\n')
output.write_line('#include <cstddef>')
- output.write_line('#include <cstdint>\n')
+ output.write_line('#include <cstdint>')
+ output.write_line('#include <span>\n')
output.write_line('#include "pw_protobuf/codegen.h"')
for imported_file in file_descriptor_proto.dependency: