blob: 7208841f098f7379c32ce395b50359d2e5cbee6a [file] [log] [blame]
// 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