blob: f8811874459ab8ce3f8aad5c707e2ccb95908fdc [file] [log] [blame]
// Copyright 2020 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 <cstddef>
#include <cstdint>
#include <span>
#include "pw_rpc_protos/packet.pwpb.h"
#include "pw_status/status_with_size.h"
namespace pw::rpc::internal {
class Packet {
public:
static constexpr uint32_t kUnassignedId = 0;
// Parses a packet from a protobuf message. Missing or malformed fields take
// their default values.
static Status FromBuffer(std::span<const std::byte> data, Packet& packet);
// Creates an RPC packet with the channel, service, and method ID of the
// provided packet.
static constexpr Packet Response(const Packet& request,
Status status = Status::Ok()) {
return Packet(PacketType::RESPONSE,
request.channel_id(),
request.service_id(),
request.method_id(),
{},
status);
}
// Creates an ERROR packet with the channel, service, and method ID of the
// provided packet.
static constexpr Packet ServerError(const Packet& packet, Status status) {
return Packet(PacketType::SERVER_ERROR,
packet.channel_id(),
packet.service_id(),
packet.method_id(),
{},
status);
}
// Creates an empty packet.
constexpr Packet()
: Packet(PacketType{}, kUnassignedId, kUnassignedId, kUnassignedId) {}
constexpr Packet(PacketType type,
uint32_t channel_id,
uint32_t service_id,
uint32_t method_id,
std::span<const std::byte> payload = {},
Status status = Status::Ok())
: type_(type),
channel_id_(channel_id),
service_id_(service_id),
method_id_(method_id),
payload_(payload),
status_(status) {}
// Encodes the packet into its wire format. Returns the encoded size.
StatusWithSize Encode(std::span<std::byte> buffer) const;
// Determines the space required to encode the packet proto fields for a
// response, excluding the payload. This may be used to split the buffer into
// reserved space and available space for the payload.
size_t MinEncodedSizeBytes() const;
enum Destination : bool { kServer, kClient };
constexpr Destination destination() const {
return static_cast<int>(type_) % 2 == 0 ? kServer : kClient;
}
constexpr PacketType type() const { return type_; }
constexpr uint32_t channel_id() const { return channel_id_; }
constexpr uint32_t service_id() const { return service_id_; }
constexpr uint32_t method_id() const { return method_id_; }
constexpr const std::span<const std::byte>& payload() const {
return payload_;
}
constexpr Status status() const { return status_; }
constexpr void set_type(PacketType type) { type_ = type; }
constexpr void set_channel_id(uint32_t channel_id) {
channel_id_ = channel_id;
}
constexpr void set_service_id(uint32_t service_id) {
service_id_ = service_id;
}
constexpr void set_method_id(uint32_t method_id) { method_id_ = method_id; }
constexpr void set_payload(std::span<const std::byte> payload) {
payload_ = payload;
}
constexpr void set_status(Status status) { status_ = status; }
private:
PacketType type_;
uint32_t channel_id_;
uint32_t service_id_;
uint32_t method_id_;
std::span<const std::byte> payload_;
Status status_;
};
} // namespace pw::rpc::internal