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 client
125 .transaction(
126 ordinals::DUPLICATE,
127 proto::FDomainDuplicateRequest { handle, new_handle, rights },
128 Responder::Duplicate,
129 )
130 .map(move |res| res.map(|_| Handle { id, client: Arc::downgrade(&client) }))
131 }
132
133 pub fn signal(
135 &self,
136 set: fidl::Signals,
137 clear: fidl::Signals,
138 ) -> impl Future<Output = Result<(), Error>> + use<> {
139 let handle = self.proto();
140 let client = self.client();
141
142 client.transaction(
143 ordinals::SIGNAL,
144 proto::FDomainSignalRequest { handle, set: set.bits(), clear: clear.bits() },
145 Responder::Signal,
146 )
147 }
148
149 pub fn get_koid(&self) -> impl Future<Output = Result<u64, Error>> {
150 let handle = self.proto();
151 let client = self.client();
152 client
153 .transaction(
154 ordinals::GET_KOID,
155 proto::FDomainGetKoidRequest { handle },
156 Responder::GetKoid,
157 )
158 .map(move |res| res.map(|r| r.koid))
159 }
160}
161
162pub trait AsHandleRef {
165 fn as_handle_ref(&self) -> HandleRef<'_>;
166 fn object_type() -> fidl::ObjectType;
167
168 fn u32_id(&self) -> u32 {
169 self.as_handle_ref().0.id
170 }
171
172 fn signal_handle(
173 &self,
174 set: fidl::Signals,
175 clear: fidl::Signals,
176 ) -> impl Future<Output = Result<(), Error>> {
177 self.as_handle_ref().signal(set, clear)
178 }
179
180 fn domain(&self) -> Arc<Client> {
182 self.as_handle_ref().0.client()
183 }
184}
185
186impl AsHandleRef for Handle {
187 fn as_handle_ref(&self) -> HandleRef<'_> {
189 HandleRef(self)
190 }
191
192 fn object_type() -> fidl::ObjectType {
194 fidl::ObjectType::NONE
195 }
196}
197
198pub trait Peered: HandleBased {
200 fn signal_peer(
202 &self,
203 clear: fidl::Signals,
204 set: fidl::Signals,
205 ) -> impl Future<Output = Result<(), Error>> + use<Self> {
206 let handle = self.as_handle_ref().proto();
207 let client = self.as_handle_ref().client();
208
209 client.transaction(
210 ordinals::SIGNAL_PEER,
211 proto::FDomainSignalPeerRequest { handle, set: set.bits(), clear: clear.bits() },
212 Responder::SignalPeer,
213 )
214 }
215}
216
217pub trait HandleBased: AsHandleRef + From<Handle> + Into<Handle> {
218 fn close(self) -> impl Future<Output = Result<(), Error>> {
220 let h = <Self as Into<Handle>>::into(self);
221 Handle::close(h)
222 }
223
224 fn duplicate_handle(&self, rights: fidl::Rights) -> impl Future<Output = Result<Self, Error>> {
226 let fut = self.as_handle_ref().duplicate(rights);
227 async move { fut.await.map(|handle| Self::from(handle)) }
228 }
229
230 fn replace_handle(self, rights: fidl::Rights) -> impl Future<Output = Result<Self, Error>> {
232 let h = <Self as Into<Handle>>::into(self);
233 async move { h.replace(rights).await.map(|handle| Self::from(handle)) }
234 }
235
236 fn into_handle(self) -> Handle {
238 self.into()
239 }
240
241 fn from_handle(handle: Handle) -> Self {
243 Self::from(handle)
244 }
245
246 fn into_handle_based<H: HandleBased>(self) -> H {
248 H::from_handle(self.into_handle())
249 }
250
251 fn from_handle_based<H: HandleBased>(h: H) -> Self {
253 Self::from_handle(h.into_handle())
254 }
255
256 fn invalidate(&mut self);
258}
259
260impl HandleBased for Handle {
261 fn invalidate(&mut self) {
262 self.client = Weak::new();
264 }
265}
266
267pub struct OnFDomainSignals {
270 fut: futures::future::BoxFuture<'static, Result<fidl::Signals, Error>>,
271}
272
273impl OnFDomainSignals {
274 pub fn new(handle: &Handle, signals: fidl::Signals) -> Self {
278 let client = handle.client();
279 let handle = handle.proto();
280 let fut = client
281 .transaction(
282 ordinals::WAIT_FOR_SIGNALS,
283 proto::FDomainWaitForSignalsRequest { handle, signals: signals.bits() },
284 Responder::WaitForSignals,
285 )
286 .map(|f| f.map(|x| fidl::Signals::from_bits_retain(x.signals)));
287 OnFDomainSignals { fut: fut.boxed() }
288 }
289}
290
291impl Future for OnFDomainSignals {
292 type Output = Result<fidl::Signals, Error>;
293
294 fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
295 self.fut.as_mut().poll(cx)
296 }
297}
298
299impl Handle {
300 pub(crate) fn proto(&self) -> proto::HandleId {
302 proto::HandleId { id: self.id }
303 }
304
305 pub(crate) fn take_proto(mut self) -> proto::HandleId {
308 let ret = self.proto();
309 self.invalidate();
310 ret
311 }
312
313 pub fn close(self) -> impl Future<Output = Result<(), Error>> {
315 let client = self.client();
316 client.transaction(
317 ordinals::CLOSE,
318 proto::FDomainCloseRequest { handles: vec![self.take_proto()] },
319 Responder::Close,
320 )
321 }
322
323 pub fn replace(self, rights: fidl::Rights) -> impl Future<Output = Result<Handle, Error>> {
326 let client = self.client();
327 let handle = self.take_proto();
328 {
329 let mut client = client.0.lock();
330 let _ = client.channel_read_states.remove(&handle);
331 let _ = client.socket_read_states.remove(&handle);
332 }
333 let new_handle = client.new_hid();
334
335 let id = new_handle.id;
336 let ret = Handle { id, client: Arc::downgrade(&client) };
337 let fut = client.transaction(
338 ordinals::REPLACE,
339 proto::FDomainReplaceRequest { handle, new_handle, rights },
340 Responder::Replace,
341 );
342
343 async move {
344 fut.await?;
345 Ok(ret)
346 }
347 }
348}
349
350impl Drop for Handle {
351 fn drop(&mut self) {
352 if let Some(client) = self.client.upgrade() {
353 let mut client = client.0.lock();
354 if client.waiting_to_close.is_empty() {
355 client.waiting_to_close_waker.wake_by_ref();
356 }
357 client.waiting_to_close.push(self.proto());
358 }
359 }
360}
361
362macro_rules! handle_type {
363 ($name:ident $objtype:ident) => {
364 impl From<$name> for Handle {
365 fn from(other: $name) -> Handle {
366 other.0
367 }
368 }
369
370 impl From<Handle> for $name {
371 fn from(other: Handle) -> $name {
372 $name(other)
373 }
374 }
375
376 impl $crate::AsHandleRef for $name {
377 fn as_handle_ref(&self) -> $crate::HandleRef<'_> {
378 self.0.as_handle_ref()
379 }
380
381 fn object_type(
382 ) -> fidl::ObjectType {
383 ::fidl::ObjectType::$objtype
384 }
385 }
386
387 impl $crate::HandleBased for $name {
388 fn invalidate(&mut self) {
389 self.0.invalidate();
390 }
391 }
392 };
393 ($name:ident $objtype:ident peered) => {
394 handle_type!($name $objtype);
395
396 impl $crate::Peered for $name {}
397 };
398}
399
400pub(crate) use handle_type;