diagnostics_traits/
fuchsia.rs1use alloc::format;
6use alloc::string::String;
7use core::fmt::Display;
8use core::marker::PhantomData;
9
10use fuchsia_async as fasync;
11use fuchsia_inspect::Node;
12use log::warn;
13
14use crate::{
15 InspectableInstant, Inspector, InspectorDeviceExt, InspectorRouteTableExt, InstantPropertyName,
16};
17
18pub trait InspectorDeviceIdProvider<DeviceId> {
20 fn device_id(id: &DeviceId) -> u64;
22}
23
24pub trait InspectorRouteTableIdProvider<R> {
26 fn route_table_id(id: &R) -> u32;
28}
29
30pub struct FuchsiaInspector<'a, D> {
32 node: &'a Node,
33 unnamed_count: usize,
34 _marker: PhantomData<D>,
35}
36
37impl<'a, D> FuchsiaInspector<'a, D> {
38 pub fn new(node: &'a Node) -> Self {
40 Self { node, unnamed_count: 0, _marker: Default::default() }
41 }
42}
43
44impl<'a, D> Inspector for FuchsiaInspector<'a, D> {
45 type ChildInspector<'l> = FuchsiaInspector<'l, D>;
46
47 fn record_child<F: FnOnce(&mut Self::ChildInspector<'_>)>(&mut self, name: &str, f: F) {
48 self.node.record_child(name, |node| f(&mut FuchsiaInspector::new(node)))
49 }
50
51 fn record_unnamed_child<F: FnOnce(&mut Self::ChildInspector<'_>)>(&mut self, f: F) {
52 let Self { node: _, unnamed_count, _marker: _ } = self;
53 let id = core::mem::replace(unnamed_count, *unnamed_count + 1);
54 self.record_child(&format!("{id}"), f)
55 }
56
57 fn record_usize<T: Into<usize>>(&mut self, name: &str, value: T) {
58 let value: u64 = value.into().try_into().unwrap_or_else(|e| {
59 warn!("failed to inspect usize value that does not fit in a u64: {e:?}");
60 u64::MAX
61 });
62 self.node.record_uint(name, value)
63 }
64
65 fn record_uint<T: Into<u64>>(&mut self, name: &str, value: T) {
66 self.node.record_uint(name, value.into())
67 }
68
69 fn record_int<T: Into<i64>>(&mut self, name: &str, value: T) {
70 self.node.record_int(name, value.into())
71 }
72
73 fn record_double<T: Into<f64>>(&mut self, name: &str, value: T) {
74 self.node.record_double(name, value.into())
75 }
76
77 fn record_str(&mut self, name: &str, value: &str) {
78 self.node.record_string(name, value)
79 }
80
81 fn record_string(&mut self, name: &str, value: String) {
82 self.node.record_string(name, value)
83 }
84
85 fn record_bool(&mut self, name: &str, value: bool) {
86 self.node.record_bool(name, value)
87 }
88}
89
90impl<'a, D, P: InspectorDeviceIdProvider<D>> InspectorDeviceExt<D> for FuchsiaInspector<'a, P> {
91 fn record_device<I: Inspector>(inspector: &mut I, name: &str, device: &D) {
92 inspector.record_uint(name, P::device_id(device))
93 }
94
95 fn device_identifier_as_address_zone(id: D) -> impl Display {
96 P::device_id(&id)
97 }
98}
99
100impl<'a, R, P: InspectorRouteTableIdProvider<R>> InspectorRouteTableExt<R>
101 for FuchsiaInspector<'a, P>
102{
103 fn record_route_table<I: Inspector>(inspector: &mut I, name: &str, table: &R) {
104 inspector.record_uint(name, P::route_table_id(table))
105 }
106
107 fn display_route_table(table: &R) -> impl Display {
108 P::route_table_id(table)
109 }
110}
111
112impl InspectableInstant for fasync::MonotonicInstant {
113 fn record<I: Inspector>(&self, name: InstantPropertyName, inspector: &mut I) {
114 inspector.record_int(name.into(), self.into_nanos());
115 }
116}