1 // Copyright 2023 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 
15 #pragma once
16 #include <cstddef>
17 #include <queue>
18 
19 #include "pw_bluetooth_sapphire/internal/host/common/assert.h"
20 #include "pw_bluetooth_sapphire/internal/host/common/inspect.h"
21 
22 namespace bt {
23 
24 // This class is intended to represent a list node in Inspect, which doesn't
25 // support lists natively. Furthermore, it makes sure that the number of list
26 // items doesn't exceed |capacity|.
27 //
28 // Each item in BoundedInspectListNode is represented as a child node with name
29 // as index. This index is always increasing and does not wrap around. For
30 // example, if capacity is 3, then the children names are `[0, 1, 2]` on the
31 // first three additions. When a new node is added, `0` is popped, and the
32 // children names are `[1, 2, 3]`.
33 //
34 // Example Usage:
35 //    BoundedInspectListNode list(/*capacity=*/2);
36 //    list.AttachInspect(parent_node);
37 //
38 //    auto& item_0 = list.CreateItem();
39 //    item_0.node.RecordInt("property_0", 0);
40 //
41 //    auto& item_1 = list.CreateItem();
42 //    item_1.node.RecordInt("property_A", 1);
43 //    item_1.node.RecordInt("property_B", 2);
44 //
45 // Inspect Tree:
46 //     example_list:
47 //         0:
48 //             property_0: 0
49 //         1:
50 //             property_A: 1
51 //             property_B: 2
52 class BoundedInspectListNode {
53  public:
54   struct Item {
55     // The list child node with the index as it's name (0, 1, 2...).
56     inspect::Node node;
57   };
58 
BoundedInspectListNode(size_t capacity)59   explicit BoundedInspectListNode(size_t capacity) : capacity_(capacity) {
60     PW_CHECK(capacity_ > 0u);
61   }
62   ~BoundedInspectListNode() = default;
63 
64   // Attach this node as a child of |parent| with the name |name|.
65   void AttachInspect(inspect::Node& parent, std::string name);
66 
67   // Add an item to the list, removing a previous item if the list is at
68   // capacity. The returned item reference is valid until the next item is added
69   // (or this list node is destroyed).
70   Item& CreateItem();
71 
72  private:
73   inspect::Node list_node_;
74   size_t next_index_ = 0;
75   const size_t capacity_;
76   std::queue<Item> items_;
77 };
78 
79 }  // namespace bt
80