settings_inspect_utils/
managed_inspect_queue.rs
1use fuchsia_inspect::Node;
6use fuchsia_inspect_derive::{AttachError, Inspect, WithInspect};
7use std::collections::VecDeque;
8
9#[derive(Default)]
16pub struct ManagedInspectQueue<V> {
17 items: VecDeque<V>,
18 size_limit: usize,
21 inspect_node: Node,
22}
23
24impl<V> ManagedInspectQueue<V>
25where
26 for<'a> &'a mut V: Inspect,
27 V: std::fmt::Debug + std::default::Default,
28{
29 pub fn new(size_limit: usize) -> Self {
32 let mut default = ManagedInspectQueue::<V>::default();
33 default.set_size_limit(size_limit);
34 default
35 }
36
37 pub fn with_node(node: Node, size_limit: usize) -> Self {
40 Self { items: VecDeque::with_capacity(size_limit), size_limit, inspect_node: node }
41 }
42
43 fn set_size_limit(&mut self, new_size_limit: usize) {
47 while self.items.len() > new_size_limit {
48 let _ = self.items.pop_front();
49 }
50 self.size_limit = new_size_limit;
51 }
52
53 pub fn iter_mut(&mut self) -> std::collections::vec_deque::IterMut<'_, V> {
55 self.items.iter_mut()
56 }
57
58 pub fn items_mut(&mut self) -> &mut VecDeque<V> {
61 &mut self.items
62 }
63
64 pub fn retain<F>(&mut self, f: F)
66 where
67 F: FnMut(&V) -> bool,
68 {
69 self.items.retain(f);
70 }
71
72 pub fn inspect_node(&self) -> &Node {
74 &self.inspect_node
75 }
76
77 pub fn push(&mut self, key: &str, item: V) {
80 if self.items.len() == self.size_limit && self.size_limit != 0 {
82 let _ = self.items.pop_front();
83 }
84 let node = &self.inspect_node;
85 self.items
86 .push_back(item.with_inspect(node, key).expect("Failed to attach new queue entry."));
87 }
88
89 #[cfg(test)]
90 pub(crate) fn len(&self) -> usize {
91 self.items.len()
92 }
93}
94
95impl<V> Inspect for &mut ManagedInspectQueue<V>
96where
97 for<'a> &'a mut V: Inspect,
98{
99 fn iattach(self, parent: &Node, name: impl AsRef<str>) -> Result<(), AttachError> {
100 self.inspect_node = parent.create_child(name.as_ref());
101 Ok(())
102 }
103}
104
105#[cfg(test)]
106mod tests {
107 use crate::managed_inspect_queue::ManagedInspectQueue;
108 use diagnostics_assertions::assert_data_tree;
109 use fuchsia_inspect::{self as inspect, Node};
110 use fuchsia_inspect_derive::{IValue, Inspect, WithInspect};
111
112 #[derive(Default, Inspect)]
113 struct TestInspectWrapper {
114 inspect_node: Node,
115 queue: ManagedInspectQueue<TestInspectItem>,
116 }
117
118 #[derive(Debug, Default, Inspect)]
119 struct TestInspectItem {
120 inspect_node: Node,
121 id: IValue<u64>,
122 }
123
124 impl TestInspectItem {
125 fn new(id: u64) -> Self {
126 Self { inspect_node: Node::default(), id: id.into() }
127 }
128 }
129
130 #[fuchsia::test]
133 fn test_queue_under_capacity() {
134 let inspector = inspect::Inspector::default();
135 let mut wrapper = TestInspectWrapper::default()
136 .with_inspect(inspector.root(), "inspect_wrapper")
137 .expect("failed to create TestInspectWrapper inspect node");
138 wrapper.queue.set_size_limit(2);
139
140 let test_val_1 = TestInspectItem::new(6);
141 let test_val_2 = TestInspectItem::new(5);
142
143 wrapper.queue.push("0", test_val_1);
144 wrapper.queue.push("1", test_val_2);
145
146 assert_data_tree!(inspector, root: {
147 inspect_wrapper: {
148 queue: {
149 "0": {
150 "id": 6_u64,
151 },
152 "1": {
153 "id": 5_u64,
154 },
155 },
156 }
157 });
158 assert_eq!(wrapper.queue.len(), 2);
159 }
160
161 #[fuchsia::test]
164 fn test_queue_over_capacity() {
165 let inspector = inspect::Inspector::default();
166 let mut wrapper = TestInspectWrapper::default()
167 .with_inspect(inspector.root(), "inspect_wrapper")
168 .expect("failed to create TestInspectWrapper inspect node");
169 wrapper.queue.set_size_limit(2);
170
171 let test_val_1 = TestInspectItem::new(6);
172 let test_val_2 = TestInspectItem::new(5);
173 let test_val_3 = TestInspectItem::new(4);
174
175 wrapper.queue.push("0", test_val_1);
176 wrapper.queue.push("1", test_val_2);
177 wrapper.queue.push("2", test_val_3);
178
179 assert_data_tree!(inspector, root: {
180 inspect_wrapper: {
181 queue: {
182 "1": {
183 "id": 5_u64,
184 },
185 "2": {
186 "id": 4_u64,
187 },
188 },
189 }
190 });
191 assert_eq!(wrapper.queue.len(), 2);
192 }
193
194 #[fuchsia::test]
197 fn test_size_limit() {
198 let inspector = inspect::Inspector::default();
199 let mut wrapper = TestInspectWrapper::default()
200 .with_inspect(inspector.root(), "inspect_wrapper")
201 .expect("failed to create TestInspectWrapper inspect node");
202
203 let test_val_1 = TestInspectItem::new(6);
204 let test_val_2 = TestInspectItem::new(5);
205 let test_val_3 = TestInspectItem::new(4);
206
207 wrapper.queue.push("0", test_val_1);
208 wrapper.queue.push("1", test_val_2);
209 wrapper.queue.push("2", test_val_3);
210 wrapper.queue.set_size_limit(1);
211
212 assert_data_tree!(inspector, root: {
213 inspect_wrapper: {
214 queue: {
215 "2": {
216 "id": 4_u64,
217 },
218 },
219 }
220 });
221 assert_eq!(wrapper.queue.len(), 1);
222 }
223
224 #[fuchsia::test]
226 fn test_queue_remove() {
227 let inspector = inspect::Inspector::default();
228
229 let mut queue = ManagedInspectQueue::<IValue<String>>::with_node(
230 inspector.root().create_child("managed_node"),
231 10,
232 );
233
234 queue.push("0", "value1".to_string().into());
235 queue.push("1", "value2".to_string().into());
236 queue.retain(|item| **item != "value1");
237
238 assert_data_tree!(inspector, root: {
239 managed_node: {
240 "1": "value2"
241 }
242 });
243 }
244}