Alexei Frolov | 4d2adde | 2020-08-04 10:19:24 -0700 | [diff] [blame] | 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 | |
Wyatt Hepler | 8ec2cf8 | 2021-07-09 17:18:41 -0700 | [diff] [blame] | 15 | #include "pw_rpc/nanopb/internal/common.h" |
Alexei Frolov | 4d2adde | 2020-08-04 10:19:24 -0700 | [diff] [blame] | 16 | |
| 17 | #include "pb_decode.h" |
| 18 | #include "pb_encode.h" |
Wyatt Hepler | 9e8ca38 | 2021-08-20 08:29:57 -0700 | [diff] [blame] | 19 | #include "pw_log/log.h" |
Alexei Frolov | 4d2adde | 2020-08-04 10:19:24 -0700 | [diff] [blame] | 20 | |
| 21 | namespace pw::rpc::internal { |
Wyatt Hepler | 9e8ca38 | 2021-08-20 08:29:57 -0700 | [diff] [blame] | 22 | namespace { |
Alexei Frolov | 4d2adde | 2020-08-04 10:19:24 -0700 | [diff] [blame] | 23 | |
| 24 | // Nanopb 3 uses pb_field_s and Nanopb 4 uses pb_msgdesc_s for fields. The |
| 25 | // Nanopb version macro is difficult to use, so deduce the correct type from the |
| 26 | // pb_decode function. |
| 27 | template <typename DecodeFunction> |
| 28 | struct NanopbTraits; |
| 29 | |
| 30 | template <typename FieldsType> |
| 31 | struct NanopbTraits<bool(pb_istream_t*, FieldsType, void*)> { |
| 32 | using Fields = FieldsType; |
| 33 | }; |
| 34 | |
| 35 | using Fields = typename NanopbTraits<decltype(pb_decode)>::Fields; |
| 36 | |
Wyatt Hepler | 9e8ca38 | 2021-08-20 08:29:57 -0700 | [diff] [blame] | 37 | } // namespace |
| 38 | |
| 39 | // PB_NO_ERRMSG is used in pb_decode.h and pb_encode.h to enable or disable the |
| 40 | // errmsg member of the istream and ostream structs. If errmsg is available, use |
| 41 | // it to give more detailed log messages. |
| 42 | #ifdef PB_NO_ERRMSG |
| 43 | |
| 44 | #define PW_RPC_LOG_NANOPB_FAILURE(msg, stream) PW_LOG_ERROR(msg) |
| 45 | |
| 46 | #else |
| 47 | |
| 48 | #define PW_RPC_LOG_NANOPB_FAILURE(msg, stream) \ |
| 49 | PW_LOG_ERROR(msg ": %s", stream.errmsg) |
| 50 | |
| 51 | #endif // PB_NO_ERRMSG |
| 52 | |
Alexei Frolov | 4d2adde | 2020-08-04 10:19:24 -0700 | [diff] [blame] | 53 | StatusWithSize NanopbMethodSerde::Encode(NanopbMessageDescriptor fields, |
Wyatt Hepler | 59b37f7 | 2021-06-15 16:23:44 -0700 | [diff] [blame] | 54 | const void* proto_struct, |
| 55 | ByteSpan buffer) const { |
Alexei Frolov | 4d2adde | 2020-08-04 10:19:24 -0700 | [diff] [blame] | 56 | auto output = pb_ostream_from_buffer( |
| 57 | reinterpret_cast<pb_byte_t*>(buffer.data()), buffer.size()); |
| 58 | if (!pb_encode(&output, static_cast<Fields>(fields), proto_struct)) { |
Wyatt Hepler | 9e8ca38 | 2021-08-20 08:29:57 -0700 | [diff] [blame] | 59 | PW_RPC_LOG_NANOPB_FAILURE("Nanopb protobuf encode failed", output); |
Alexei Frolov | 4d2adde | 2020-08-04 10:19:24 -0700 | [diff] [blame] | 60 | return StatusWithSize::Internal(); |
| 61 | } |
| 62 | |
Wyatt Hepler | 1b3da3a | 2021-01-07 13:26:57 -0800 | [diff] [blame] | 63 | return StatusWithSize(output.bytes_written); |
Alexei Frolov | 4d2adde | 2020-08-04 10:19:24 -0700 | [diff] [blame] | 64 | } |
| 65 | |
| 66 | bool NanopbMethodSerde::Decode(NanopbMessageDescriptor fields, |
Wyatt Hepler | 59b37f7 | 2021-06-15 16:23:44 -0700 | [diff] [blame] | 67 | ConstByteSpan buffer, |
| 68 | void* proto_struct) const { |
Alexei Frolov | 4d2adde | 2020-08-04 10:19:24 -0700 | [diff] [blame] | 69 | auto input = pb_istream_from_buffer( |
| 70 | reinterpret_cast<const pb_byte_t*>(buffer.data()), buffer.size()); |
Wyatt Hepler | 9e8ca38 | 2021-08-20 08:29:57 -0700 | [diff] [blame] | 71 | bool result = pb_decode(&input, static_cast<Fields>(fields), proto_struct); |
| 72 | if (!result) { |
| 73 | PW_RPC_LOG_NANOPB_FAILURE("Nanopb protobuf decode failed", input); |
| 74 | } |
| 75 | return result; |
Alexei Frolov | 4d2adde | 2020-08-04 10:19:24 -0700 | [diff] [blame] | 76 | } |
| 77 | |
Wyatt Hepler | 9e8ca38 | 2021-08-20 08:29:57 -0700 | [diff] [blame] | 78 | #undef PW_RPC_LOG_NANOPB_FAILURE |
| 79 | |
Alexei Frolov | 4d2adde | 2020-08-04 10:19:24 -0700 | [diff] [blame] | 80 | } // namespace pw::rpc::internal |