1use crate::{
8 Koid, MonotonicInstant, Name, ObjectQuery, ObjectType, Port, Property, PropertyQuery, Rights,
9 Signals, Status, Topic, WaitAsyncOpts, ok, sys,
10};
11use std::marker::PhantomData;
12use std::mem::{ManuallyDrop, MaybeUninit};
13use std::num::NonZeroU32;
14use zerocopy::{FromBytes, Immutable, IntoBytes};
15
16pub(crate) const INFO_VEC_SIZE_INITIAL: usize = 16;
18
19#[derive(Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
37#[repr(transparent)]
38pub struct Handle(NonZeroU32);
39
40static_assertions::const_assert_eq!(sys::ZX_HANDLE_INVALID, 0);
45static_assertions::assert_eq_size!(Handle, sys::zx_handle_t);
46static_assertions::assert_eq_align!(Handle, sys::zx_handle_t);
47static_assertions::assert_eq_size!(Option<Handle>, sys::zx_handle_t);
48static_assertions::assert_eq_align!(Option<Handle>, sys::zx_handle_t);
49
50impl Handle {
51 pub unsafe fn from_raw(raw: sys::zx_handle_t) -> Self {
62 debug_assert!(Self::check_raw_valid(raw).is_ok());
63 Self(NonZeroU32::new(raw).unwrap())
64 }
65
66 pub fn check_raw_valid(raw: sys::zx_handle_t) -> Result<(), Status> {
73 ok(unsafe { sys::zx_handle_check_valid(raw) })
75 }
76
77 pub const fn raw_handle(&self) -> sys::zx_handle_t {
79 self.0.get()
80 }
81
82 pub fn into_raw(self) -> sys::zx_handle_t {
84 let ret = self.0.get();
85 std::mem::forget(self);
86 ret
87 }
88
89 pub fn duplicate(&self, rights: Rights) -> Result<Self, Status> {
93 let mut out = 0;
94 let status =
96 unsafe { sys::zx_handle_duplicate(self.raw_handle(), rights.bits(), &mut out) };
97 ok(status)?;
98
99 Ok(unsafe { Self::from_raw(out) })
101 }
102
103 pub fn replace(self, rights: Rights) -> Result<Self, Status> {
107 let mut out = 0;
108
109 let status = unsafe { sys::zx_handle_replace(self.into_raw(), rights.bits(), &mut out) };
111 ok(status)?;
112
113 unsafe { Ok(Self::from_raw(out)) }
115 }
116
117 pub fn signal(&self, clear_mask: Signals, set_mask: Signals) -> Result<(), Status> {
119 ok(unsafe { sys::zx_object_signal(self.raw_handle(), clear_mask.bits(), set_mask.bits()) })
121 }
122
123 pub fn wait_one(&self, signals: Signals, deadline: MonotonicInstant) -> WaitResult {
126 let mut pending = Signals::empty().bits();
127 let status = unsafe {
129 sys::zx_object_wait_one(
130 self.raw_handle(),
131 signals.bits(),
132 deadline.into_nanos(),
133 &mut pending,
134 )
135 };
136 let signals = Signals::from_bits_truncate(pending);
137 match ok(status) {
138 Ok(()) => WaitResult::Ok(signals),
139 Err(Status::TIMED_OUT) => WaitResult::TimedOut(signals),
140 Err(Status::CANCELED) => WaitResult::Canceled(signals),
141 Err(e) => WaitResult::Err(e),
142 }
143 }
144
145 pub fn wait_async(
148 &self,
149 port: &Port,
150 key: u64,
151 signals: Signals,
152 options: WaitAsyncOpts,
153 ) -> Result<(), Status> {
154 ok(unsafe {
156 sys::zx_object_wait_async(
157 self.raw_handle(),
158 port.raw_handle(),
159 key,
160 signals.bits(),
161 options.bits(),
162 )
163 })
164 }
165
166 pub fn get_name(&self) -> Result<Name, Status> {
172 self.get_property::<NameProperty>()
173 }
174
175 pub fn set_name(&self, name: &Name) -> Result<(), Status> {
185 self.set_property::<NameProperty>(&name)
186 }
187
188 pub(crate) fn get_property<P: PropertyQuery>(&self) -> Result<P::PropTy, Status>
190 where
191 P::PropTy: FromBytes + Immutable,
192 {
193 let mut out = ::std::mem::MaybeUninit::<P::PropTy>::uninit();
194
195 let status = unsafe {
197 sys::zx_object_get_property(
198 self.raw_handle(),
199 *P::PROPERTY,
200 out.as_mut_ptr().cast::<u8>(),
201 std::mem::size_of::<P::PropTy>(),
202 )
203 };
204 Status::ok(status).map(|_| unsafe { out.assume_init() })
205 }
206
207 pub(crate) fn set_property<P: PropertyQuery>(&self, val: &P::PropTy) -> Result<(), Status>
209 where
210 P::PropTy: IntoBytes + Immutable,
211 {
212 let status = unsafe {
213 sys::zx_object_set_property(
214 self.raw_handle(),
215 *P::PROPERTY,
216 std::ptr::from_ref(val).cast::<u8>(),
217 std::mem::size_of::<P::PropTy>(),
218 )
219 };
220 Status::ok(status)
221 }
222
223 pub fn basic_info(&self) -> Result<HandleBasicInfo, Status> {
227 Ok(HandleBasicInfo::from(self.get_info_single::<HandleBasicInfoQuery>()?))
228 }
229
230 pub fn count_info(&self) -> Result<HandleCountInfo, Status> {
234 Ok(HandleCountInfo::from(self.get_info_single::<HandleCountInfoQuery>()?))
235 }
236
237 pub fn koid(&self) -> Result<Koid, Status> {
239 self.basic_info().map(|info| info.koid)
240 }
241
242 pub(crate) fn get_info<'a, Q: ObjectQuery>(
245 &self,
246 out: &'a mut [MaybeUninit<Q::InfoTy>],
247 ) -> Result<(&'a mut [Q::InfoTy], &'a mut [MaybeUninit<Q::InfoTy>], usize), Status>
248 where
249 Q::InfoTy: FromBytes + Immutable,
250 {
251 let mut actual = 0;
252 let mut avail = 0;
253
254 let status = unsafe {
257 sys::zx_object_get_info(
258 self.raw_handle(),
259 *Q::TOPIC,
260 out.as_mut_ptr().cast::<u8>(),
261 std::mem::size_of_val(out),
262 &mut actual,
263 &mut avail,
264 )
265 };
266 ok(status)?;
267
268 let (initialized, uninit) = out.split_at_mut(actual);
269
270 let initialized: &mut [Q::InfoTy] = unsafe {
274 std::slice::from_raw_parts_mut(
275 initialized.as_mut_ptr().cast::<Q::InfoTy>(),
276 initialized.len(),
277 )
278 };
279
280 Ok((initialized, uninit, avail))
281 }
282
283 pub(crate) fn get_info_single<Q: ObjectQuery>(&self) -> Result<Q::InfoTy, Status>
285 where
286 Q::InfoTy: Copy + FromBytes + Immutable,
287 {
288 let mut info = MaybeUninit::<Q::InfoTy>::uninit();
289 let (info, _uninit, _avail) = self.get_info::<Q>(std::slice::from_mut(&mut info))?;
290 Ok(info[0])
291 }
292
293 pub(crate) fn get_info_vec<Q: ObjectQuery>(&self) -> Result<Vec<Q::InfoTy>, Status> {
297 let mut out = Vec::<Q::InfoTy>::with_capacity(INFO_VEC_SIZE_INITIAL);
299 loop {
300 let (init, _uninit, avail) = self.get_info::<Q>(out.spare_capacity_mut())?;
301 let num_initialized = init.len();
302 if num_initialized == avail {
303 unsafe { out.set_len(num_initialized) };
305 return Ok(out);
306 } else {
307 if avail > out.capacity() {
308 out.reserve_exact(avail - out.len());
309 }
310 }
311 }
312 }
313}
314
315impl Drop for Handle {
316 fn drop(&mut self) {
317 unsafe { sys::zx_handle_close(self.0.get()) };
319 }
320}
321
322#[derive(Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
335#[repr(transparent)]
336pub struct NullableHandle(Option<Handle>);
337
338impl AsHandleRef for NullableHandle {
339 fn as_handle_ref(&self) -> HandleRef<'_> {
340 if let Some(inner) = &self.0 {
341 unsafe { Unowned::from_raw_handle(inner.raw_handle()) }
343 } else {
344 unsafe { Unowned::from_raw_handle(sys::ZX_HANDLE_INVALID) }
346 }
347 }
348
349 fn raw_handle(&self) -> sys::zx_handle_t {
350 self.0.as_ref().map(|h| h.raw_handle()).unwrap_or(sys::ZX_HANDLE_INVALID)
351 }
352}
353
354impl HandleBased for NullableHandle {
355 fn into_raw(self) -> sys::zx_handle_t {
356 if let Some(inner) = self.0 { inner.into_raw() } else { sys::ZX_HANDLE_INVALID }
357 }
358}
359
360impl NullableHandle {
361 #[inline(always)]
363 pub const fn invalid() -> Self {
364 Self(None)
365 }
366
367 pub const unsafe fn from_raw(raw: sys::zx_handle_t) -> Self {
379 if let Some(inner) = NonZeroU32::new(raw) { Self(Some(Handle(inner))) } else { Self(None) }
383 }
384
385 pub const fn raw_handle(&self) -> sys::zx_handle_t {
386 if let Some(inner) = &self.0 { inner.raw_handle() } else { sys::ZX_HANDLE_INVALID }
387 }
388
389 pub fn into_raw(self) -> sys::zx_handle_t {
390 self.0.map(Handle::into_raw).unwrap_or(sys::ZX_HANDLE_INVALID)
391 }
392
393 pub const fn is_invalid(&self) -> bool {
394 self.0.is_none()
395 }
396
397 pub fn duplicate(&self, rights: Rights) -> Result<Self, Status> {
398 self.0
399 .as_ref()
400 .map(|h| h.duplicate(rights).map(|new| Self(Some(new))))
401 .unwrap_or(Err(Status::BAD_HANDLE))
402 }
403
404 pub fn replace(mut self, rights: Rights) -> Result<Self, Status> {
405 if let Some(inner) = self.0.take() {
406 let inner = inner.replace(rights)?;
407 Ok(Self(Some(inner)))
408 } else {
409 Ok(Self(None))
410 }
411 }
412
413 pub fn signal(&self, clear_mask: Signals, set_mask: Signals) -> Result<(), Status> {
414 self.0.as_ref().map(|h| h.signal(clear_mask, set_mask)).unwrap_or(Err(Status::BAD_HANDLE))
415 }
416
417 pub fn wait_one(&self, signals: Signals, deadline: MonotonicInstant) -> WaitResult {
418 self.0
419 .as_ref()
420 .map(|h| h.wait_one(signals, deadline))
421 .unwrap_or(WaitResult::Err(Status::BAD_HANDLE))
422 }
423
424 pub fn wait_async(
425 &self,
426 port: &Port,
427 key: u64,
428 signals: Signals,
429 options: WaitAsyncOpts,
430 ) -> Result<(), Status> {
431 self.0
432 .as_ref()
433 .map(|h| h.wait_async(port, key, signals, options))
434 .unwrap_or(Err(Status::BAD_HANDLE))
435 }
436
437 pub fn get_name(&self) -> Result<Name, Status> {
438 self.0.as_ref().map(Handle::get_name).unwrap_or(Err(Status::BAD_HANDLE))
439 }
440
441 pub fn set_name(&self, name: &Name) -> Result<(), Status> {
442 self.0.as_ref().map(|h| h.set_name(name)).unwrap_or(Err(Status::BAD_HANDLE))
443 }
444
445 pub fn basic_info(&self) -> Result<HandleBasicInfo, Status> {
446 self.0.as_ref().map(Handle::basic_info).unwrap_or(Err(Status::BAD_HANDLE))
447 }
448
449 pub fn count_info(&self) -> Result<HandleCountInfo, Status> {
450 self.0.as_ref().map(Handle::count_info).unwrap_or(Err(Status::BAD_HANDLE))
451 }
452
453 pub fn koid(&self) -> Result<Koid, Status> {
454 self.0.as_ref().map(Handle::koid).unwrap_or(Err(Status::BAD_HANDLE))
455 }
456
457 pub(crate) fn get_info<'a, Q: ObjectQuery>(
458 &self,
459 out: &'a mut [MaybeUninit<Q::InfoTy>],
460 ) -> Result<(&'a mut [Q::InfoTy], &'a mut [MaybeUninit<Q::InfoTy>], usize), Status>
461 where
462 Q::InfoTy: FromBytes + Immutable,
463 {
464 self.0.as_ref().map(|h| h.get_info::<Q>(out)).unwrap_or(Err(Status::BAD_HANDLE))
465 }
466
467 pub(crate) fn get_info_single<Q: ObjectQuery>(&self) -> Result<Q::InfoTy, Status>
468 where
469 Q::InfoTy: Copy + FromBytes + Immutable,
470 {
471 self.0.as_ref().map(|h| h.get_info_single::<Q>()).unwrap_or(Err(Status::BAD_HANDLE))
472 }
473
474 pub(crate) fn get_info_vec<Q: ObjectQuery>(&self) -> Result<Vec<Q::InfoTy>, Status> {
475 self.0.as_ref().map(|h| h.get_info_vec::<Q>()).unwrap_or(Err(Status::BAD_HANDLE))
476 }
477
478 pub(crate) fn get_property<P: PropertyQuery>(&self) -> Result<P::PropTy, Status>
479 where
480 P::PropTy: FromBytes + Immutable,
481 {
482 self.0.as_ref().map(|h| h.get_property::<P>()).unwrap_or(Err(Status::BAD_HANDLE))
483 }
484
485 pub(crate) fn set_property<P: PropertyQuery>(&self, val: &P::PropTy) -> Result<(), Status>
486 where
487 P::PropTy: IntoBytes + Immutable,
488 {
489 self.0.as_ref().map(|h| h.set_property::<P>(val)).unwrap_or(Err(Status::BAD_HANDLE))
490 }
491}
492
493struct NameProperty();
494unsafe impl PropertyQuery for NameProperty {
495 const PROPERTY: Property = Property::NAME;
496 type PropTy = Name;
499}
500
501#[derive(Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
505#[repr(transparent)]
506pub struct Unowned<'a, T> {
507 inner: ManuallyDrop<T>,
508 marker: PhantomData<&'a T>,
509}
510
511impl<'a, T: Into<NullableHandle>> ::std::ops::Deref for Unowned<'a, T> {
512 type Target = T;
513
514 fn deref(&self) -> &Self::Target {
515 &*self.inner
516 }
517}
518
519impl<'a, T: AsHandleRef> AsHandleRef for Unowned<'a, T> {
520 fn as_handle_ref(&self) -> HandleRef<'_> {
521 Unowned {
522 inner: ManuallyDrop::new(unsafe { NullableHandle::from_raw(self.inner.raw_handle()) }),
525 marker: PhantomData,
526 }
527 }
528}
529
530impl<T: HandleBased> Clone for Unowned<'_, T> {
531 fn clone(&self) -> Self {
532 unsafe { Self::from_raw_handle(self.inner.as_handle_ref().raw_handle()) }
533 }
534}
535
536pub type HandleRef<'a> = Unowned<'a, NullableHandle>;
537
538impl<'a, T: Into<NullableHandle>> Unowned<'a, T> {
539 pub fn new<U: AsHandleRef + From<NullableHandle>>(inner: &'a U) -> Self
543 where
544 T: From<U>,
545 {
546 Unowned {
549 inner: ManuallyDrop::new(T::from(U::from(unsafe {
550 NullableHandle::from_raw(inner.as_handle_ref().raw_handle())
551 }))),
552 marker: PhantomData,
553 }
554 }
555}
556
557impl<'a, T: HandleBased> Unowned<'a, T> {
558 pub unsafe fn from_raw_handle(handle: sys::zx_handle_t) -> Self {
570 Unowned {
571 inner: ManuallyDrop::new(T::from(unsafe { NullableHandle::from_raw(handle) })),
572 marker: PhantomData,
573 }
574 }
575
576 pub fn raw_handle(&self) -> sys::zx_handle_t {
578 self.inner.raw_handle()
579 }
580}
581
582#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
588pub enum WaitResult {
589 Ok(Signals),
591
592 TimedOut(Signals),
596
597 Canceled(Signals),
604
605 Err(Status),
608}
609
610impl WaitResult {
611 pub const fn to_result(self) -> Result<Signals, Status> {
614 match self {
615 WaitResult::Ok(signals) => Ok(signals),
616 WaitResult::TimedOut(_signals) => Err(Status::TIMED_OUT),
617 WaitResult::Canceled(_signals) => Err(Status::CANCELED),
618 WaitResult::Err(status) => Err(status),
619 }
620 }
621
622 #[must_use = "if you intended to assert that this is ok, consider `.unwrap()` instead"]
627 #[inline]
628 pub const fn is_ok(&self) -> bool {
629 self.to_result().is_ok()
630 }
631
632 #[must_use = "if you intended to assert that this is err, consider `.unwrap_err()` instead"]
633 #[inline]
634 pub const fn is_err(&self) -> bool {
635 self.to_result().is_err()
636 }
637
638 #[inline]
639 pub fn map<U, F: FnOnce(Signals) -> U>(self, op: F) -> Result<U, Status> {
640 self.to_result().map(op)
641 }
642
643 #[inline]
644 pub fn map_err<F, O: FnOnce(Status) -> F>(self, op: O) -> Result<Signals, F> {
645 self.to_result().map_err(op)
646 }
647
648 #[inline]
649 #[track_caller]
650 pub fn expect(self, msg: &str) -> Signals {
651 self.to_result().expect(msg)
652 }
653
654 #[inline]
655 #[track_caller]
656 pub fn expect_err(self, msg: &str) -> Status {
657 self.to_result().expect_err(msg)
658 }
659
660 #[inline(always)]
661 #[track_caller]
662 pub fn unwrap(self) -> Signals {
663 self.to_result().unwrap()
664 }
665}
666
667impl<'a> Unowned<'a, NullableHandle> {
668 pub fn cast<T: HandleBased>(self) -> Unowned<'a, T> {
670 unsafe { Unowned::from_raw_handle(self.raw_handle()) }
672 }
673}
674
675pub trait AsHandleRef {
677 fn as_handle_ref(&self) -> HandleRef<'_>;
680
681 fn raw_handle(&self) -> sys::zx_handle_t {
685 NullableHandle::raw_handle(&self.as_handle_ref())
686 }
687
688 fn wait_async_handle(
692 &self,
693 port: &Port,
694 key: u64,
695 signals: Signals,
696 options: WaitAsyncOpts,
697 ) -> Result<(), Status> {
698 NullableHandle::wait_async(&self.as_handle_ref(), port, key, signals, options)
699 }
700
701 fn get_name(&self) -> Result<Name, Status> {
707 NullableHandle::get_name(&self.as_handle_ref())
708 }
709
710 fn set_name(&self, name: &Name) -> Result<(), Status> {
720 NullableHandle::set_name(&self.as_handle_ref(), name)
721 }
722
723 fn basic_info(&self) -> Result<HandleBasicInfo, Status> {
727 NullableHandle::basic_info(&self.as_handle_ref())
728 }
729
730 fn count_info(&self) -> Result<HandleCountInfo, Status> {
734 NullableHandle::count_info(&self.as_handle_ref())
735 }
736
737 fn get_koid(&self) -> Result<Koid, Status> {
739 NullableHandle::koid(&self.as_handle_ref())
740 }
741}
742
743impl<T: AsHandleRef> AsHandleRef for &T {
744 fn as_handle_ref(&self) -> HandleRef<'_> {
745 (*self).as_handle_ref()
746 }
747}
748
749pub trait HandleBased: AsHandleRef + From<NullableHandle> + Into<NullableHandle> {
757 fn duplicate_handle(&self, rights: Rights) -> Result<Self, Status> {
761 self.as_handle_ref().duplicate(rights).map(|handle| Self::from(handle))
762 }
763
764 fn replace_handle(self, rights: Rights) -> Result<Self, Status> {
769 <Self as Into<NullableHandle>>::into(self).replace(rights).map(|handle| Self::from(handle))
770 }
771
772 fn into_handle(self) -> NullableHandle {
776 self.into()
777 }
778
779 fn into_raw(self) -> sys::zx_handle_t {
783 self.into_handle().into_raw()
784 }
785
786 fn from_handle(handle: NullableHandle) -> Self {
790 Self::from(handle)
791 }
792
793 fn into_handle_based<H: HandleBased>(self) -> H {
795 H::from_handle(self.into_handle())
796 }
797
798 fn from_handle_based<H: HandleBased>(h: H) -> Self {
801 Self::from_handle(h.into_handle())
802 }
803
804 fn is_invalid_handle(&self) -> bool {
805 self.as_handle_ref().is_invalid()
806 }
807}
808
809pub trait Peered: HandleBased {
811 fn signal_peer(&self, clear_mask: Signals, set_mask: Signals) -> Result<(), Status> {
816 let handle = self.raw_handle();
817 let status =
818 unsafe { sys::zx_object_signal_peer(handle, clear_mask.bits(), set_mask.bits()) };
819 ok(status)
820 }
821
822 fn is_closed(&self) -> Result<bool, Status> {
830 match self
831 .as_handle_ref()
832 .wait_one(Signals::OBJECT_PEER_CLOSED, MonotonicInstant::INFINITE_PAST)
833 {
834 WaitResult::Ok(signals) => Ok(signals.contains(Signals::OBJECT_PEER_CLOSED)),
835 WaitResult::TimedOut(_) => Ok(false),
836 WaitResult::Canceled(_) => Err(Status::CANCELED),
837 WaitResult::Err(e) => Err(e),
838 }
839 }
840}
841
842#[derive(Debug, Copy, Clone, Eq, PartialEq)]
846pub struct HandleBasicInfo {
847 pub koid: Koid,
848 pub rights: Rights,
849 pub object_type: ObjectType,
850 pub related_koid: Koid,
851}
852
853impl Default for HandleBasicInfo {
854 fn default() -> Self {
855 Self::from(sys::zx_info_handle_basic_t::default())
856 }
857}
858
859impl From<sys::zx_info_handle_basic_t> for HandleBasicInfo {
860 fn from(info: sys::zx_info_handle_basic_t) -> Self {
861 let sys::zx_info_handle_basic_t { koid, rights, type_, related_koid, .. } = info;
862
863 HandleBasicInfo {
866 koid: Koid::from_raw(koid),
867 rights: Rights::from_bits_truncate(rights),
868 object_type: ObjectType::from_raw(type_),
869 related_koid: Koid::from_raw(related_koid),
870 }
871 }
872}
873
874struct HandleBasicInfoQuery;
877unsafe impl ObjectQuery for HandleBasicInfoQuery {
878 const TOPIC: Topic = Topic::HANDLE_BASIC;
879 type InfoTy = sys::zx_info_handle_basic_t;
880}
881
882sys::zx_info_handle_count_t!(HandleCountInfo);
883
884impl From<sys::zx_info_handle_count_t> for HandleCountInfo {
885 fn from(sys::zx_info_handle_count_t { handle_count }: sys::zx_info_handle_count_t) -> Self {
886 HandleCountInfo { handle_count }
887 }
888}
889
890struct HandleCountInfoQuery;
893unsafe impl ObjectQuery for HandleCountInfoQuery {
894 const TOPIC: Topic = Topic::HANDLE_COUNT;
895 type InfoTy = sys::zx_info_handle_count_t;
896}
897
898#[derive(Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
900pub enum HandleOp<'a> {
901 Move(NullableHandle),
902 Duplicate(HandleRef<'a>),
903}
904
905#[derive(Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
907#[repr(C)]
908pub struct HandleDisposition<'a> {
909 operation: sys::zx_handle_op_t,
911 handle: sys::zx_handle_t,
913 _handle_lifetime: std::marker::PhantomData<&'a ()>,
915
916 pub object_type: ObjectType,
917 pub rights: Rights,
918 pub result: Status,
919}
920
921static_assertions::assert_eq_size!(HandleDisposition<'_>, sys::zx_handle_disposition_t);
922static_assertions::const_assert_eq!(
923 std::mem::offset_of!(HandleDisposition<'_>, operation),
924 std::mem::offset_of!(sys::zx_handle_disposition_t, operation)
925);
926static_assertions::const_assert_eq!(
927 std::mem::offset_of!(HandleDisposition<'_>, handle),
928 std::mem::offset_of!(sys::zx_handle_disposition_t, handle)
929);
930static_assertions::const_assert_eq!(
931 std::mem::offset_of!(HandleDisposition<'_>, object_type),
932 std::mem::offset_of!(sys::zx_handle_disposition_t, type_)
933);
934static_assertions::const_assert_eq!(
935 std::mem::offset_of!(HandleDisposition<'_>, rights),
936 std::mem::offset_of!(sys::zx_handle_disposition_t, rights)
937);
938static_assertions::const_assert_eq!(
939 std::mem::offset_of!(HandleDisposition<'_>, result),
940 std::mem::offset_of!(sys::zx_handle_disposition_t, result)
941);
942
943impl<'a> HandleDisposition<'a> {
944 #[inline]
945 pub fn new(
946 handle_op: HandleOp<'a>,
947 object_type: ObjectType,
948 rights: Rights,
949 status: Status,
950 ) -> Self {
951 let (operation, handle) = match handle_op {
952 HandleOp::Move(h) => (sys::ZX_HANDLE_OP_MOVE, h.into_raw()),
953 HandleOp::Duplicate(h) => (sys::ZX_HANDLE_OP_DUPLICATE, h.raw_handle()),
954 };
955
956 Self {
957 operation,
958 handle,
959 _handle_lifetime: std::marker::PhantomData,
960 object_type,
961 rights: rights,
962 result: status,
963 }
964 }
965
966 pub fn raw_handle(&self) -> sys::zx_handle_t {
967 self.handle
968 }
969
970 pub fn is_move(&self) -> bool {
971 self.operation == sys::ZX_HANDLE_OP_MOVE
972 }
973
974 pub fn is_duplicate(&self) -> bool {
975 self.operation == sys::ZX_HANDLE_OP_DUPLICATE
976 }
977
978 pub fn take_op(&mut self) -> HandleOp<'a> {
979 match self.operation {
980 sys::ZX_HANDLE_OP_MOVE => {
981 HandleOp::Move(unsafe {
984 NullableHandle::from_raw(std::mem::replace(
985 &mut self.handle,
986 sys::ZX_HANDLE_INVALID,
987 ))
988 })
989 }
990 sys::ZX_HANDLE_OP_DUPLICATE => {
991 HandleOp::Duplicate(Unowned {
994 inner: ManuallyDrop::new(unsafe { NullableHandle::from_raw(self.handle) }),
995 marker: PhantomData,
996 })
997 }
998 _ => unreachable!(),
999 }
1000 }
1001
1002 pub fn into_raw(mut self) -> sys::zx_handle_disposition_t {
1003 match self.take_op() {
1004 HandleOp::Move(mut handle) => sys::zx_handle_disposition_t {
1005 operation: sys::ZX_HANDLE_OP_MOVE,
1006 handle: std::mem::replace(&mut handle, NullableHandle::invalid()).into_raw(),
1007 type_: self.object_type.into_raw(),
1008 rights: self.rights.bits(),
1009 result: self.result.into_raw(),
1010 },
1011 HandleOp::Duplicate(handle_ref) => sys::zx_handle_disposition_t {
1012 operation: sys::ZX_HANDLE_OP_DUPLICATE,
1013 handle: handle_ref.raw_handle(),
1014 type_: self.object_type.into_raw(),
1015 rights: self.rights.bits(),
1016 result: self.result.into_raw(),
1017 },
1018 }
1019 }
1020}
1021
1022impl<'a> Drop for HandleDisposition<'a> {
1023 fn drop(&mut self) {
1024 if self.operation == sys::ZX_HANDLE_OP_MOVE {
1026 unsafe { drop(NullableHandle::from_raw(self.handle)) };
1027 }
1028 }
1029}
1030
1031#[derive(Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
1035#[repr(C)]
1036pub struct HandleInfo {
1037 pub handle: NullableHandle,
1038 pub object_type: ObjectType,
1039 pub rights: Rights,
1040
1041 pub(crate) _unused: u32,
1043}
1044
1045static_assertions::assert_eq_size!(HandleInfo, sys::zx_handle_info_t);
1046static_assertions::const_assert_eq!(
1047 std::mem::offset_of!(HandleInfo, handle),
1048 std::mem::offset_of!(sys::zx_handle_info_t, handle)
1049);
1050static_assertions::const_assert_eq!(
1051 std::mem::offset_of!(HandleInfo, object_type),
1052 std::mem::offset_of!(sys::zx_handle_info_t, ty)
1053);
1054static_assertions::const_assert_eq!(
1055 std::mem::offset_of!(HandleInfo, rights),
1056 std::mem::offset_of!(sys::zx_handle_info_t, rights)
1057);
1058static_assertions::const_assert_eq!(
1059 std::mem::offset_of!(HandleInfo, _unused),
1060 std::mem::offset_of!(sys::zx_handle_info_t, unused)
1061);
1062
1063impl HandleInfo {
1064 pub const fn new(handle: NullableHandle, object_type: ObjectType, rights: Rights) -> Self {
1066 Self { handle, object_type, rights, _unused: 0 }
1067 }
1068
1069 pub const unsafe fn from_raw(raw: sys::zx_handle_info_t) -> HandleInfo {
1077 HandleInfo::new(
1078 unsafe { NullableHandle::from_raw(raw.handle) },
1080 ObjectType::from_raw(raw.ty),
1081 Rights::from_bits_retain(raw.rights),
1082 )
1083 }
1084}
1085
1086#[cfg(test)]
1087mod tests {
1088 use super::*;
1089 use zx::{
1092 AsHandleRef, Channel, HandleBased, HandleDisposition, HandleInfo, HandleOp, Name,
1093 NullableHandle, ObjectType, Rights, Vmo,
1094 };
1095 use zx_sys as sys;
1096
1097 #[test]
1098 fn into_raw() {
1099 let vmo = Vmo::create(1).unwrap();
1100 let h = vmo.into_raw();
1101 let vmo2 = Vmo::from(unsafe { NullableHandle::from_raw(h) });
1102 assert!(vmo2.write(b"1", 0).is_ok());
1103 }
1104
1105 #[test]
1106 fn check_raw_valid() {
1107 assert!(Handle::check_raw_valid(sys::ZX_HANDLE_INVALID).is_err());
1108 let vmo = Vmo::create(1).unwrap();
1109 let vmo_raw = vmo.raw_handle();
1110 assert!(Handle::check_raw_valid(vmo_raw).is_ok());
1111 drop(vmo);
1112 assert!(Handle::check_raw_valid(vmo_raw).is_err());
1113 }
1114
1115 #[test]
1117 fn duplicate() {
1118 let hello_length: usize = 5;
1119
1120 let vmo = Vmo::create(hello_length as u64).unwrap();
1122 assert!(vmo.write(b"hello", 0).is_ok());
1123
1124 let readonly_vmo = vmo.duplicate_handle(Rights::READ).unwrap();
1126 let mut read_vec = vec![0; hello_length];
1128 assert!(readonly_vmo.read(&mut read_vec, 0).is_ok());
1129 assert_eq!(read_vec, b"hello");
1130 assert_eq!(readonly_vmo.write(b"", 0), Err(Status::ACCESS_DENIED));
1131
1132 assert!(vmo.write(b"bye", 0).is_ok());
1134 assert!(readonly_vmo.read(&mut read_vec, 0).is_ok());
1135 assert_eq!(read_vec, b"byelo");
1136 }
1137
1138 #[test]
1140 fn replace() {
1141 let hello_length: usize = 5;
1142
1143 let vmo = Vmo::create(hello_length as u64).unwrap();
1145 assert!(vmo.write(b"hello", 0).is_ok());
1146
1147 let readonly_vmo = vmo.replace_handle(Rights::READ).unwrap();
1149 let mut read_vec = vec![0; hello_length];
1151 assert!(readonly_vmo.read(&mut read_vec, 0).is_ok());
1152 assert_eq!(read_vec, b"hello");
1153 assert_eq!(readonly_vmo.write(b"", 0), Err(Status::ACCESS_DENIED));
1154 }
1155
1156 #[test]
1157 fn set_get_name() {
1158 let vmo = Vmo::create(1).unwrap();
1160 let short_name = Name::new("v").unwrap();
1161 assert!(vmo.set_name(&short_name).is_ok());
1162 assert_eq!(vmo.get_name().unwrap(), short_name);
1163 }
1164
1165 #[test]
1166 fn set_get_max_len_name() {
1167 let vmo = Vmo::create(1).unwrap();
1168 let max_len_name = Name::new("a_great_maximum_length_vmo_name").unwrap(); assert!(vmo.set_name(&max_len_name).is_ok());
1170 assert_eq!(vmo.get_name().unwrap(), max_len_name);
1171 }
1172
1173 #[test]
1174 fn basic_info_channel() {
1175 let (side1, side2) = Channel::create();
1176 let info1 = side1.basic_info().expect("side1 basic_info failed");
1177 let info2 = side2.basic_info().expect("side2 basic_info failed");
1178
1179 assert_eq!(info1.koid, info2.related_koid);
1180 assert_eq!(info2.koid, info1.related_koid);
1181
1182 for info in &[info1, info2] {
1183 assert!(info.koid.raw_koid() >= sys::ZX_KOID_FIRST);
1184 assert_eq!(info.object_type, ObjectType::CHANNEL);
1185 assert!(info.rights.contains(Rights::READ | Rights::WRITE | Rights::WAIT));
1186 }
1187
1188 let side1_repl = side1.replace_handle(Rights::READ).expect("side1 replace_handle failed");
1189 let info1_repl = side1_repl.basic_info().expect("side1_repl basic_info failed");
1190 assert_eq!(info1_repl.koid, info1.koid);
1191 assert_eq!(info1_repl.rights, Rights::READ);
1192 }
1193
1194 #[test]
1195 fn basic_info_vmar() {
1196 let root_vmar = fuchsia_runtime::vmar_root_self();
1198 let info = root_vmar.basic_info().expect("vmar basic_info failed");
1199 assert_eq!(info.object_type, ObjectType::VMAR);
1200 assert!(!info.rights.contains(Rights::WAIT));
1201 }
1202
1203 #[test]
1204 fn count_info() {
1205 let vmo0 = Vmo::create(1).unwrap();
1206 let count_info = vmo0.count_info().expect("vmo0 count_info failed");
1207 assert_eq!(count_info.handle_count, 1);
1208
1209 let vmo1 = vmo0.duplicate_handle(Rights::SAME_RIGHTS).expect("vmo duplicate_handle failed");
1210 let count_info = vmo1.count_info().expect("vmo1 count_info failed");
1211 assert_eq!(count_info.handle_count, 2);
1212 }
1213
1214 #[test]
1215 fn raw_handle_disposition() {
1216 const RAW_HANDLE: sys::zx_handle_t = 1;
1217 let hd = HandleDisposition::new(
1218 HandleOp::Move(unsafe { NullableHandle::from_raw(RAW_HANDLE) }),
1219 ObjectType::VMO,
1220 Rights::EXECUTE,
1221 Status::OK,
1222 );
1223 let raw_hd = hd.into_raw();
1224 assert_eq!(raw_hd.operation, sys::ZX_HANDLE_OP_MOVE);
1225 assert_eq!(raw_hd.handle, RAW_HANDLE);
1226 assert_eq!(raw_hd.rights, sys::ZX_RIGHT_EXECUTE);
1227 assert_eq!(raw_hd.type_, sys::ZX_OBJ_TYPE_VMO);
1228 assert_eq!(raw_hd.result, sys::ZX_OK);
1229 }
1230
1231 #[test]
1232 fn regression_nullable_handle_into_raw_recursion() {
1233 let h = NullableHandle::invalid();
1234 assert_eq!(h.into_raw(), sys::ZX_HANDLE_INVALID);
1236
1237 let vmo = Vmo::create(1).unwrap();
1238 let raw = vmo.raw_handle();
1239 let h = vmo.into_handle();
1240 assert_eq!(h.into_raw(), raw);
1242 }
1243
1244 #[test]
1245 fn handle_info_from_raw() {
1246 const RAW_HANDLE: sys::zx_handle_t = 1;
1247 let raw_hi = sys::zx_handle_info_t {
1248 handle: RAW_HANDLE,
1249 ty: sys::ZX_OBJ_TYPE_VMO,
1250 rights: sys::ZX_RIGHT_EXECUTE,
1251 unused: 128,
1252 };
1253 let hi = unsafe { HandleInfo::from_raw(raw_hi) };
1254 assert_eq!(hi.handle.into_raw(), RAW_HANDLE);
1255 assert_eq!(hi.object_type, ObjectType::VMO);
1256 assert_eq!(hi.rights, Rights::EXECUTE);
1257 }
1258
1259 #[test]
1260 fn basic_peer_closed() {
1261 let (lhs, rhs) = crate::EventPair::create();
1262 assert!(!lhs.is_closed().unwrap());
1263 assert!(!rhs.is_closed().unwrap());
1264 drop(rhs);
1265 assert!(lhs.is_closed().unwrap());
1266 }
1267}