1use self::unowned::Unowned;
6use crate::responder::Responder;
7use crate::{Client, Error, ordinals};
8use fidl_fuchsia_fdomain as proto;
9use futures::FutureExt;
10use std::future::Future;
11use std::pin::Pin;
12use std::sync::{Arc, Weak};
13use std::task::{Context, Poll};
14
15pub(crate) mod unowned;
16
17pub type NullableHandle = Handle;
19
20#[derive(Debug)]
22pub struct Handle {
23 pub(crate) id: u32,
24 pub(crate) client: Weak<Client>,
25}
26
27impl Handle {
28 pub fn id(&self) -> u32 {
30 self.id
31 }
32
33 pub fn has_client(&self) -> bool {
38 self.client.upgrade().is_some()
39 }
40
41 pub(crate) fn client(&self) -> Arc<Client> {
43 self.client.upgrade().unwrap_or_else(|| Arc::clone(&*crate::DEAD_CLIENT))
44 }
45
46 pub fn invalid() -> Self {
48 Handle { id: 0, client: Weak::new() }
49 }
50
51 pub fn is_invalid(&self) -> bool {
53 !self.has_client()
54 }
55
56 pub fn as_unowned<H: HandleBased>(&self) -> Unowned<H> {
70 Unowned::from_handle(self)
71 }
72}
73
74impl std::cmp::PartialEq for Handle {
75 fn eq(&self, other: &Self) -> bool {
76 self.id == other.id && Weak::ptr_eq(&self.client, &other.client)
77 }
78}
79
80impl std::cmp::Eq for Handle {}
81
82impl std::cmp::PartialOrd for Handle {
83 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
84 Some(self.cmp(other))
85 }
86}
87
88impl std::cmp::Ord for Handle {
89 fn cmp(&self, other: &Self) -> std::cmp::Ordering {
90 self.id.cmp(&other.id)
91 }
92}
93
94impl std::hash::Hash for Handle {
95 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
96 self.id.hash(state);
97 }
98}
99
100#[derive(Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
103pub struct HandleRef<'a>(&'a Handle);
104
105impl std::ops::Deref for HandleRef<'_> {
106 type Target = Handle;
107
108 fn deref(&self) -> &Self::Target {
109 self.0
110 }
111}
112
113impl HandleRef<'_> {
114 pub fn duplicate(
117 &self,
118 rights: fidl::Rights,
119 ) -> impl Future<Output = Result<Handle, Error>> + 'static + use<> {
120 let client = self.0.client();
121 let handle = self.0.proto();
122 let new_handle = client.new_hid();
123 let id = new_handle.id;
124 let ret = Handle { id, client: Arc::downgrade(&client) };
125 client
126 .transaction(
127 ordinals::DUPLICATE,
128 proto::FDomainDuplicateRequest { handle, new_handle, rights },
129 Responder::Duplicate,
130 )
131 .map(move |res| res.map(|_| ret))
132 }
133
134 pub fn signal(
136 &self,
137 clear: fidl::Signals,
138 set: fidl::Signals,
139 ) -> impl Future<Output = Result<(), Error>> + use<> {
140 let handle = self.proto();
141 let client = self.client();
142
143 client.transaction(
144 ordinals::SIGNAL,
145 proto::FDomainSignalRequest { handle, set: set.bits(), clear: clear.bits() },
146 Responder::Signal,
147 )
148 }
149
150 pub fn get_koid(&self) -> impl Future<Output = Result<u64, Error>> {
151 let handle = self.proto();
152 let client = self.client();
153 client
154 .transaction(
155 ordinals::GET_KOID,
156 proto::FDomainGetKoidRequest { handle },
157 Responder::GetKoid,
158 )
159 .map(move |res| res.map(|r| r.koid))
160 }
161}
162
163pub trait AsHandleRef {
166 fn as_handle_ref(&self) -> HandleRef<'_>;
167 fn object_type() -> fidl::ObjectType;
168
169 fn u32_id(&self) -> u32 {
170 self.as_handle_ref().0.id
171 }
172
173 fn signal_handle(
174 &self,
175 clear: fidl::Signals,
176 set: fidl::Signals,
177 ) -> impl Future<Output = Result<(), Error>> {
178 self.as_handle_ref().signal(clear, set)
179 }
180
181 fn domain(&self) -> Arc<Client> {
183 self.as_handle_ref().0.client()
184 }
185}
186
187impl AsHandleRef for Handle {
188 fn as_handle_ref(&self) -> HandleRef<'_> {
190 HandleRef(self)
191 }
192
193 fn object_type() -> fidl::ObjectType {
195 fidl::ObjectType::NONE
196 }
197}
198
199pub trait Peered: HandleBased {
201 fn signal_peer(
203 &self,
204 clear: fidl::Signals,
205 set: fidl::Signals,
206 ) -> impl Future<Output = Result<(), Error>> + use<Self> {
207 let handle = self.as_handle_ref().proto();
208 let client = self.as_handle_ref().client();
209
210 client.transaction(
211 ordinals::SIGNAL_PEER,
212 proto::FDomainSignalPeerRequest { handle, set: set.bits(), clear: clear.bits() },
213 Responder::SignalPeer,
214 )
215 }
216}
217
218pub trait HandleBased: AsHandleRef + From<Handle> + Into<Handle> {
219 fn close(self) -> impl Future<Output = Result<(), Error>> {
221 let h = <Self as Into<Handle>>::into(self);
222 Handle::close(h)
223 }
224
225 fn duplicate_handle(&self, rights: fidl::Rights) -> impl Future<Output = Result<Self, Error>> {
227 let fut = self.as_handle_ref().duplicate(rights);
228 async move { fut.await.map(|handle| Self::from(handle)) }
229 }
230
231 fn replace_handle(self, rights: fidl::Rights) -> impl Future<Output = Result<Self, Error>> {
233 let h = <Self as Into<Handle>>::into(self);
234 async move { h.replace(rights).await.map(|handle| Self::from(handle)) }
235 }
236
237 fn into_handle(self) -> Handle {
239 self.into()
240 }
241
242 fn from_handle(handle: Handle) -> Self {
244 Self::from(handle)
245 }
246
247 fn into_handle_based<H: HandleBased>(self) -> H {
249 H::from_handle(self.into_handle())
250 }
251
252 fn from_handle_based<H: HandleBased>(h: H) -> Self {
254 Self::from_handle(h.into_handle())
255 }
256
257 fn invalidate(&mut self);
259
260 fn is_invalid(&self) -> bool {
262 self.as_handle_ref().is_invalid()
263 }
264}
265
266impl HandleBased for Handle {
267 fn invalidate(&mut self) {
268 self.client = Weak::new();
270 }
271}
272
273pub struct OnFDomainSignals {
276 fut: futures::future::BoxFuture<'static, Result<fidl::Signals, Error>>,
277}
278
279impl OnFDomainSignals {
280 pub fn new(handle: &Handle, signals: fidl::Signals) -> Self {
284 let client = handle.client();
285 let handle = handle.proto();
286 let fut = client
287 .transaction(
288 ordinals::WAIT_FOR_SIGNALS,
289 proto::FDomainWaitForSignalsRequest { handle, signals: signals.bits() },
290 Responder::WaitForSignals,
291 )
292 .map(|f| f.map(|x| fidl::Signals::from_bits_retain(x.signals)));
293 OnFDomainSignals { fut: fut.boxed() }
294 }
295}
296
297impl Future for OnFDomainSignals {
298 type Output = Result<fidl::Signals, Error>;
299
300 fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
301 self.fut.as_mut().poll(cx)
302 }
303}
304
305impl Handle {
306 pub(crate) fn proto(&self) -> proto::HandleId {
308 proto::HandleId { id: self.id }
309 }
310
311 pub(crate) fn take_proto(mut self) -> proto::HandleId {
314 let ret = self.proto();
315 self.invalidate();
316 ret
317 }
318
319 pub fn close(self) -> impl Future<Output = Result<(), Error>> {
321 let client = self.client();
322 let handle = self.take_proto();
323 {
324 let mut client = client.0.lock();
325 let _ = client.channel_read_states.remove(&handle);
326 let _ = client.socket_read_states.remove(&handle);
327 client.handles.remove(&handle);
328 }
329 client.transaction(
330 ordinals::CLOSE,
331 proto::FDomainCloseRequest { handles: vec![handle] },
332 Responder::Close,
333 )
334 }
335
336 pub fn replace(self, rights: fidl::Rights) -> impl Future<Output = Result<Handle, Error>> {
339 let client = self.client();
340 let handle = self.take_proto();
341 let new_handle = {
342 let mut client = client.0.lock();
343 let _ = client.channel_read_states.remove(&handle);
344 let _ = client.socket_read_states.remove(&handle);
345 client.handles.remove(&handle);
346 client.new_hid()
347 };
348
349 let id = new_handle.id;
350 let ret = Handle { id, client: Arc::downgrade(&client) };
351 let fut = client.transaction(
352 ordinals::REPLACE,
353 proto::FDomainReplaceRequest { handle, new_handle, rights },
354 Responder::Replace,
355 );
356
357 async move {
358 fut.await?;
359 Ok(ret)
360 }
361 }
362}
363
364impl Drop for Handle {
365 fn drop(&mut self) {
366 if let Some(client) = self.client.upgrade() {
367 let mut client = client.0.lock();
368 if client.waiting_to_close.is_empty() {
369 client.waiting_to_close_waker.wake_by_ref();
370 }
371 client.waiting_to_close.push(self.proto());
372 }
373 }
374}
375
376macro_rules! handle_type {
377 ($name:ident $objtype:ident) => {
378 impl $name {
379 pub fn invalid() -> Self {
381 $name($crate::Handle::invalid())
382 }
383
384 pub fn is_invalid(&self) -> bool {
386 self.0.is_invalid()
387 }
388 }
389
390 impl From<$name> for Handle {
391 fn from(other: $name) -> Handle {
392 other.0
393 }
394 }
395
396 impl From<Handle> for $name {
397 fn from(other: Handle) -> $name {
398 $name(other)
399 }
400 }
401
402 impl $crate::AsHandleRef for $name {
403 fn as_handle_ref(&self) -> $crate::HandleRef<'_> {
404 self.0.as_handle_ref()
405 }
406
407 fn object_type(
408 ) -> fidl::ObjectType {
409 ::fidl::ObjectType::$objtype
410 }
411 }
412
413 impl $crate::HandleBased for $name {
414 fn invalidate(&mut self) {
415 self.0.invalidate();
416 }
417 }
418 };
419 ($name:ident $objtype:ident peered) => {
420 handle_type!($name $objtype);
421
422 impl $crate::Peered for $name {}
423 };
424}
425
426pub(crate) use handle_type;