fuchsia_inspect/reader/
readable_tree.rs1use crate::Inspector;
9use crate::reader::ReaderError;
10use async_trait::async_trait;
11
12#[cfg(target_os = "fuchsia")]
13pub type SnapshotSource = zx::Vmo;
14
15#[cfg(not(target_os = "fuchsia"))]
16pub type SnapshotSource = Vec<u8>;
17
18#[async_trait]
20pub trait ReadableTree: Sized {
21 async fn tree_names(&self) -> Result<Vec<String>, ReaderError>;
23
24 async fn vmo(&self) -> Result<SnapshotSource, ReaderError>;
26
27 async fn read_tree(&self, name: &str) -> Result<Self, ReaderError>;
29}
30
31#[async_trait]
32impl ReadableTree for Inspector {
33 async fn vmo(&self) -> Result<SnapshotSource, ReaderError> {
34 self.duplicate_vmo().ok_or(ReaderError::DuplicateVmo)
35 }
36
37 async fn tree_names(&self) -> Result<Vec<String>, ReaderError> {
38 match self.state() {
39 None => Ok(vec![]),
41 Some(state) => {
42 let state = state.try_lock().map_err(ReaderError::FailedToLockState)?;
43 let names =
44 state.callbacks().keys().map(|k| k.to_string()).collect::<Vec<String>>();
45 Ok(names)
46 }
47 }
48 }
49
50 async fn read_tree(&self, name: &str) -> Result<Self, ReaderError> {
51 let cloned_callbacks = self.state().and_then(|state| match state.try_lock() {
52 Err(_) => None,
53 Ok(state) => state.callbacks().get(name).cloned(),
54 });
55 let result = cloned_callbacks.map(|value| value());
56 match result {
57 Some(cb_result) => cb_result.await.map_err(ReaderError::LazyCallback),
58 None => return Err(ReaderError::FailedToLoadTree(name.to_string())),
59 }
60 }
61}
62
63#[cfg(target_os = "fuchsia")]
64#[async_trait]
65impl ReadableTree for fidl_fuchsia_inspect::TreeProxy {
66 async fn vmo(&self) -> Result<zx::Vmo, ReaderError> {
67 let tree_content = self.get_content().await.map_err(|e| ReaderError::Fidl(e.into()))?;
68 tree_content.buffer.map(|b| b.vmo).ok_or(ReaderError::FetchVmo)
69 }
70
71 async fn tree_names(&self) -> Result<Vec<String>, ReaderError> {
72 let (name_iterator, server_end) =
73 fidl::endpoints::create_proxy::<fidl_fuchsia_inspect::TreeNameIteratorMarker>();
74 self.list_child_names(server_end).map_err(|e| ReaderError::Fidl(e.into()))?;
75 let mut names = vec![];
76 loop {
77 let subset_names =
78 name_iterator.get_next().await.map_err(|e| ReaderError::Fidl(e.into()))?;
79 if subset_names.is_empty() {
80 return Ok(names);
81 }
82 names.extend(subset_names);
83 }
84 }
85
86 async fn read_tree(&self, name: &str) -> Result<Self, ReaderError> {
87 let (child_tree, server_end) =
88 fidl::endpoints::create_proxy::<fidl_fuchsia_inspect::TreeMarker>();
89 self.open_child(name, server_end).map_err(|e| ReaderError::Fidl(e.into()))?;
90 Ok(child_tree)
91 }
92}