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}