1use crate::responder::Responder;
6use crate::{Client, Error, ordinals};
7use fidl_fuchsia_fdomain as proto;
8use futures::FutureExt;
9use std::future::Future;
10use std::pin::Pin;
11use std::sync::{Arc, Weak};
12use std::task::{Context, Poll};
13
14#[derive(Debug)]
16pub struct Handle {
17 pub(crate) id: u32,
18 pub(crate) client: Weak<Client>,
19}
20
21impl Handle {
22 pub(crate) fn client(&self) -> Arc<Client> {
24 self.client.upgrade().unwrap_or_else(|| Arc::clone(&*crate::DEAD_CLIENT))
25 }
26
27 pub fn invalid() -> Self {
29 Handle { id: 0, client: Weak::new() }
30 }
31}
32
33impl std::cmp::PartialEq for Handle {
34 fn eq(&self, other: &Self) -> bool {
35 self.id == other.id && Weak::ptr_eq(&self.client, &other.client)
36 }
37}
38
39impl std::cmp::Eq for Handle {}
40
41impl std::cmp::PartialOrd for Handle {
42 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
43 Some(self.cmp(other))
44 }
45}
46
47impl std::cmp::Ord for Handle {
48 fn cmp(&self, other: &Self) -> std::cmp::Ordering {
49 self.id.cmp(&other.id)
50 }
51}
52
53impl std::hash::Hash for Handle {
54 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
55 self.id.hash(state);
56 }
57}
58
59#[derive(Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
62pub struct HandleRef<'a>(&'a Handle);
63
64impl std::ops::Deref for HandleRef<'_> {
65 type Target = Handle;
66
67 fn deref(&self) -> &Self::Target {
68 self.0
69 }
70}
71
72impl HandleRef<'_> {
73 pub fn duplicate(
76 &self,
77 rights: fidl::Rights,
78 ) -> impl Future<Output = Result<Handle, Error>> + 'static + use<> {
79 let client = self.0.client();
80 let handle = self.0.proto();
81 let new_handle = client.new_hid();
82 let id = new_handle.id;
83 client
84 .transaction(
85 ordinals::DUPLICATE,
86 proto::FDomainDuplicateRequest { handle, new_handle, rights },
87 Responder::Duplicate,
88 )
89 .map(move |res| res.map(|_| Handle { id, client: Arc::downgrade(&client) }))
90 }
91
92 pub fn signal(
94 &self,
95 set: fidl::Signals,
96 clear: fidl::Signals,
97 ) -> impl Future<Output = Result<(), Error>> + use<> {
98 let handle = self.proto();
99 let client = self.client();
100
101 client.transaction(
102 ordinals::SIGNAL,
103 proto::FDomainSignalRequest { handle, set: set.bits(), clear: clear.bits() },
104 Responder::Signal,
105 )
106 }
107}
108
109pub trait AsHandleRef {
112 fn as_handle_ref(&self) -> HandleRef<'_>;
113 fn object_type() -> fidl::ObjectType;
114
115 fn u32_id(&self) -> u32 {
116 self.as_handle_ref().0.id
117 }
118
119 fn signal_handle(
120 &self,
121 set: fidl::Signals,
122 clear: fidl::Signals,
123 ) -> impl Future<Output = Result<(), Error>> {
124 self.as_handle_ref().signal(set, clear)
125 }
126
127 fn domain(&self) -> Arc<Client> {
129 self.as_handle_ref().0.client()
130 }
131}
132
133impl AsHandleRef for Handle {
134 fn as_handle_ref(&self) -> HandleRef<'_> {
136 HandleRef(self)
137 }
138
139 fn object_type() -> fidl::ObjectType {
141 fidl::ObjectType::NONE
142 }
143}
144
145pub trait Peered: HandleBased {
147 fn signal_peer(
149 &self,
150 set: fidl::Signals,
151 clear: fidl::Signals,
152 ) -> impl Future<Output = Result<(), Error>> {
153 let handle = self.as_handle_ref().proto();
154 let client = self.as_handle_ref().client();
155
156 client.transaction(
157 ordinals::SIGNAL_PEER,
158 proto::FDomainSignalPeerRequest { handle, set: set.bits(), clear: clear.bits() },
159 Responder::SignalPeer,
160 )
161 }
162}
163
164pub trait HandleBased: AsHandleRef + From<Handle> + Into<Handle> {
165 fn close(self) -> impl Future<Output = Result<(), Error>> {
167 let h = <Self as Into<Handle>>::into(self);
168 Handle::close(h)
169 }
170
171 fn duplicate_handle(&self, rights: fidl::Rights) -> impl Future<Output = Result<Self, Error>> {
173 let fut = self.as_handle_ref().duplicate(rights);
174 async move { fut.await.map(|handle| Self::from(handle)) }
175 }
176
177 fn replace_handle(self, rights: fidl::Rights) -> impl Future<Output = Result<Self, Error>> {
179 let h = <Self as Into<Handle>>::into(self);
180 async move { h.replace(rights).await.map(|handle| Self::from(handle)) }
181 }
182
183 fn into_handle(self) -> Handle {
185 self.into()
186 }
187
188 fn from_handle(handle: Handle) -> Self {
190 Self::from(handle)
191 }
192
193 fn into_handle_based<H: HandleBased>(self) -> H {
195 H::from_handle(self.into_handle())
196 }
197
198 fn from_handle_based<H: HandleBased>(h: H) -> Self {
200 Self::from_handle(h.into_handle())
201 }
202}
203
204impl HandleBased for Handle {}
205
206pub struct OnFDomainSignals {
209 fut: futures::future::BoxFuture<'static, Result<fidl::Signals, Error>>,
210}
211
212impl OnFDomainSignals {
213 pub fn new(handle: &Handle, signals: fidl::Signals) -> Self {
217 let client = handle.client();
218 let handle = handle.proto();
219 let fut = client
220 .transaction(
221 ordinals::WAIT_FOR_SIGNALS,
222 proto::FDomainWaitForSignalsRequest { handle, signals: signals.bits() },
223 Responder::WaitForSignals,
224 )
225 .map(|f| f.map(|x| fidl::Signals::from_bits_retain(x.signals)));
226 OnFDomainSignals { fut: fut.boxed() }
227 }
228}
229
230impl Future for OnFDomainSignals {
231 type Output = Result<fidl::Signals, Error>;
232
233 fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
234 self.fut.as_mut().poll(cx)
235 }
236}
237
238impl Handle {
239 pub(crate) fn proto(&self) -> proto::HandleId {
241 proto::HandleId { id: self.id }
242 }
243
244 pub(crate) fn take_proto(mut self) -> proto::HandleId {
247 let ret = self.proto();
248 self.client = Weak::new();
250 ret
251 }
252
253 pub fn close(self) -> impl Future<Output = Result<(), Error>> {
255 let client = self.client();
256 client.transaction(
257 ordinals::CLOSE,
258 proto::FDomainCloseRequest { handles: vec![self.take_proto()] },
259 Responder::Close,
260 )
261 }
262
263 pub fn replace(self, rights: fidl::Rights) -> impl Future<Output = Result<Handle, Error>> {
266 let client = self.client();
267 let handle = self.take_proto();
268 {
269 let mut client = client.0.lock().unwrap();
270 let _ = client.channel_read_states.remove(&handle);
271 let _ = client.socket_read_states.remove(&handle);
272 }
273 let new_handle = client.new_hid();
274
275 let id = new_handle.id;
276 let ret = Handle { id, client: Arc::downgrade(&client) };
277 let fut = client.transaction(
278 ordinals::REPLACE,
279 proto::FDomainReplaceRequest { handle, new_handle, rights },
280 Responder::Replace,
281 );
282
283 async move {
284 fut.await?;
285 Ok(ret)
286 }
287 }
288}
289
290impl Drop for Handle {
291 fn drop(&mut self) {
292 if let Some(client) = self.client.upgrade() {
293 let mut client = client.0.lock().unwrap();
294 if client.waiting_to_close.is_empty() {
295 client.waiting_to_close_waker.wake_by_ref();
296 }
297 client.waiting_to_close.push(self.proto());
298 }
299 }
300}
301
302macro_rules! handle_type {
303 ($name:ident $objtype:ident) => {
304 impl From<$name> for Handle {
305 fn from(other: $name) -> Handle {
306 other.0
307 }
308 }
309
310 impl From<Handle> for $name {
311 fn from(other: Handle) -> $name {
312 $name(other)
313 }
314 }
315
316 impl $crate::AsHandleRef for $name {
317 fn as_handle_ref(&self) -> $crate::HandleRef<'_> {
318 self.0.as_handle_ref()
319 }
320
321 fn object_type(
322 ) -> fidl::ObjectType {
323 ::fidl::ObjectType::$objtype
324 }
325 }
326
327 impl $crate::HandleBased for $name {}
328 };
329 ($name:ident $objtype:ident peered) => {
330 handle_type!($name $objtype);
331
332 impl $crate::Peered for $name {}
333 };
334}
335
336pub(crate) use handle_type;