xref: /aosp_15_r20/external/pigweed/pw_rpc/public/pw_rpc/internal/channel_list.h (revision 61c4878ac05f98d0ceed94b57d316916de578985)
1 // Copyright 2022 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 #pragma once
15 
16 #include <utility>
17 
18 #include "pw_polyfill/language_feature_macros.h"
19 #include "pw_rpc/channel.h"
20 #include "pw_rpc/internal/config.h"
21 #include "pw_span/span.h"
22 
23 // With dynamic allocation enabled, include the specified header and don't
24 // require the constructor to be constexpr.
25 #if PW_RPC_DYNAMIC_ALLOCATION
26 
27 #include PW_RPC_DYNAMIC_CONTAINER_INCLUDE
28 
29 #define _PW_RPC_CONSTEXPR
30 #define _PW_RPC_CONSTINIT
31 
32 #else  // Otherwise, channels are stored in a constexpr constructible span.
33 
34 #define _PW_RPC_CONSTEXPR constexpr
35 #define _PW_RPC_CONSTINIT PW_CONSTINIT
36 
37 #endif  // PW_RPC_DYNAMIC_ALLOCATION
38 
39 namespace pw::rpc::internal {
40 
41 class ChannelList {
42  public:
43   _PW_RPC_CONSTEXPR ChannelList() = default;
44 
ChannelList(span<Channel> channels)45   _PW_RPC_CONSTEXPR ChannelList(span<Channel> channels)
46   // If dynamic allocation is enabled, channels aren't typically allocated
47   // beforehand, though they can be. If they are, push them one-by-one to the
48   // vector to avoid requiring a constructor that does that.
49 #if PW_RPC_DYNAMIC_ALLOCATION
50   {
51     for (const Channel& channel : channels) {
52       channels_.emplace_back(channel);
53     }
54 #else   // Without dynamic allocation, simply initialize the span.
55       : channels_(channels) {
56 #endif  // PW_RPC_DYNAMIC_ALLOCATION
57   }
58 
59   // Returns the first channel with the matching ID or nullptr if none match.
60   // Except for Channel::kUnassignedChannelId, there should be no duplicate
61   // channels.
62   const Channel* Get(uint32_t channel_id) const;
63 
64   Channel* Get(uint32_t channel_id) {
65     return const_cast<Channel*>(std::as_const(*this).Get(channel_id));
66   }
67 
68   // Adds the channel with the requested ID to the list. Returns:
69   //
70   //   OK - the channel was added
71   //   ALREADY_EXISTS - a channel with this ID is already present; remove it
72   //       first
73   //   RESOURCE_EXHAUSTED - no unassigned channels are available; only possible
74   //       if PW_RPC_DYNAMIC_ALLOCATION is disabled
75   //
76   Status Add(uint32_t channel_id, ChannelOutput& output);
77 
78   // Removes the channel with the requested ID. Returns:
79   //
80   //   OK - the channel was removed
81   //   NOT_FOUND - no channel with the provided ID was found
82   //
83   Status Remove(uint32_t channel_id);
84 
85 #if PW_RPC_DYNAMIC_ALLOCATION
86   PW_RPC_DYNAMIC_CONTAINER(Channel) channels_;
87 #else
88   span<Channel> channels_;
89 #endif  // PW_RPC_DYNAMIC_ALLOCATION
90 };
91 
92 }  // namespace pw::rpc::internal
93