1use crate::{
8 MonotonicInstant, Name, ObjectQuery, Port, Property, PropertyQuery, Rights, Signals, Status,
9 Topic, WaitAsyncOpts, object_get_info_single, object_get_property, object_set_property, ok,
10 sys,
11};
12use std::marker::PhantomData;
13use std::mem::{self, ManuallyDrop};
14use std::num::NonZeroU32;
15
16#[derive(Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
34#[repr(transparent)]
35pub struct Handle(NonZeroU32);
36
37static_assertions::const_assert_eq!(sys::ZX_HANDLE_INVALID, 0);
42static_assertions::assert_eq_size!(Handle, sys::zx_handle_t);
43static_assertions::assert_eq_align!(Handle, sys::zx_handle_t);
44static_assertions::assert_eq_size!(Option<Handle>, sys::zx_handle_t);
45static_assertions::assert_eq_align!(Option<Handle>, sys::zx_handle_t);
46
47impl Handle {
48 pub unsafe fn from_raw(raw: sys::zx_handle_t) -> Self {
59 debug_assert!(Self::check_raw_valid(raw).is_ok());
60 Self(NonZeroU32::new(raw).unwrap())
61 }
62
63 pub fn check_raw_valid(raw: sys::zx_handle_t) -> Result<(), Status> {
70 ok(unsafe { sys::zx_handle_check_valid(raw) })
72 }
73
74 pub const fn raw_handle(&self) -> sys::zx_handle_t {
76 self.0.get()
77 }
78
79 pub const fn into_raw(self) -> sys::zx_handle_t {
81 let ret = self.0.get();
82 std::mem::forget(self);
83 ret
84 }
85
86 pub fn replace(self, rights: Rights) -> Result<Self, Status> {
90 let mut out = 0;
91
92 let status = unsafe { sys::zx_handle_replace(self.into_raw(), rights.bits(), &mut out) };
94 ok(status)?;
95
96 unsafe { Ok(Self::from_raw(out)) }
98 }
99}
100
101impl Drop for Handle {
102 fn drop(&mut self) {
103 unsafe { sys::zx_handle_close(self.0.get()) };
105 }
106}
107
108#[derive(
109 Debug,
110 Copy,
111 Clone,
112 Eq,
113 PartialEq,
114 Ord,
115 PartialOrd,
116 Hash,
117 zerocopy::FromBytes,
118 zerocopy::KnownLayout,
119 zerocopy::Immutable,
120)]
121#[repr(transparent)]
122pub struct Koid(sys::zx_koid_t);
123
124impl Koid {
125 pub const fn from_raw(raw: sys::zx_koid_t) -> Koid {
126 Koid(raw)
127 }
128
129 pub const fn raw_koid(&self) -> sys::zx_koid_t {
130 self.0
131 }
132}
133
134#[derive(Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
147#[repr(transparent)]
148pub struct NullableHandle(Option<Handle>);
149
150impl AsHandleRef for NullableHandle {
151 fn as_handle_ref(&self) -> HandleRef<'_> {
152 if let Some(inner) = &self.0 {
153 unsafe { Unowned::from_raw_handle(inner.raw_handle()) }
155 } else {
156 unsafe { Unowned::from_raw_handle(sys::ZX_HANDLE_INVALID) }
158 }
159 }
160
161 fn raw_handle(&self) -> sys::zx_handle_t {
162 self.0.as_ref().map(|h| h.raw_handle()).unwrap_or(sys::ZX_HANDLE_INVALID)
163 }
164}
165
166impl HandleBased for NullableHandle {
167 fn into_raw(self) -> sys::zx_handle_t {
168 if let Some(inner) = self.0 { inner.into_raw() } else { sys::ZX_HANDLE_INVALID }
169 }
170}
171
172impl NullableHandle {
173 #[inline(always)]
175 pub const fn invalid() -> Self {
176 Self(None)
177 }
178
179 pub const unsafe fn from_raw(raw: sys::zx_handle_t) -> Self {
191 if let Some(inner) = NonZeroU32::new(raw) { Self(Some(Handle(inner))) } else { Self(None) }
195 }
196
197 pub fn is_invalid(&self) -> bool {
198 self.0.is_none()
199 }
200
201 pub fn replace(mut self, rights: Rights) -> Result<Self, Status> {
202 if let Some(inner) = self.0.take() {
203 let inner = inner.replace(rights)?;
204 Ok(Self(Some(inner)))
205 } else {
206 Ok(Self(None))
207 }
208 }
209}
210struct NameProperty();
211unsafe impl PropertyQuery for NameProperty {
212 const PROPERTY: Property = Property::NAME;
213 type PropTy = Name;
216}
217
218#[derive(Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
222#[repr(transparent)]
223pub struct Unowned<'a, T: Into<NullableHandle>> {
224 inner: ManuallyDrop<T>,
225 marker: PhantomData<&'a T>,
226}
227
228impl<T: Into<NullableHandle>> Drop for Unowned<'_, T> {
229 fn drop(&mut self) {
230 let handle: NullableHandle = unsafe { ManuallyDrop::take(&mut self.inner).into() };
232 mem::forget(handle);
233 }
234}
235
236impl<'a, T: Into<NullableHandle>> ::std::ops::Deref for Unowned<'a, T> {
237 type Target = T;
238
239 fn deref(&self) -> &Self::Target {
240 &*self.inner
241 }
242}
243
244impl<T: HandleBased> Clone for Unowned<'_, T> {
245 fn clone(&self) -> Self {
246 unsafe { Self::from_raw_handle(self.inner.as_handle_ref().raw_handle()) }
247 }
248}
249
250pub type HandleRef<'a> = Unowned<'a, NullableHandle>;
251
252impl<'a, T: Into<NullableHandle>> Unowned<'a, T> {
253 pub fn new<U: AsHandleRef + From<NullableHandle>>(inner: &'a U) -> Self
257 where
258 T: From<U>,
259 {
260 Unowned {
263 inner: ManuallyDrop::new(T::from(U::from(unsafe {
264 NullableHandle::from_raw(inner.as_handle_ref().raw_handle())
265 }))),
266 marker: PhantomData,
267 }
268 }
269}
270
271impl<'a, T: HandleBased> Unowned<'a, T> {
272 pub unsafe fn from_raw_handle(handle: sys::zx_handle_t) -> Self {
284 Unowned {
285 inner: ManuallyDrop::new(T::from(unsafe { NullableHandle::from_raw(handle) })),
286 marker: PhantomData,
287 }
288 }
289
290 pub fn raw_handle(&self) -> sys::zx_handle_t {
291 self.inner.raw_handle()
292 }
293
294 pub fn duplicate(&self, rights: Rights) -> Result<T, Status> {
295 let mut out = 0;
296 let status =
298 unsafe { sys::zx_handle_duplicate(self.raw_handle(), rights.bits(), &mut out) };
299 ok(status)?;
300
301 Ok(T::from(unsafe { NullableHandle::from_raw(out) }))
303 }
304
305 pub fn signal(&self, clear_mask: Signals, set_mask: Signals) -> Result<(), Status> {
306 let status =
307 unsafe { sys::zx_object_signal(self.raw_handle(), clear_mask.bits(), set_mask.bits()) };
308 ok(status)
309 }
310
311 pub fn wait(&self, signals: Signals, deadline: MonotonicInstant) -> WaitResult {
312 let mut pending = Signals::empty().bits();
313 let status = unsafe {
314 sys::zx_object_wait_one(
315 self.raw_handle(),
316 signals.bits(),
317 deadline.into_nanos(),
318 &mut pending,
319 )
320 };
321 let signals = Signals::from_bits_truncate(pending);
322 match ok(status) {
323 Ok(()) => WaitResult::Ok(signals),
324 Err(Status::TIMED_OUT) => WaitResult::TimedOut(signals),
325 Err(Status::CANCELED) => WaitResult::Canceled(signals),
326 Err(e) => WaitResult::Err(e),
327 }
328 }
329
330 pub fn wait_async(
331 &self,
332 port: &Port,
333 key: u64,
334 signals: Signals,
335 options: WaitAsyncOpts,
336 ) -> Result<(), Status> {
337 let status = unsafe {
338 sys::zx_object_wait_async(
339 self.raw_handle(),
340 port.raw_handle(),
341 key,
342 signals.bits(),
343 options.bits(),
344 )
345 };
346 ok(status)
347 }
348}
349
350#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
356pub enum WaitResult {
357 Ok(Signals),
359
360 TimedOut(Signals),
364
365 Canceled(Signals),
372
373 Err(Status),
376}
377
378impl WaitResult {
379 pub const fn to_result(self) -> Result<Signals, Status> {
382 match self {
383 WaitResult::Ok(signals) => Ok(signals),
384 WaitResult::TimedOut(_signals) => Err(Status::TIMED_OUT),
385 WaitResult::Canceled(_signals) => Err(Status::CANCELED),
386 WaitResult::Err(status) => Err(status),
387 }
388 }
389
390 #[must_use = "if you intended to assert that this is ok, consider `.unwrap()` instead"]
395 #[inline]
396 pub const fn is_ok(&self) -> bool {
397 self.to_result().is_ok()
398 }
399
400 #[must_use = "if you intended to assert that this is err, consider `.unwrap_err()` instead"]
401 #[inline]
402 pub const fn is_err(&self) -> bool {
403 self.to_result().is_err()
404 }
405
406 #[inline]
407 pub fn map<U, F: FnOnce(Signals) -> U>(self, op: F) -> Result<U, Status> {
408 self.to_result().map(op)
409 }
410
411 #[inline]
412 pub fn map_err<F, O: FnOnce(Status) -> F>(self, op: O) -> Result<Signals, F> {
413 self.to_result().map_err(op)
414 }
415
416 #[inline]
417 #[track_caller]
418 pub fn expect(self, msg: &str) -> Signals {
419 self.to_result().expect(msg)
420 }
421
422 #[inline]
423 #[track_caller]
424 pub fn expect_err(self, msg: &str) -> Status {
425 self.to_result().expect_err(msg)
426 }
427
428 #[inline(always)]
429 #[track_caller]
430 pub fn unwrap(self) -> Signals {
431 self.to_result().unwrap()
432 }
433}
434
435impl<'a> Unowned<'a, NullableHandle> {
436 pub fn cast<T: HandleBased>(self) -> Unowned<'a, T> {
438 unsafe { Unowned::from_raw_handle(self.raw_handle()) }
440 }
441}
442
443pub trait AsHandleRef {
445 fn as_handle_ref(&self) -> HandleRef<'_>;
448
449 fn raw_handle(&self) -> sys::zx_handle_t {
453 self.as_handle_ref().inner.raw_handle()
454 }
455
456 fn signal_handle(&self, clear_mask: Signals, set_mask: Signals) -> Result<(), Status> {
460 self.as_handle_ref().signal(clear_mask, set_mask)
461 }
462
463 fn wait_handle(&self, signals: Signals, deadline: MonotonicInstant) -> WaitResult {
467 self.as_handle_ref().wait(signals, deadline)
468 }
469
470 fn wait_async_handle(
474 &self,
475 port: &Port,
476 key: u64,
477 signals: Signals,
478 options: WaitAsyncOpts,
479 ) -> Result<(), Status> {
480 self.as_handle_ref().wait_async(port, key, signals, options)
481 }
482
483 fn get_name(&self) -> Result<Name, Status> {
489 object_get_property::<NameProperty>(self.as_handle_ref())
490 }
491
492 fn set_name(&self, name: &Name) -> Result<(), Status> {
502 object_set_property::<NameProperty>(self.as_handle_ref(), &name)
503 }
504
505 fn basic_info(&self) -> Result<HandleBasicInfo, Status> {
509 Ok(HandleBasicInfo::from(object_get_info_single::<HandleBasicInfoQuery>(
510 self.as_handle_ref(),
511 )?))
512 }
513
514 fn count_info(&self) -> Result<HandleCountInfo, Status> {
518 Ok(HandleCountInfo::from(object_get_info_single::<HandleCountInfoQuery>(
519 self.as_handle_ref(),
520 )?))
521 }
522
523 fn get_koid(&self) -> Result<Koid, Status> {
525 self.basic_info().map(|info| info.koid)
526 }
527}
528
529impl<'a, T: HandleBased> AsHandleRef for Unowned<'a, T> {
530 fn as_handle_ref(&self) -> HandleRef<'_> {
531 self.inner.as_handle_ref()
532 }
533}
534
535impl<T: AsHandleRef> AsHandleRef for &T {
536 fn as_handle_ref(&self) -> HandleRef<'_> {
537 (*self).as_handle_ref()
538 }
539}
540
541pub trait HandleBased: AsHandleRef + From<NullableHandle> + Into<NullableHandle> {
549 fn duplicate_handle(&self, rights: Rights) -> Result<Self, Status> {
553 self.as_handle_ref().duplicate(rights).map(|handle| Self::from(handle))
554 }
555
556 fn replace_handle(self, rights: Rights) -> Result<Self, Status> {
561 <Self as Into<NullableHandle>>::into(self).replace(rights).map(|handle| Self::from(handle))
562 }
563
564 fn into_handle(self) -> NullableHandle {
568 self.into()
569 }
570
571 fn into_raw(self) -> sys::zx_handle_t {
575 self.into_handle().into_raw()
576 }
577
578 fn from_handle(handle: NullableHandle) -> Self {
582 Self::from(handle)
583 }
584
585 fn into_handle_based<H: HandleBased>(self) -> H {
587 H::from_handle(self.into_handle())
588 }
589
590 fn from_handle_based<H: HandleBased>(h: H) -> Self {
593 Self::from_handle(h.into_handle())
594 }
595
596 fn is_invalid_handle(&self) -> bool {
597 self.as_handle_ref().is_invalid()
598 }
599}
600
601pub trait Peered: HandleBased {
603 fn signal_peer(&self, clear_mask: Signals, set_mask: Signals) -> Result<(), Status> {
608 let handle = self.raw_handle();
609 let status =
610 unsafe { sys::zx_object_signal_peer(handle, clear_mask.bits(), set_mask.bits()) };
611 ok(status)
612 }
613
614 fn is_closed(&self) -> Result<bool, Status> {
622 match self.wait_handle(Signals::OBJECT_PEER_CLOSED, MonotonicInstant::INFINITE_PAST) {
623 WaitResult::Ok(signals) => Ok(signals.contains(Signals::OBJECT_PEER_CLOSED)),
624 WaitResult::TimedOut(_) => Ok(false),
625 WaitResult::Canceled(_) => Err(Status::CANCELED),
626 WaitResult::Err(e) => Err(e),
627 }
628 }
629}
630
631#[derive(Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash)]
633#[repr(transparent)]
634pub struct ObjectType(sys::zx_obj_type_t);
635
636assoc_values!(ObjectType, [
637 NONE = sys::ZX_OBJ_TYPE_NONE;
638 PROCESS = sys::ZX_OBJ_TYPE_PROCESS;
639 THREAD = sys::ZX_OBJ_TYPE_THREAD;
640 VMO = sys::ZX_OBJ_TYPE_VMO;
641 CHANNEL = sys::ZX_OBJ_TYPE_CHANNEL;
642 EVENT = sys::ZX_OBJ_TYPE_EVENT;
643 PORT = sys::ZX_OBJ_TYPE_PORT;
644 INTERRUPT = sys::ZX_OBJ_TYPE_INTERRUPT;
645 PCI_DEVICE = sys::ZX_OBJ_TYPE_PCI_DEVICE;
646 DEBUGLOG = sys::ZX_OBJ_TYPE_DEBUGLOG;
647 SOCKET = sys::ZX_OBJ_TYPE_SOCKET;
648 RESOURCE = sys::ZX_OBJ_TYPE_RESOURCE;
649 EVENTPAIR = sys::ZX_OBJ_TYPE_EVENTPAIR;
650 JOB = sys::ZX_OBJ_TYPE_JOB;
651 VMAR = sys::ZX_OBJ_TYPE_VMAR;
652 FIFO = sys::ZX_OBJ_TYPE_FIFO;
653 GUEST = sys::ZX_OBJ_TYPE_GUEST;
654 VCPU = sys::ZX_OBJ_TYPE_VCPU;
655 TIMER = sys::ZX_OBJ_TYPE_TIMER;
656 IOMMU = sys::ZX_OBJ_TYPE_IOMMU;
657 BTI = sys::ZX_OBJ_TYPE_BTI;
658 PROFILE = sys::ZX_OBJ_TYPE_PROFILE;
659 PMT = sys::ZX_OBJ_TYPE_PMT;
660 SUSPEND_TOKEN = sys::ZX_OBJ_TYPE_SUSPEND_TOKEN;
661 PAGER = sys::ZX_OBJ_TYPE_PAGER;
662 EXCEPTION = sys::ZX_OBJ_TYPE_EXCEPTION;
663 CLOCK = sys::ZX_OBJ_TYPE_CLOCK;
664 STREAM = sys::ZX_OBJ_TYPE_STREAM;
665 MSI = sys::ZX_OBJ_TYPE_MSI;
666 IOB = sys::ZX_OBJ_TYPE_IOB;
667 COUNTER = sys::ZX_OBJ_TYPE_COUNTER;
668]);
669
670impl ObjectType {
671 pub const fn from_raw(raw: sys::zx_obj_type_t) -> Self {
673 Self(raw)
674 }
675
676 pub const fn into_raw(self) -> sys::zx_obj_type_t {
678 self.0
679 }
680}
681
682#[derive(Debug, Copy, Clone, Eq, PartialEq)]
686pub struct HandleBasicInfo {
687 pub koid: Koid,
688 pub rights: Rights,
689 pub object_type: ObjectType,
690 pub related_koid: Koid,
691}
692
693impl Default for HandleBasicInfo {
694 fn default() -> Self {
695 Self::from(sys::zx_info_handle_basic_t::default())
696 }
697}
698
699impl From<sys::zx_info_handle_basic_t> for HandleBasicInfo {
700 fn from(info: sys::zx_info_handle_basic_t) -> Self {
701 let sys::zx_info_handle_basic_t { koid, rights, type_, related_koid, .. } = info;
702
703 HandleBasicInfo {
706 koid: Koid(koid),
707 rights: Rights::from_bits_truncate(rights),
708 object_type: ObjectType(type_),
709 related_koid: Koid(related_koid),
710 }
711 }
712}
713
714struct HandleBasicInfoQuery;
717unsafe impl ObjectQuery for HandleBasicInfoQuery {
718 const TOPIC: Topic = Topic::HANDLE_BASIC;
719 type InfoTy = sys::zx_info_handle_basic_t;
720}
721
722sys::zx_info_handle_count_t!(HandleCountInfo);
723
724impl From<sys::zx_info_handle_count_t> for HandleCountInfo {
725 fn from(sys::zx_info_handle_count_t { handle_count }: sys::zx_info_handle_count_t) -> Self {
726 HandleCountInfo { handle_count }
727 }
728}
729
730struct HandleCountInfoQuery;
733unsafe impl ObjectQuery for HandleCountInfoQuery {
734 const TOPIC: Topic = Topic::HANDLE_COUNT;
735 type InfoTy = sys::zx_info_handle_count_t;
736}
737
738#[derive(Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
740pub enum HandleOp<'a> {
741 Move(NullableHandle),
742 Duplicate(HandleRef<'a>),
743}
744
745#[derive(Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
747#[repr(C)]
748pub struct HandleDisposition<'a> {
749 operation: sys::zx_handle_op_t,
751 handle: sys::zx_handle_t,
753 _handle_lifetime: std::marker::PhantomData<&'a ()>,
755
756 pub object_type: ObjectType,
757 pub rights: Rights,
758 pub result: Status,
759}
760
761static_assertions::assert_eq_size!(HandleDisposition<'_>, sys::zx_handle_disposition_t);
762static_assertions::const_assert_eq!(
763 std::mem::offset_of!(HandleDisposition<'_>, operation),
764 std::mem::offset_of!(sys::zx_handle_disposition_t, operation)
765);
766static_assertions::const_assert_eq!(
767 std::mem::offset_of!(HandleDisposition<'_>, handle),
768 std::mem::offset_of!(sys::zx_handle_disposition_t, handle)
769);
770static_assertions::const_assert_eq!(
771 std::mem::offset_of!(HandleDisposition<'_>, object_type),
772 std::mem::offset_of!(sys::zx_handle_disposition_t, type_)
773);
774static_assertions::const_assert_eq!(
775 std::mem::offset_of!(HandleDisposition<'_>, rights),
776 std::mem::offset_of!(sys::zx_handle_disposition_t, rights)
777);
778static_assertions::const_assert_eq!(
779 std::mem::offset_of!(HandleDisposition<'_>, result),
780 std::mem::offset_of!(sys::zx_handle_disposition_t, result)
781);
782
783impl<'a> HandleDisposition<'a> {
784 #[inline]
785 pub fn new(
786 handle_op: HandleOp<'a>,
787 object_type: ObjectType,
788 rights: Rights,
789 status: Status,
790 ) -> Self {
791 let (operation, handle) = match handle_op {
792 HandleOp::Move(h) => (sys::ZX_HANDLE_OP_MOVE, h.into_raw()),
793 HandleOp::Duplicate(h) => (sys::ZX_HANDLE_OP_DUPLICATE, h.raw_handle()),
794 };
795
796 Self {
797 operation,
798 handle,
799 _handle_lifetime: std::marker::PhantomData,
800 object_type,
801 rights: rights,
802 result: status,
803 }
804 }
805
806 pub fn raw_handle(&self) -> sys::zx_handle_t {
807 self.handle
808 }
809
810 pub fn is_move(&self) -> bool {
811 self.operation == sys::ZX_HANDLE_OP_MOVE
812 }
813
814 pub fn is_duplicate(&self) -> bool {
815 self.operation == sys::ZX_HANDLE_OP_DUPLICATE
816 }
817
818 pub fn take_op(&mut self) -> HandleOp<'a> {
819 match self.operation {
820 sys::ZX_HANDLE_OP_MOVE => {
821 HandleOp::Move(unsafe {
824 NullableHandle::from_raw(std::mem::replace(
825 &mut self.handle,
826 sys::ZX_HANDLE_INVALID,
827 ))
828 })
829 }
830 sys::ZX_HANDLE_OP_DUPLICATE => {
831 HandleOp::Duplicate(unsafe { Unowned::from_raw_handle(self.handle) })
834 }
835 _ => unreachable!(),
836 }
837 }
838
839 pub fn into_raw(mut self) -> sys::zx_handle_disposition_t {
840 match self.take_op() {
841 HandleOp::Move(mut handle) => sys::zx_handle_disposition_t {
842 operation: sys::ZX_HANDLE_OP_MOVE,
843 handle: std::mem::replace(&mut handle, NullableHandle::invalid()).into_raw(),
844 type_: self.object_type.0,
845 rights: self.rights.bits(),
846 result: self.result.into_raw(),
847 },
848 HandleOp::Duplicate(handle_ref) => sys::zx_handle_disposition_t {
849 operation: sys::ZX_HANDLE_OP_DUPLICATE,
850 handle: handle_ref.raw_handle(),
851 type_: self.object_type.0,
852 rights: self.rights.bits(),
853 result: self.result.into_raw(),
854 },
855 }
856 }
857}
858
859impl<'a> Drop for HandleDisposition<'a> {
860 fn drop(&mut self) {
861 if self.operation == sys::ZX_HANDLE_OP_MOVE {
863 unsafe { drop(NullableHandle::from_raw(self.handle)) };
864 }
865 }
866}
867
868#[derive(Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
872#[repr(C)]
873pub struct HandleInfo {
874 pub handle: NullableHandle,
875 pub object_type: ObjectType,
876 pub rights: Rights,
877
878 pub(crate) _unused: u32,
880}
881
882static_assertions::assert_eq_size!(HandleInfo, sys::zx_handle_info_t);
883static_assertions::const_assert_eq!(
884 std::mem::offset_of!(HandleInfo, handle),
885 std::mem::offset_of!(sys::zx_handle_info_t, handle)
886);
887static_assertions::const_assert_eq!(
888 std::mem::offset_of!(HandleInfo, object_type),
889 std::mem::offset_of!(sys::zx_handle_info_t, ty)
890);
891static_assertions::const_assert_eq!(
892 std::mem::offset_of!(HandleInfo, rights),
893 std::mem::offset_of!(sys::zx_handle_info_t, rights)
894);
895static_assertions::const_assert_eq!(
896 std::mem::offset_of!(HandleInfo, _unused),
897 std::mem::offset_of!(sys::zx_handle_info_t, unused)
898);
899
900impl HandleInfo {
901 pub const fn new(handle: NullableHandle, object_type: ObjectType, rights: Rights) -> Self {
903 Self { handle, object_type, rights, _unused: 0 }
904 }
905
906 pub const unsafe fn from_raw(raw: sys::zx_handle_info_t) -> HandleInfo {
914 HandleInfo::new(
915 unsafe { NullableHandle::from_raw(raw.handle) },
917 ObjectType(raw.ty),
918 Rights::from_bits_retain(raw.rights),
919 )
920 }
921}
922
923#[cfg(test)]
924mod tests {
925 use super::*;
926 use zx::{
929 AsHandleRef, Channel, HandleBased, HandleDisposition, HandleInfo, HandleOp, Name,
930 NullableHandle, ObjectType, Rights, Vmo,
931 };
932 use zx_sys as sys;
933
934 #[test]
935 fn into_raw() {
936 let vmo = Vmo::create(1).unwrap();
937 let h = vmo.into_raw();
938 let vmo2 = Vmo::from(unsafe { NullableHandle::from_raw(h) });
939 assert!(vmo2.write(b"1", 0).is_ok());
940 }
941
942 #[test]
943 fn check_raw_valid() {
944 assert!(Handle::check_raw_valid(sys::ZX_HANDLE_INVALID).is_err());
945 let vmo = Vmo::create(1).unwrap();
946 let vmo_raw = vmo.raw_handle();
947 assert!(Handle::check_raw_valid(vmo_raw).is_ok());
948 drop(vmo);
949 assert!(Handle::check_raw_valid(vmo_raw).is_err());
950 }
951
952 #[test]
954 fn duplicate() {
955 let hello_length: usize = 5;
956
957 let vmo = Vmo::create(hello_length as u64).unwrap();
959 assert!(vmo.write(b"hello", 0).is_ok());
960
961 let readonly_vmo = vmo.duplicate_handle(Rights::READ).unwrap();
963 let mut read_vec = vec![0; hello_length];
965 assert!(readonly_vmo.read(&mut read_vec, 0).is_ok());
966 assert_eq!(read_vec, b"hello");
967 assert_eq!(readonly_vmo.write(b"", 0), Err(Status::ACCESS_DENIED));
968
969 assert!(vmo.write(b"bye", 0).is_ok());
971 assert!(readonly_vmo.read(&mut read_vec, 0).is_ok());
972 assert_eq!(read_vec, b"byelo");
973 }
974
975 #[test]
977 fn replace() {
978 let hello_length: usize = 5;
979
980 let vmo = Vmo::create(hello_length as u64).unwrap();
982 assert!(vmo.write(b"hello", 0).is_ok());
983
984 let readonly_vmo = vmo.replace_handle(Rights::READ).unwrap();
986 let mut read_vec = vec![0; hello_length];
988 assert!(readonly_vmo.read(&mut read_vec, 0).is_ok());
989 assert_eq!(read_vec, b"hello");
990 assert_eq!(readonly_vmo.write(b"", 0), Err(Status::ACCESS_DENIED));
991 }
992
993 #[test]
994 fn set_get_name() {
995 let vmo = Vmo::create(1).unwrap();
997 let short_name = Name::new("v").unwrap();
998 assert!(vmo.set_name(&short_name).is_ok());
999 assert_eq!(vmo.get_name().unwrap(), short_name);
1000 }
1001
1002 #[test]
1003 fn set_get_max_len_name() {
1004 let vmo = Vmo::create(1).unwrap();
1005 let max_len_name = Name::new("a_great_maximum_length_vmo_name").unwrap(); assert!(vmo.set_name(&max_len_name).is_ok());
1007 assert_eq!(vmo.get_name().unwrap(), max_len_name);
1008 }
1009
1010 #[test]
1011 fn basic_info_channel() {
1012 let (side1, side2) = Channel::create();
1013 let info1 = side1.basic_info().expect("side1 basic_info failed");
1014 let info2 = side2.basic_info().expect("side2 basic_info failed");
1015
1016 assert_eq!(info1.koid, info2.related_koid);
1017 assert_eq!(info2.koid, info1.related_koid);
1018
1019 for info in &[info1, info2] {
1020 assert!(info.koid.raw_koid() >= sys::ZX_KOID_FIRST);
1021 assert_eq!(info.object_type, ObjectType::CHANNEL);
1022 assert!(info.rights.contains(Rights::READ | Rights::WRITE | Rights::WAIT));
1023 }
1024
1025 let side1_repl = side1.replace_handle(Rights::READ).expect("side1 replace_handle failed");
1026 let info1_repl = side1_repl.basic_info().expect("side1_repl basic_info failed");
1027 assert_eq!(info1_repl.koid, info1.koid);
1028 assert_eq!(info1_repl.rights, Rights::READ);
1029 }
1030
1031 #[test]
1032 fn basic_info_vmar() {
1033 let root_vmar = fuchsia_runtime::vmar_root_self();
1035 let info = root_vmar.basic_info().expect("vmar basic_info failed");
1036 assert_eq!(info.object_type, ObjectType::VMAR);
1037 assert!(!info.rights.contains(Rights::WAIT));
1038 }
1039
1040 #[test]
1041 fn count_info() {
1042 let vmo0 = Vmo::create(1).unwrap();
1043 let count_info = vmo0.count_info().expect("vmo0 count_info failed");
1044 assert_eq!(count_info.handle_count, 1);
1045
1046 let vmo1 = vmo0.duplicate_handle(Rights::SAME_RIGHTS).expect("vmo duplicate_handle failed");
1047 let count_info = vmo1.count_info().expect("vmo1 count_info failed");
1048 assert_eq!(count_info.handle_count, 2);
1049 }
1050
1051 #[test]
1052 fn raw_handle_disposition() {
1053 const RAW_HANDLE: sys::zx_handle_t = 1;
1054 let hd = HandleDisposition::new(
1055 HandleOp::Move(unsafe { NullableHandle::from_raw(RAW_HANDLE) }),
1056 ObjectType::VMO,
1057 Rights::EXECUTE,
1058 Status::OK,
1059 );
1060 let raw_hd = hd.into_raw();
1061 assert_eq!(raw_hd.operation, sys::ZX_HANDLE_OP_MOVE);
1062 assert_eq!(raw_hd.handle, RAW_HANDLE);
1063 assert_eq!(raw_hd.rights, sys::ZX_RIGHT_EXECUTE);
1064 assert_eq!(raw_hd.type_, sys::ZX_OBJ_TYPE_VMO);
1065 assert_eq!(raw_hd.result, sys::ZX_OK);
1066 }
1067
1068 #[test]
1069 fn regression_nullable_handle_into_raw_recursion() {
1070 let h = NullableHandle::invalid();
1071 assert_eq!(h.into_raw(), sys::ZX_HANDLE_INVALID);
1073
1074 let vmo = Vmo::create(1).unwrap();
1075 let raw = vmo.raw_handle();
1076 let h = vmo.into_handle();
1077 assert_eq!(h.into_raw(), raw);
1079 }
1080
1081 #[test]
1082 fn handle_info_from_raw() {
1083 const RAW_HANDLE: sys::zx_handle_t = 1;
1084 let raw_hi = sys::zx_handle_info_t {
1085 handle: RAW_HANDLE,
1086 ty: sys::ZX_OBJ_TYPE_VMO,
1087 rights: sys::ZX_RIGHT_EXECUTE,
1088 unused: 128,
1089 };
1090 let hi = unsafe { HandleInfo::from_raw(raw_hi) };
1091 assert_eq!(hi.handle.into_raw(), RAW_HANDLE);
1092 assert_eq!(hi.object_type, ObjectType::VMO);
1093 assert_eq!(hi.rights, Rights::EXECUTE);
1094 }
1095
1096 #[test]
1097 fn basic_peer_closed() {
1098 let (lhs, rhs) = crate::EventPair::create();
1099 assert!(!lhs.is_closed().unwrap());
1100 assert!(!rhs.is_closed().unwrap());
1101 drop(rhs);
1102 assert!(lhs.is_closed().unwrap());
1103 }
1104}