fuchsia_inspect_contrib/log/wrappers.rs
1// Copyright 2019 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5use super::WriteInspect;
6use fuchsia_inspect::{ArrayProperty, Node};
7use std::borrow::Cow;
8use std::marker::PhantomData;
9
10/// Wrapper to log bytes in an `inspect_log!` or `inspect_insert!` macro.
11///
12/// This wrapper is defined because a default `WriteInspect` implementation isn't provided for
13/// an array or slice of bytes. Such default implementation was left out so that the user has
14/// to explicitly choose whether to log bytes slice as a string or a byte vector in Inspect.
15pub struct InspectBytes<T: AsRef<[u8]>>(pub T);
16
17impl<T: AsRef<[u8]>> WriteInspect for InspectBytes<T> {
18 fn write_inspect<'a>(&self, writer: &Node, key: impl Into<Cow<'a, str>>) {
19 writer.record_bytes(key, self.0.as_ref());
20 }
21}
22
23/// Wrapper to log a list of items in `inspect_log!` or `inspect_insert!` macro. Each item
24/// in the list must be a type that implements `WriteInspect`
25///
26/// Example:
27/// ```
28/// let list = ["foo", "bar", "baz"];
29/// inspect_insert!(node_writer, some_list: InspectList(&list));
30/// ```
31///
32/// The above code snippet would create the following child under node_writer:
33/// ```
34/// some_list:
35/// 0: "foo"
36/// 1: "bar"
37/// 2: "baz"
38/// ```
39pub struct InspectList<'a, T>(pub &'a [T]);
40
41impl<T> WriteInspect for InspectList<'_, T>
42where
43 T: WriteInspect,
44{
45 fn write_inspect<'a>(&self, writer: &Node, key: impl Into<Cow<'a, str>>) {
46 let child = writer.create_child(key);
47 for (i, val) in self.0.iter().enumerate() {
48 val.write_inspect(&child, i.to_string());
49 }
50
51 writer.record(child);
52 }
53}
54
55/// Wrapper around a list `[T]` and a closure function `F` that determines how to map
56/// and log each value of `T` in `inspect_log!` or `inspect_insert!` macro.
57///
58/// Example:
59/// ```
60/// let list = ["foo", "bar", "baz"]
61/// let list_mapped = InspectListClosure(&list, |node_writer, key, item| {
62/// let mapped_item = format!("super{}", item);
63/// inspect_insert!(node_writer, var key: mapped_item);
64/// });
65/// inspect_insert!(node_writer, some_list: list_mapped);
66/// ```
67///
68/// The above code snippet would create the following child under node_writer:
69/// ```
70/// some_list:
71/// 0: "superfoo"
72/// 1: "superbar"
73/// 2: "superbaz"
74/// ```
75pub struct InspectListClosure<'a, T, F>(pub &'a [T], pub F)
76where
77 F: Fn(&Node, &str, &T);
78
79impl<T, F> WriteInspect for InspectListClosure<'_, T, F>
80where
81 F: Fn(&Node, &str, &T),
82{
83 fn write_inspect<'a>(&self, writer: &Node, key: impl Into<Cow<'a, str>>) {
84 let child = writer.create_child(key);
85 for (i, val) in self.0.iter().enumerate() {
86 self.1(&child, &i.to_string(), val);
87 }
88
89 writer.record(child);
90 }
91}
92
93/// Wrapper to log uint array in an `inspect_log!` or `inspect_insert!` macro.
94pub struct InspectUintArray<T: AsRef<[I]>, I: Into<u64> + Clone> {
95 pub items: T,
96 _phantom: PhantomData<I>,
97}
98
99impl<T: AsRef<[I]>, I: Into<u64> + Clone> InspectUintArray<T, I> {
100 pub fn new(items: T) -> Self {
101 Self { items, _phantom: PhantomData }
102 }
103}
104
105impl<T: AsRef<[I]>, I: Into<u64> + Clone> WriteInspect for InspectUintArray<T, I> {
106 fn write_inspect<'a>(&self, node: &Node, key: impl Into<Cow<'a, str>>) {
107 let iter = self.items.as_ref().iter();
108 let inspect_array = node.create_uint_array(key, iter.len());
109 for (i, c) in iter.enumerate() {
110 inspect_array.set(i, (*c).clone());
111 }
112 node.record(inspect_array);
113 }
114}