blob: 1f509a4bace667a5592ae191bc092ce8222b240a [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 <utility>
#include "pw_rpc/channel.h"
#include "pw_rpc/internal/config.h"
#include "pw_span/span.h"
// With dynamic allocation enabled, include the specified header and don't
// require the constructor to be constexpr.
#if PW_RPC_DYNAMIC_ALLOCATION
#include PW_RPC_DYNAMIC_CONTAINER_INCLUDE
#define _PW_RPC_CONSTEXPR
#else // Otherwise, channels are stored in a constexpr constructible span.
#define _PW_RPC_CONSTEXPR constexpr
#endif // PW_RPC_DYNAMIC_ALLOCATION
namespace pw::rpc::internal {
class ChannelList {
public:
_PW_RPC_CONSTEXPR ChannelList() = default;
_PW_RPC_CONSTEXPR ChannelList(span<Channel> channels)
// If dynamic allocation is enabled, channels aren't typically allocated
// beforehand, though they can be. If they are, push them one-by-one to the
// vector to avoid requiring a constructor that does that.
#if PW_RPC_DYNAMIC_ALLOCATION
{
for (const Channel& channel : channels) {
channels_.emplace_back(channel);
}
#else // Without dynamic allocation, simply initialize the span.
: channels_(channels) {
#endif // PW_RPC_DYNAMIC_ALLOCATION
}
// Returns the first channel with the matching ID or nullptr if none match.
// Except for Channel::kUnassignedChannelId, there should be no duplicate
// channels.
const Channel* Get(uint32_t channel_id) const;
Channel* Get(uint32_t channel_id) {
return const_cast<Channel*>(std::as_const(*this).Get(channel_id));
}
// Adds the channel with the requested ID to the list. Returns:
//
// OK - the channel was added
// ALREADY_EXISTS - a channel with this ID is already present; remove it
// first
// RESOURCE_EXHAUSTED - no unassigned channels are available; only possible
// if PW_RPC_DYNAMIC_ALLOCATION is disabled
//
Status Add(uint32_t channel_id, ChannelOutput& output);
// Removes the channel with the requested ID. Returns:
//
// OK - the channel was removed
// NOT_FOUND - no channel with the provided ID was found
//
Status Remove(uint32_t channel_id);
#if PW_RPC_DYNAMIC_ALLOCATION
PW_RPC_DYNAMIC_CONTAINER(Channel) channels_;
#else
span<Channel> channels_;
#endif // PW_RPC_DYNAMIC_ALLOCATION
};
} // namespace pw::rpc::internal