pw_rpc: Support Nanopb versions 3 or 4 The type of the fields parameter changed between versions. Store the fields as const void* and deduce the type to cast them to from the pb_decode function. Change-Id: I31cf3ee2225b0c21a774031b34aa52bf7d8f3ea7
diff --git a/pw_rpc/nanopb/method.cc b/pw_rpc/nanopb/method.cc index e17d7ee..366e53a 100644 --- a/pw_rpc/nanopb/method.cc +++ b/pw_rpc/nanopb/method.cc
@@ -18,6 +18,22 @@ #include "pb_encode.h" namespace pw::rpc::internal { +namespace { + +// Nanopb 3 uses pb_field_s and Nanopb 4 uses pb_msgdesc_s for fields. The +// Nanopb version macro is difficult to use, so deduce the correct type from the +// pb_decode function. +template <typename DecodeFunction> +struct NanopbTraits; + +template <typename FieldsType> +struct NanopbTraits<bool(pb_istream_t*, FieldsType, void*)> { + using Fields = FieldsType; +}; + +using Fields = typename NanopbTraits<decltype(pb_decode)>::Fields; + +} // namespace using std::byte; @@ -25,15 +41,16 @@ void* proto_struct) const { auto input = pb_istream_from_buffer( reinterpret_cast<const pb_byte_t*>(buffer.data()), buffer.size()); - return pb_decode(&input, request_fields_, proto_struct) ? Status::OK - : Status::INTERNAL; + return pb_decode(&input, static_cast<Fields>(request_fields_), proto_struct) + ? Status::OK + : Status::INTERNAL; } StatusWithSize Method::EncodeResponse(const void* proto_struct, span<byte> buffer) const { auto output = pb_ostream_from_buffer( reinterpret_cast<pb_byte_t*>(buffer.data()), buffer.size()); - if (pb_encode(&output, response_fields_, proto_struct)) { + if (pb_encode(&output, static_cast<Fields>(response_fields_), proto_struct)) { return StatusWithSize(output.bytes_written); } return StatusWithSize::INTERNAL;
diff --git a/pw_rpc/nanopb/public_overrides/pw_rpc/internal/method.h b/pw_rpc/nanopb/public_overrides/pw_rpc/internal/method.h index 330d97b..8dd7764 100644 --- a/pw_rpc/nanopb/public_overrides/pw_rpc/internal/method.h +++ b/pw_rpc/nanopb/public_overrides/pw_rpc/internal/method.h
@@ -24,10 +24,6 @@ #include "pw_status/status.h" #include "pw_status/status_with_size.h" -// Forward declare Nanopb types to avoid exposing Nanopb headers. -extern "C" struct pb_field_s; -extern "C" struct pb_msgdesc_s; - namespace pw::rpc { // Define the Nanopb version of the the ServerWriter class. @@ -48,9 +44,8 @@ namespace internal { -// TODO(hepler): Nanopb 4 uses pb_msgdesc_s instead of pb_field_s. -// using NanopbMessageDescriptor = const pb_msgdesc_s*; -using NanopbMessageDescriptor = const pb_field_s*; +// Use a void* to cover both Nanopb 3's pb_field_s and Nanopb 4's pb_msgdesc_s. +using NanopbMessageDescriptor = const void*; // Extracts the request and response proto types from a method. template <typename Method>