aboutsummaryrefslogtreecommitdiff
path: root/pw_rpc/pwpb/pw_rpc_pwpb_private/internal_test_utils.h
blob: 7208841f098f7379c32ce395b50359d2e5cbee6a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
// Copyright 2022 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.
#pragma once

#include <array>
#include <cstddef>

#include "pw_span/span.h"
#include "pw_status/status.h"
#include "pw_stream/memory_stream.h"

namespace pw::rpc::internal {

// Encodes a protobuf to a local span named by result from a list of pw_protobuf
// struct initializers.  Note that the proto namespace is passed, not the name
// of the struct --- ie. exclude the "::Message" suffix.
//
//  PW_ENCODE_PB(pw::rpc::TestProto, encoded, .value = 42);
//
#define PW_ENCODE_PB(proto, result, ...) \
  _PW_ENCODE_PB_EXPAND(proto, result, __LINE__, __VA_ARGS__)

#define _PW_ENCODE_PB_EXPAND(proto, result, unique, ...) \
  _PW_ENCODE_PB_IMPL(proto, result, unique, __VA_ARGS__)

#define _PW_ENCODE_PB_IMPL(proto, result, unique, ...)                     \
  std::array<std::byte, 2 * sizeof(proto::Message)> _pb_buffer_##unique{}; \
  const span result =                                                      \
      ::pw::rpc::internal::EncodeProtobuf<proto::Message,                  \
                                          proto::MemoryEncoder>(           \
          proto::Message{__VA_ARGS__}, _pb_buffer_##unique)

template <typename Message, typename MemoryEncoder>
span<const std::byte> EncodeProtobuf(const Message& message,
                                     span<std::byte> buffer) {
  MemoryEncoder encoder(buffer);
  EXPECT_EQ(encoder.Write(message), OkStatus());
  return buffer.first(encoder.size());
}

// Decodes a protobuf to a pw_protobuf struct named by result. Note that the
// proto namespace is passed, not the name of the struct --- ie. exclude the
// "::Message" suffix.
//
//  PW_DECODE_PB(pw::rpc::TestProto, decoded, buffer);
//
#define PW_DECODE_PB(proto, result, buffer)                                  \
  proto::Message result;                                                     \
  ::pw::rpc::internal::DecodeProtobuf<proto::Message, proto::StreamDecoder>( \
      buffer, result);

template <typename Message, typename StreamDecoder>
void DecodeProtobuf(span<const std::byte> buffer, Message& message) {
  stream::MemoryReader reader(buffer);
  EXPECT_EQ(StreamDecoder(reader).Read(message), OkStatus());
}

}  // namespace pw::rpc::internal