1use flex_client::fidl::ProtocolMarker;
9use flex_client::ProxyHasDomain;
10use moniker::Moniker;
11use thiserror::Error;
12use {flex_fuchsia_io as fio, flex_fuchsia_sys2 as fsys};
13
14#[derive(Debug, Error)]
16pub enum OpenError {
17 #[error("instance {0} could not be found")]
18 InstanceNotFound(Moniker),
19 #[error("opening {0} requires {1} to be resolved")]
20 InstanceNotResolved(OpenDirType, Moniker),
21 #[error("opening {0} requires {1} to be running")]
22 InstanceNotRunning(OpenDirType, Moniker),
23 #[error("component manager's open request on the directory returned a FIDL error")]
24 OpenDirectoryFidlError,
25 #[error("{0} does not have a {1}")]
26 NoSuchDir(Moniker, OpenDirType),
27 #[error("component manager could not parse moniker: {0}")]
28 BadMoniker(Moniker),
29 #[error("component manager could not parse dir type: {0}")]
30 BadDirType(OpenDirType),
31 #[error("component manager could not parse path: {0}")]
32 BadPath(String),
33 #[error("component manager responded with an unknown error code")]
34 UnknownError,
35 #[error(transparent)]
36 Fidl(#[from] fidl::Error),
37}
38
39#[derive(Clone, Debug)]
41pub enum OpenDirType {
42 Outgoing,
44 Runtime,
46 Package,
48 Exposed,
50 Namespace,
52}
53
54impl std::fmt::Display for OpenDirType {
55 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
56 match self {
57 Self::Outgoing => write!(f, "outgoing directory"),
58 Self::Runtime => write!(f, "runtime directory"),
59 Self::Package => write!(f, "package directory"),
60 Self::Exposed => write!(f, "exposed directory"),
61 Self::Namespace => write!(f, "namespace directory"),
62 }
63 }
64}
65
66impl Into<fsys::OpenDirType> for OpenDirType {
67 fn into(self) -> fsys::OpenDirType {
68 match self {
69 Self::Outgoing => fsys::OpenDirType::OutgoingDir,
70 Self::Runtime => fsys::OpenDirType::RuntimeDir,
71 Self::Package => fsys::OpenDirType::PackageDir,
72 Self::Exposed => fsys::OpenDirType::ExposedDir,
73 Self::Namespace => fsys::OpenDirType::NamespaceDir,
74 }
75 }
76}
77
78impl From<fsys::OpenDirType> for OpenDirType {
79 fn from(fidl_type: fsys::OpenDirType) -> Self {
80 match fidl_type {
81 fsys::OpenDirType::OutgoingDir => Self::Outgoing,
82 fsys::OpenDirType::RuntimeDir => Self::Runtime,
83 fsys::OpenDirType::PackageDir => Self::Package,
84 fsys::OpenDirType::ExposedDir => Self::Exposed,
85 fsys::OpenDirType::NamespaceDir => Self::Namespace,
86 fsys::OpenDirTypeUnknown!() => panic!("This should not be constructed"),
87 }
88 }
89}
90
91pub async fn connect_to_instance_protocol<P: ProtocolMarker>(
93 moniker: &Moniker,
94 dir_type: OpenDirType,
95 realm: &fsys::RealmQueryProxy,
96) -> Result<P::Proxy, OpenError> {
97 connect_to_instance_protocol_at_path::<P>(moniker, dir_type, P::DEBUG_NAME, realm).await
98}
99
100pub async fn connect_to_instance_protocol_at_path<P: ProtocolMarker>(
102 moniker: &Moniker,
103 dir_type: OpenDirType,
104 path: &str,
105 realm: &fsys::RealmQueryProxy,
106) -> Result<P::Proxy, OpenError> {
107 let dir_client = open_instance_directory(moniker, dir_type, realm).await?;
108 let (proxy, server_end) = realm.domain().create_proxy::<P>();
109 dir_client
110 .open(path, fio::Flags::PROTOCOL_SERVICE, &Default::default(), server_end.into_channel())
111 .map_err(|_| OpenError::OpenDirectoryFidlError)?;
112 Ok(proxy)
113}
114
115pub async fn open_instance_directory(
117 moniker: &Moniker,
118 dir_type: OpenDirType,
119 realm: &fsys::RealmQueryProxy,
120) -> Result<fio::DirectoryProxy, OpenError> {
121 let moniker_str = moniker.to_string();
122 let (dir_client, dir_server) = realm.domain().create_proxy::<fio::DirectoryMarker>();
123 realm
124 .open_directory(&moniker_str, dir_type.clone().into(), dir_server)
125 .await
126 .map_err(|e| OpenError::Fidl(e))?
127 .map_err(|e| match e {
128 fsys::OpenError::InstanceNotFound => OpenError::InstanceNotFound(moniker.clone()),
129 fsys::OpenError::InstanceNotResolved => {
130 OpenError::InstanceNotResolved(dir_type, moniker.clone())
131 }
132 fsys::OpenError::InstanceNotRunning => {
133 OpenError::InstanceNotRunning(dir_type, moniker.clone())
134 }
135 fsys::OpenError::NoSuchDir => OpenError::NoSuchDir(moniker.clone(), dir_type),
136 fsys::OpenError::BadDirType => OpenError::BadDirType(dir_type),
137 fsys::OpenError::BadMoniker => OpenError::BadMoniker(moniker.clone()),
138 fsys::OpenError::FidlError => OpenError::OpenDirectoryFidlError,
139 _ => OpenError::UnknownError,
140 })?;
141 Ok(dir_client)
142}