1 // Copyright 2020 The Pigweed Authors 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); you may not 4 // use this file except in compliance with the License. You may obtain a copy of 5 // the License at 6 // 7 // https://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 // License for the specific language governing permissions and limitations under 13 // the License. 14 #pragma once 15 16 #include "pb_common.h" 17 #include "pw_bytes/span.h" 18 #include "pw_rpc/internal/lock.h" 19 #include "pw_status/status_with_size.h" 20 21 namespace pw::rpc::internal { 22 23 // Nanopb 0.3 uses pb_field_t, but Nanopb 4 uses pb_msgdesc_t. Determine which 24 // type to use by deducing it from the pb_field_iter_begin function. 25 template <typename PbFieldIterBeginFunction> 26 struct NanopbDescriptorTraits; 27 28 template <typename T> 29 struct NanopbDescriptorTraits<bool(pb_field_iter_t*, T, void*)> { 30 using Type = T; 31 }; 32 33 using NanopbMessageDescriptor = 34 NanopbDescriptorTraits<decltype(pb_field_iter_begin)>::Type; 35 36 // Serializer/deserializer for a Nanopb protobuf message. 37 class NanopbSerde { 38 public: 39 explicit constexpr NanopbSerde(NanopbMessageDescriptor fields) 40 : fields_(fields) {} 41 42 NanopbSerde(const NanopbSerde&) = default; 43 NanopbSerde& operator=(const NanopbSerde&) = default; 44 45 // Encodes a Nanopb protobuf struct to the serialized wire format. 46 StatusWithSize Encode(const void* proto_struct, ByteSpan buffer) const; 47 48 // Calculates the encoded size of the provided protobuf struct without 49 // actually encoding it. 50 StatusWithSize EncodedSizeBytes(const void* proto_struct) const; 51 52 // Decodes a serialized protobuf to a Nanopb struct. 53 template <typename T> 54 Status Decode(ConstByteSpan buffer, T& proto_struct) const { 55 return Decode(buffer, static_cast<void*>(&proto_struct)); 56 } 57 58 Status Decode(ConstByteSpan buffer, void* proto_struct) const; 59 60 private: 61 NanopbMessageDescriptor fields_; 62 }; 63 64 // Serializer/deserializer for Nanopb message request and response structs in an 65 // RPC method. 66 class NanopbMethodSerde { 67 public: 68 constexpr NanopbMethodSerde(NanopbMessageDescriptor request_fields, 69 NanopbMessageDescriptor response_fields) 70 : request_fields_(request_fields), response_fields_(response_fields) {} 71 72 NanopbMethodSerde(const NanopbMethodSerde&) = delete; 73 NanopbMethodSerde& operator=(const NanopbMethodSerde&) = delete; 74 75 const NanopbSerde& request() const { return request_fields_; } 76 const NanopbSerde& response() const { return response_fields_; } 77 78 private: 79 NanopbSerde request_fields_; 80 NanopbSerde response_fields_; 81 }; 82 83 template <NanopbMessageDescriptor kRequest, NanopbMessageDescriptor kResponse> 84 inline constexpr NanopbMethodSerde kNanopbMethodSerde(kRequest, kResponse); 85 86 class Call; 87 class ClientCall; 88 class NanopbServerCall; 89 90 // [Client] Encodes and sends the initial request message for the call. 91 // active() must be true. 92 void NanopbSendInitialRequest(ClientCall& call, 93 NanopbSerde serde, 94 const void* payload) 95 PW_EXCLUSIVE_LOCKS_REQUIRED(rpc_lock()); 96 97 // [Client/Server] Encodes and sends a client or server stream message. 98 // active() must be true. 99 Status NanopbSendStream(Call& call, 100 const void* payload, 101 const NanopbMethodSerde* serde) 102 PW_EXCLUSIVE_LOCKS_REQUIRED(rpc_lock()); 103 104 // [Server] Encodes and sends the final response message. 105 // Returns Status::FailedPrecondition if active() is false. 106 Status SendFinalResponse(NanopbServerCall& call, 107 const void* payload, 108 Status status) PW_LOCKS_EXCLUDED(rpc_lock()); 109 110 } // namespace pw::rpc::internal 111