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