fuchsia_inspect/reader/
readable_tree.rs
1use crate::reader::ReaderError;
9use crate::Inspector;
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 result = self.state().and_then(|state| match state.try_lock() {
52 Err(_) => None,
53 Ok(state) => state.callbacks().get(name).map(|cb| cb()),
54 });
55 match result {
56 Some(cb_result) => cb_result.await.map_err(ReaderError::LazyCallback),
57 None => return Err(ReaderError::FailedToLoadTree(name.to_string())),
58 }
59 }
60}
61
62#[cfg(target_os = "fuchsia")]
63#[async_trait]
64impl ReadableTree for fidl_fuchsia_inspect::TreeProxy {
65 async fn vmo(&self) -> Result<zx::Vmo, ReaderError> {
66 let tree_content = self.get_content().await.map_err(|e| ReaderError::Fidl(e.into()))?;
67 tree_content.buffer.map(|b| b.vmo).ok_or(ReaderError::FetchVmo)
68 }
69
70 async fn tree_names(&self) -> Result<Vec<String>, ReaderError> {
71 let (name_iterator, server_end) =
72 fidl::endpoints::create_proxy::<fidl_fuchsia_inspect::TreeNameIteratorMarker>();
73 self.list_child_names(server_end).map_err(|e| ReaderError::Fidl(e.into()))?;
74 let mut names = vec![];
75 loop {
76 let subset_names =
77 name_iterator.get_next().await.map_err(|e| ReaderError::Fidl(e.into()))?;
78 if subset_names.is_empty() {
79 return Ok(names);
80 }
81 names.extend(subset_names);
82 }
83 }
84
85 async fn read_tree(&self, name: &str) -> Result<Self, ReaderError> {
86 let (child_tree, server_end) =
87 fidl::endpoints::create_proxy::<fidl_fuchsia_inspect::TreeMarker>();
88 self.open_child(name, server_end).map_err(|e| ReaderError::Fidl(e.into()))?;
89 Ok(child_tree)
90 }
91}