1use thiserror::Error;
6use zx_status::Status;
7
8#[cfg(target_os = "fuchsia")]
9use {fidl_fuchsia_io as fio, fidl_fuchsia_mem as fmem};
10
11#[derive(Debug, Error)]
13#[allow(missing_docs)]
14pub enum OpenImageError {
15 #[error("while opening the file path {path:?}")]
16 OpenPath {
17 path: String,
18 #[source]
19 err: fuchsia_fs::node::OpenError,
20 },
21
22 #[error("while calling get_backing_memory for {path:?}")]
23 FidlGetBackingMemory {
24 path: String,
25 #[source]
26 err: fidl::Error,
27 },
28
29 #[error("while obtaining vmo of file for {path:?}: {status}")]
30 GetBackingMemory { path: String, status: Status },
31
32 #[error("while converting vmo to a resizable vmo for {path:?}: {status}")]
33 CloneBuffer { path: String, status: Status },
34}
35
36#[cfg(target_os = "fuchsia")]
37pub(crate) async fn open_from_path(
39 proxy: &fio::DirectoryProxy,
40 path: &str,
41) -> Result<fmem::Buffer, OpenImageError> {
42 let file = fuchsia_fs::directory::open_file(proxy, path, fio::PERM_READABLE)
43 .await
44 .map_err(|err| OpenImageError::OpenPath { path: path.to_string(), err })?;
45
46 let vmo = file
47 .get_backing_memory(fio::VmoFlags::READ)
48 .await
49 .map_err(|err| OpenImageError::FidlGetBackingMemory { path: path.to_string(), err })?
50 .map_err(Status::from_raw)
51 .map_err(|status| OpenImageError::GetBackingMemory { path: path.to_string(), status })?;
52
53 let size = vmo
54 .get_content_size()
55 .map_err(|status| OpenImageError::GetBackingMemory { path: path.to_string(), status })?;
56
57 let vmo = vmo
60 .create_child(
61 zx::VmoChildOptions::SNAPSHOT_AT_LEAST_ON_WRITE | zx::VmoChildOptions::RESIZABLE,
62 0,
63 size,
64 )
65 .map_err(|status| OpenImageError::CloneBuffer { path: path.to_string(), status })?;
66
67 Ok(fmem::Buffer { vmo, size })
68}