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 as_unowned<H: HandleBased>(&self) -> Unowned<H> {
65 Unowned::from_handle(self)
66 }
67}
68
69impl std::cmp::PartialEq for Handle {
70 fn eq(&self, other: &Self) -> bool {
71 self.id == other.id && Weak::ptr_eq(&self.client, &other.client)
72 }
73}
74
75impl std::cmp::Eq for Handle {}
76
77impl std::cmp::PartialOrd for Handle {
78 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
79 Some(self.cmp(other))
80 }
81}
82
83impl std::cmp::Ord for Handle {
84 fn cmp(&self, other: &Self) -> std::cmp::Ordering {
85 self.id.cmp(&other.id)
86 }
87}
88
89impl std::hash::Hash for Handle {
90 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
91 self.id.hash(state);
92 }
93}
94
95#[derive(Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
98pub struct HandleRef<'a>(&'a Handle);
99
100impl std::ops::Deref for HandleRef<'_> {
101 type Target = Handle;
102
103 fn deref(&self) -> &Self::Target {
104 self.0
105 }
106}
107
108impl HandleRef<'_> {
109 pub fn duplicate(
112 &self,
113 rights: fidl::Rights,
114 ) -> impl Future<Output = Result<Handle, Error>> + 'static + use<> {
115 let client = self.0.client();
116 let handle = self.0.proto();
117 let new_handle = client.new_hid();
118 let id = new_handle.id;
119 client
120 .transaction(
121 ordinals::DUPLICATE,
122 proto::FDomainDuplicateRequest { handle, new_handle, rights },
123 Responder::Duplicate,
124 )
125 .map(move |res| res.map(|_| Handle { id, client: Arc::downgrade(&client) }))
126 }
127
128 pub fn signal(
130 &self,
131 set: fidl::Signals,
132 clear: fidl::Signals,
133 ) -> impl Future<Output = Result<(), Error>> + use<> {
134 let handle = self.proto();
135 let client = self.client();
136
137 client.transaction(
138 ordinals::SIGNAL,
139 proto::FDomainSignalRequest { handle, set: set.bits(), clear: clear.bits() },
140 Responder::Signal,
141 )
142 }
143
144 pub fn get_koid(&self) -> impl Future<Output = Result<u64, Error>> {
145 let handle = self.proto();
146 let client = self.client();
147 client
148 .transaction(
149 ordinals::GET_KOID,
150 proto::FDomainGetKoidRequest { handle },
151 Responder::GetKoid,
152 )
153 .map(move |res| res.map(|r| r.koid))
154 }
155}
156
157pub trait AsHandleRef {
160 fn as_handle_ref(&self) -> HandleRef<'_>;
161 fn object_type() -> fidl::ObjectType;
162
163 fn u32_id(&self) -> u32 {
164 self.as_handle_ref().0.id
165 }
166
167 fn signal_handle(
168 &self,
169 set: fidl::Signals,
170 clear: fidl::Signals,
171 ) -> impl Future<Output = Result<(), Error>> {
172 self.as_handle_ref().signal(set, clear)
173 }
174
175 fn domain(&self) -> Arc<Client> {
177 self.as_handle_ref().0.client()
178 }
179}
180
181impl AsHandleRef for Handle {
182 fn as_handle_ref(&self) -> HandleRef<'_> {
184 HandleRef(self)
185 }
186
187 fn object_type() -> fidl::ObjectType {
189 fidl::ObjectType::NONE
190 }
191}
192
193pub trait Peered: HandleBased {
195 fn signal_peer(
197 &self,
198 set: fidl::Signals,
199 clear: fidl::Signals,
200 ) -> impl Future<Output = Result<(), Error>> {
201 let handle = self.as_handle_ref().proto();
202 let client = self.as_handle_ref().client();
203
204 client.transaction(
205 ordinals::SIGNAL_PEER,
206 proto::FDomainSignalPeerRequest { handle, set: set.bits(), clear: clear.bits() },
207 Responder::SignalPeer,
208 )
209 }
210}
211
212pub trait HandleBased: AsHandleRef + From<Handle> + Into<Handle> {
213 fn close(self) -> impl Future<Output = Result<(), Error>> {
215 let h = <Self as Into<Handle>>::into(self);
216 Handle::close(h)
217 }
218
219 fn duplicate_handle(&self, rights: fidl::Rights) -> impl Future<Output = Result<Self, Error>> {
221 let fut = self.as_handle_ref().duplicate(rights);
222 async move { fut.await.map(|handle| Self::from(handle)) }
223 }
224
225 fn replace_handle(self, rights: fidl::Rights) -> impl Future<Output = Result<Self, Error>> {
227 let h = <Self as Into<Handle>>::into(self);
228 async move { h.replace(rights).await.map(|handle| Self::from(handle)) }
229 }
230
231 fn into_handle(self) -> Handle {
233 self.into()
234 }
235
236 fn from_handle(handle: Handle) -> Self {
238 Self::from(handle)
239 }
240
241 fn into_handle_based<H: HandleBased>(self) -> H {
243 H::from_handle(self.into_handle())
244 }
245
246 fn from_handle_based<H: HandleBased>(h: H) -> Self {
248 Self::from_handle(h.into_handle())
249 }
250
251 fn invalidate(&mut self);
253}
254
255impl HandleBased for Handle {
256 fn invalidate(&mut self) {
257 self.client = Weak::new();
259 }
260}
261
262pub struct OnFDomainSignals {
265 fut: futures::future::BoxFuture<'static, Result<fidl::Signals, Error>>,
266}
267
268impl OnFDomainSignals {
269 pub fn new(handle: &Handle, signals: fidl::Signals) -> Self {
273 let client = handle.client();
274 let handle = handle.proto();
275 let fut = client
276 .transaction(
277 ordinals::WAIT_FOR_SIGNALS,
278 proto::FDomainWaitForSignalsRequest { handle, signals: signals.bits() },
279 Responder::WaitForSignals,
280 )
281 .map(|f| f.map(|x| fidl::Signals::from_bits_retain(x.signals)));
282 OnFDomainSignals { fut: fut.boxed() }
283 }
284}
285
286impl Future for OnFDomainSignals {
287 type Output = Result<fidl::Signals, Error>;
288
289 fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
290 self.fut.as_mut().poll(cx)
291 }
292}
293
294impl Handle {
295 pub(crate) fn proto(&self) -> proto::HandleId {
297 proto::HandleId { id: self.id }
298 }
299
300 pub(crate) fn take_proto(mut self) -> proto::HandleId {
303 let ret = self.proto();
304 self.invalidate();
305 ret
306 }
307
308 pub fn close(self) -> impl Future<Output = Result<(), Error>> {
310 let client = self.client();
311 client.transaction(
312 ordinals::CLOSE,
313 proto::FDomainCloseRequest { handles: vec![self.take_proto()] },
314 Responder::Close,
315 )
316 }
317
318 pub fn replace(self, rights: fidl::Rights) -> impl Future<Output = Result<Handle, 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 }
328 let new_handle = client.new_hid();
329
330 let id = new_handle.id;
331 let ret = Handle { id, client: Arc::downgrade(&client) };
332 let fut = client.transaction(
333 ordinals::REPLACE,
334 proto::FDomainReplaceRequest { handle, new_handle, rights },
335 Responder::Replace,
336 );
337
338 async move {
339 fut.await?;
340 Ok(ret)
341 }
342 }
343}
344
345impl Drop for Handle {
346 fn drop(&mut self) {
347 if let Some(client) = self.client.upgrade() {
348 let mut client = client.0.lock();
349 if client.waiting_to_close.is_empty() {
350 client.waiting_to_close_waker.wake_by_ref();
351 }
352 client.waiting_to_close.push(self.proto());
353 }
354 }
355}
356
357macro_rules! handle_type {
358 ($name:ident $objtype:ident) => {
359 impl From<$name> for Handle {
360 fn from(other: $name) -> Handle {
361 other.0
362 }
363 }
364
365 impl From<Handle> for $name {
366 fn from(other: Handle) -> $name {
367 $name(other)
368 }
369 }
370
371 impl $crate::AsHandleRef for $name {
372 fn as_handle_ref(&self) -> $crate::HandleRef<'_> {
373 self.0.as_handle_ref()
374 }
375
376 fn object_type(
377 ) -> fidl::ObjectType {
378 ::fidl::ObjectType::$objtype
379 }
380 }
381
382 impl $crate::HandleBased for $name {
383 fn invalidate(&mut self) {
384 self.0.invalidate();
385 }
386 }
387 };
388 ($name:ident $objtype:ident peered) => {
389 handle_type!($name $objtype);
390
391 impl $crate::Peered for $name {}
392 };
393}
394
395pub(crate) use handle_type;