1use crate::{
8 object_get_info_single, object_get_property, object_set_property, ok, sys, MonotonicInstant,
9 Name, ObjectQuery, Port, Property, PropertyQuery, Rights, Signals, Status, Topic,
10 WaitAsyncOpts,
11};
12use std::marker::PhantomData;
13use std::mem::{self, ManuallyDrop};
14
15#[derive(
16 Debug,
17 Copy,
18 Clone,
19 Eq,
20 PartialEq,
21 Ord,
22 PartialOrd,
23 Hash,
24 zerocopy::FromBytes,
25 zerocopy::KnownLayout,
26 zerocopy::Immutable,
27)]
28#[repr(transparent)]
29pub struct Koid(sys::zx_koid_t);
30
31impl Koid {
32 pub fn from_raw(raw: sys::zx_koid_t) -> Koid {
33 Koid(raw)
34 }
35
36 pub fn raw_koid(&self) -> sys::zx_koid_t {
37 self.0
38 }
39}
40
41#[derive(Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
53#[repr(transparent)]
54pub struct Handle(sys::zx_handle_t);
55
56impl AsHandleRef for Handle {
57 fn as_handle_ref(&self) -> HandleRef<'_> {
58 Unowned { inner: ManuallyDrop::new(Handle(self.0)), marker: PhantomData }
59 }
60}
61
62impl HandleBased for Handle {}
63
64impl Drop for Handle {
65 fn drop(&mut self) {
66 if self.0 != sys::ZX_HANDLE_INVALID {
67 unsafe { sys::zx_handle_close(self.0) };
68 }
69 }
70}
71
72impl Handle {
73 #[inline(always)]
75 pub const fn invalid() -> Handle {
76 Handle(sys::ZX_HANDLE_INVALID)
77 }
78
79 pub const unsafe fn from_raw(raw: sys::zx_handle_t) -> Handle {
91 Handle(raw)
92 }
93
94 pub fn is_invalid(&self) -> bool {
95 self.0 == sys::ZX_HANDLE_INVALID
96 }
97
98 pub fn replace(self, rights: Rights) -> Result<Handle, Status> {
99 let handle = self.0;
100 let mut out = 0;
101 let status = unsafe { sys::zx_handle_replace(handle, rights.bits(), &mut out) };
102 std::mem::forget(self);
104 ok(status).map(|()| Handle(out))
105 }
106}
107
108struct NameProperty();
109unsafe impl PropertyQuery for NameProperty {
110 const PROPERTY: Property = Property::NAME;
111 type PropTy = Name;
114}
115
116#[derive(Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
120#[repr(transparent)]
121pub struct Unowned<'a, T: Into<Handle>> {
122 inner: ManuallyDrop<T>,
123 marker: PhantomData<&'a T>,
124}
125
126impl<T: Into<Handle>> Drop for Unowned<'_, T> {
127 fn drop(&mut self) {
128 let handle: Handle = unsafe { ManuallyDrop::take(&mut self.inner).into() };
130 mem::forget(handle);
131 }
132}
133
134impl<'a, T: Into<Handle>> ::std::ops::Deref for Unowned<'a, T> {
135 type Target = T;
136
137 fn deref(&self) -> &Self::Target {
138 &*self.inner
139 }
140}
141
142impl<T: HandleBased> Clone for Unowned<'_, T> {
143 fn clone(&self) -> Self {
144 unsafe { Self::from_raw_handle(self.inner.as_handle_ref().raw_handle()) }
145 }
146}
147
148pub type HandleRef<'a> = Unowned<'a, Handle>;
149
150impl<'a, T: Into<Handle>> Unowned<'a, T> {
151 pub fn new<U: AsHandleRef + From<Handle>>(inner: &'a U) -> Self
155 where
156 T: From<U>,
157 {
158 Unowned {
161 inner: ManuallyDrop::new(T::from(U::from(unsafe {
162 Handle::from_raw(inner.as_handle_ref().raw_handle())
163 }))),
164 marker: PhantomData,
165 }
166 }
167}
168
169impl<'a, T: HandleBased> Unowned<'a, T> {
170 pub unsafe fn from_raw_handle(handle: sys::zx_handle_t) -> Self {
182 Unowned { inner: ManuallyDrop::new(T::from(Handle::from_raw(handle))), marker: PhantomData }
183 }
184
185 pub fn raw_handle(&self) -> sys::zx_handle_t {
186 self.inner.raw_handle()
187 }
188
189 pub fn duplicate(&self, rights: Rights) -> Result<T, Status> {
190 let mut out = 0;
191 let status =
192 unsafe { sys::zx_handle_duplicate(self.raw_handle(), rights.bits(), &mut out) };
193 ok(status).map(|()| T::from(Handle(out)))
194 }
195
196 pub fn signal(&self, clear_mask: Signals, set_mask: Signals) -> Result<(), Status> {
197 let status =
198 unsafe { sys::zx_object_signal(self.raw_handle(), clear_mask.bits(), set_mask.bits()) };
199 ok(status)
200 }
201
202 pub fn wait(&self, signals: Signals, deadline: MonotonicInstant) -> Result<Signals, Status> {
203 let mut pending = Signals::empty().bits();
204 let status = unsafe {
205 sys::zx_object_wait_one(
206 self.raw_handle(),
207 signals.bits(),
208 deadline.into_nanos(),
209 &mut pending,
210 )
211 };
212 ok(status).map(|()| Signals::from_bits_truncate(pending))
213 }
214
215 pub fn wait_async(
216 &self,
217 port: &Port,
218 key: u64,
219 signals: Signals,
220 options: WaitAsyncOpts,
221 ) -> Result<(), Status> {
222 let status = unsafe {
223 sys::zx_object_wait_async(
224 self.raw_handle(),
225 port.raw_handle(),
226 key,
227 signals.bits(),
228 options.bits(),
229 )
230 };
231 ok(status)
232 }
233}
234
235impl<'a> Unowned<'a, Handle> {
236 pub fn cast<T: HandleBased>(self) -> Unowned<'a, T> {
238 unsafe { Unowned::from_raw_handle(self.raw_handle()) }
240 }
241}
242
243pub trait AsHandleRef {
245 fn as_handle_ref(&self) -> HandleRef<'_>;
248
249 fn raw_handle(&self) -> sys::zx_handle_t {
253 self.as_handle_ref().inner.0
254 }
255
256 fn signal_handle(&self, clear_mask: Signals, set_mask: Signals) -> Result<(), Status> {
260 self.as_handle_ref().signal(clear_mask, set_mask)
261 }
262
263 fn wait_handle(&self, signals: Signals, deadline: MonotonicInstant) -> Result<Signals, Status> {
267 self.as_handle_ref().wait(signals, deadline)
268 }
269
270 fn wait_async_handle(
274 &self,
275 port: &Port,
276 key: u64,
277 signals: Signals,
278 options: WaitAsyncOpts,
279 ) -> Result<(), Status> {
280 self.as_handle_ref().wait_async(port, key, signals, options)
281 }
282
283 fn get_name(&self) -> Result<Name, Status> {
289 object_get_property::<NameProperty>(self.as_handle_ref())
290 }
291
292 fn set_name(&self, name: &Name) -> Result<(), Status> {
302 object_set_property::<NameProperty>(self.as_handle_ref(), &name)
303 }
304
305 fn basic_info(&self) -> Result<HandleBasicInfo, Status> {
309 Ok(HandleBasicInfo::from(object_get_info_single::<HandleBasicInfoQuery>(
310 self.as_handle_ref(),
311 )?))
312 }
313
314 fn count_info(&self) -> Result<HandleCountInfo, Status> {
318 Ok(HandleCountInfo::from(object_get_info_single::<HandleCountInfoQuery>(
319 self.as_handle_ref(),
320 )?))
321 }
322
323 fn get_koid(&self) -> Result<Koid, Status> {
325 self.basic_info().map(|info| info.koid)
326 }
327}
328
329impl<'a, T: HandleBased> AsHandleRef for Unowned<'a, T> {
330 fn as_handle_ref(&self) -> HandleRef<'_> {
331 Unowned { inner: ManuallyDrop::new(Handle(self.raw_handle())), marker: PhantomData }
332 }
333}
334
335impl<T: AsHandleRef> AsHandleRef for &T {
336 fn as_handle_ref(&self) -> HandleRef<'_> {
337 (*self).as_handle_ref()
338 }
339}
340
341pub trait HandleBased: AsHandleRef + From<Handle> + Into<Handle> {
349 fn duplicate_handle(&self, rights: Rights) -> Result<Self, Status> {
353 self.as_handle_ref().duplicate(rights).map(|handle| Self::from(handle))
354 }
355
356 fn replace_handle(self, rights: Rights) -> Result<Self, Status> {
361 <Self as Into<Handle>>::into(self).replace(rights).map(|handle| Self::from(handle))
362 }
363
364 fn into_handle(self) -> Handle {
368 self.into()
369 }
370
371 fn into_raw(self) -> sys::zx_handle_t {
375 let h = self.into_handle();
376 let r = h.0;
377 mem::forget(h);
378 r
379 }
380
381 fn from_handle(handle: Handle) -> Self {
385 Self::from(handle)
386 }
387
388 fn into_handle_based<H: HandleBased>(self) -> H {
390 H::from_handle(self.into_handle())
391 }
392
393 fn from_handle_based<H: HandleBased>(h: H) -> Self {
396 Self::from_handle(h.into_handle())
397 }
398
399 fn is_invalid_handle(&self) -> bool {
400 self.as_handle_ref().is_invalid()
401 }
402}
403
404pub trait Peered: HandleBased {
406 fn signal_peer(&self, clear_mask: Signals, set_mask: Signals) -> Result<(), Status> {
411 let handle = self.raw_handle();
412 let status =
413 unsafe { sys::zx_object_signal_peer(handle, clear_mask.bits(), set_mask.bits()) };
414 ok(status)
415 }
416
417 fn is_closed(&self) -> Result<bool, Status> {
425 match self.wait_handle(Signals::OBJECT_PEER_CLOSED, MonotonicInstant::INFINITE_PAST) {
426 Ok(signals) => Ok(signals.contains(Signals::OBJECT_PEER_CLOSED)),
427 Err(Status::TIMED_OUT) => Ok(false),
428 Err(e) => Err(e),
429 }
430 }
431}
432
433#[derive(Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash)]
435#[repr(transparent)]
436pub struct ObjectType(sys::zx_obj_type_t);
437
438assoc_values!(ObjectType, [
439 NONE = sys::ZX_OBJ_TYPE_NONE;
440 PROCESS = sys::ZX_OBJ_TYPE_PROCESS;
441 THREAD = sys::ZX_OBJ_TYPE_THREAD;
442 VMO = sys::ZX_OBJ_TYPE_VMO;
443 CHANNEL = sys::ZX_OBJ_TYPE_CHANNEL;
444 EVENT = sys::ZX_OBJ_TYPE_EVENT;
445 PORT = sys::ZX_OBJ_TYPE_PORT;
446 INTERRUPT = sys::ZX_OBJ_TYPE_INTERRUPT;
447 PCI_DEVICE = sys::ZX_OBJ_TYPE_PCI_DEVICE;
448 DEBUGLOG = sys::ZX_OBJ_TYPE_DEBUGLOG;
449 SOCKET = sys::ZX_OBJ_TYPE_SOCKET;
450 RESOURCE = sys::ZX_OBJ_TYPE_RESOURCE;
451 EVENTPAIR = sys::ZX_OBJ_TYPE_EVENTPAIR;
452 JOB = sys::ZX_OBJ_TYPE_JOB;
453 VMAR = sys::ZX_OBJ_TYPE_VMAR;
454 FIFO = sys::ZX_OBJ_TYPE_FIFO;
455 GUEST = sys::ZX_OBJ_TYPE_GUEST;
456 VCPU = sys::ZX_OBJ_TYPE_VCPU;
457 TIMER = sys::ZX_OBJ_TYPE_TIMER;
458 IOMMU = sys::ZX_OBJ_TYPE_IOMMU;
459 BTI = sys::ZX_OBJ_TYPE_BTI;
460 PROFILE = sys::ZX_OBJ_TYPE_PROFILE;
461 PMT = sys::ZX_OBJ_TYPE_PMT;
462 SUSPEND_TOKEN = sys::ZX_OBJ_TYPE_SUSPEND_TOKEN;
463 PAGER = sys::ZX_OBJ_TYPE_PAGER;
464 EXCEPTION = sys::ZX_OBJ_TYPE_EXCEPTION;
465 CLOCK = sys::ZX_OBJ_TYPE_CLOCK;
466 STREAM = sys::ZX_OBJ_TYPE_STREAM;
467 MSI = sys::ZX_OBJ_TYPE_MSI;
468 IOB = sys::ZX_OBJ_TYPE_IOB;
469 COUNTER = sys::ZX_OBJ_TYPE_COUNTER;
470]);
471
472impl ObjectType {
473 pub const fn from_raw(raw: sys::zx_obj_type_t) -> Self {
475 Self(raw)
476 }
477
478 pub const fn into_raw(self) -> sys::zx_obj_type_t {
480 self.0
481 }
482}
483
484#[derive(Debug, Copy, Clone, Eq, PartialEq)]
488pub struct HandleBasicInfo {
489 pub koid: Koid,
490 pub rights: Rights,
491 pub object_type: ObjectType,
492 pub related_koid: Koid,
493}
494
495impl Default for HandleBasicInfo {
496 fn default() -> Self {
497 Self::from(sys::zx_info_handle_basic_t::default())
498 }
499}
500
501impl From<sys::zx_info_handle_basic_t> for HandleBasicInfo {
502 fn from(info: sys::zx_info_handle_basic_t) -> Self {
503 let sys::zx_info_handle_basic_t { koid, rights, type_, related_koid, .. } = info;
504
505 HandleBasicInfo {
508 koid: Koid(koid),
509 rights: Rights::from_bits_truncate(rights),
510 object_type: ObjectType(type_),
511 related_koid: Koid(related_koid),
512 }
513 }
514}
515
516struct HandleBasicInfoQuery;
519unsafe impl ObjectQuery for HandleBasicInfoQuery {
520 const TOPIC: Topic = Topic::HANDLE_BASIC;
521 type InfoTy = sys::zx_info_handle_basic_t;
522}
523
524sys::zx_info_handle_count_t!(HandleCountInfo);
525
526impl From<sys::zx_info_handle_count_t> for HandleCountInfo {
527 fn from(sys::zx_info_handle_count_t { handle_count }: sys::zx_info_handle_count_t) -> Self {
528 HandleCountInfo { handle_count }
529 }
530}
531
532struct HandleCountInfoQuery;
535unsafe impl ObjectQuery for HandleCountInfoQuery {
536 const TOPIC: Topic = Topic::HANDLE_COUNT;
537 type InfoTy = sys::zx_info_handle_count_t;
538}
539
540#[derive(Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
542pub enum HandleOp<'a> {
543 Move(Handle),
544 Duplicate(HandleRef<'a>),
545}
546
547#[derive(Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
549#[repr(C)]
550pub struct HandleDisposition<'a> {
551 operation: sys::zx_handle_op_t,
553 handle: sys::zx_handle_t,
555 _handle_lifetime: std::marker::PhantomData<&'a ()>,
557
558 pub object_type: ObjectType,
559 pub rights: Rights,
560 pub result: Status,
561}
562
563static_assertions::assert_eq_size!(HandleDisposition<'_>, sys::zx_handle_disposition_t);
564static_assertions::const_assert_eq!(
565 std::mem::offset_of!(HandleDisposition<'_>, operation),
566 std::mem::offset_of!(sys::zx_handle_disposition_t, operation)
567);
568static_assertions::const_assert_eq!(
569 std::mem::offset_of!(HandleDisposition<'_>, handle),
570 std::mem::offset_of!(sys::zx_handle_disposition_t, handle)
571);
572static_assertions::const_assert_eq!(
573 std::mem::offset_of!(HandleDisposition<'_>, object_type),
574 std::mem::offset_of!(sys::zx_handle_disposition_t, type_)
575);
576static_assertions::const_assert_eq!(
577 std::mem::offset_of!(HandleDisposition<'_>, rights),
578 std::mem::offset_of!(sys::zx_handle_disposition_t, rights)
579);
580static_assertions::const_assert_eq!(
581 std::mem::offset_of!(HandleDisposition<'_>, result),
582 std::mem::offset_of!(sys::zx_handle_disposition_t, result)
583);
584
585impl<'a> HandleDisposition<'a> {
586 #[inline]
587 pub fn new(
588 handle_op: HandleOp<'a>,
589 object_type: ObjectType,
590 rights: Rights,
591 status: Status,
592 ) -> Self {
593 let (operation, handle) = match handle_op {
594 HandleOp::Move(h) => (sys::ZX_HANDLE_OP_MOVE, h.into_raw()),
595 HandleOp::Duplicate(h) => (sys::ZX_HANDLE_OP_DUPLICATE, h.raw_handle()),
596 };
597
598 Self {
599 operation,
600 handle,
601 _handle_lifetime: std::marker::PhantomData,
602 object_type,
603 rights: rights,
604 result: status,
605 }
606 }
607
608 pub fn raw_handle(&self) -> sys::zx_handle_t {
609 self.handle
610 }
611
612 pub fn is_move(&self) -> bool {
613 self.operation == sys::ZX_HANDLE_OP_MOVE
614 }
615
616 pub fn is_duplicate(&self) -> bool {
617 self.operation == sys::ZX_HANDLE_OP_DUPLICATE
618 }
619
620 pub fn take_op(&mut self) -> HandleOp<'a> {
621 match self.operation {
622 sys::ZX_HANDLE_OP_MOVE => {
623 HandleOp::Move(unsafe {
626 Handle::from_raw(std::mem::replace(&mut self.handle, sys::ZX_HANDLE_INVALID))
627 })
628 }
629 sys::ZX_HANDLE_OP_DUPLICATE => {
630 HandleOp::Duplicate(unsafe { Unowned::from_raw_handle(self.handle) })
633 }
634 _ => unreachable!(),
635 }
636 }
637
638 pub fn into_raw(mut self) -> sys::zx_handle_disposition_t {
639 match self.take_op() {
640 HandleOp::Move(mut handle) => sys::zx_handle_disposition_t {
641 operation: sys::ZX_HANDLE_OP_MOVE,
642 handle: std::mem::replace(&mut handle, Handle::invalid()).into_raw(),
643 type_: self.object_type.0,
644 rights: self.rights.bits(),
645 result: self.result.into_raw(),
646 },
647 HandleOp::Duplicate(handle_ref) => sys::zx_handle_disposition_t {
648 operation: sys::ZX_HANDLE_OP_DUPLICATE,
649 handle: handle_ref.raw_handle(),
650 type_: self.object_type.0,
651 rights: self.rights.bits(),
652 result: self.result.into_raw(),
653 },
654 }
655 }
656}
657
658impl<'a> Drop for HandleDisposition<'a> {
659 fn drop(&mut self) {
660 if self.operation == sys::ZX_HANDLE_OP_MOVE {
662 unsafe { drop(Handle::from_raw(self.handle)) };
663 }
664 }
665}
666
667#[derive(Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
671#[repr(C)]
672pub struct HandleInfo {
673 pub handle: Handle,
674 pub object_type: ObjectType,
675 pub rights: Rights,
676
677 pub(crate) _unused: u32,
679}
680
681static_assertions::assert_eq_size!(HandleInfo, sys::zx_handle_info_t);
682static_assertions::const_assert_eq!(
683 std::mem::offset_of!(HandleInfo, handle),
684 std::mem::offset_of!(sys::zx_handle_info_t, handle)
685);
686static_assertions::const_assert_eq!(
687 std::mem::offset_of!(HandleInfo, object_type),
688 std::mem::offset_of!(sys::zx_handle_info_t, ty)
689);
690static_assertions::const_assert_eq!(
691 std::mem::offset_of!(HandleInfo, rights),
692 std::mem::offset_of!(sys::zx_handle_info_t, rights)
693);
694static_assertions::const_assert_eq!(
695 std::mem::offset_of!(HandleInfo, _unused),
696 std::mem::offset_of!(sys::zx_handle_info_t, unused)
697);
698
699impl HandleInfo {
700 pub const fn new(handle: Handle, object_type: ObjectType, rights: Rights) -> Self {
702 Self { handle, object_type, rights, _unused: 0 }
703 }
704
705 pub const unsafe fn from_raw(raw: sys::zx_handle_info_t) -> HandleInfo {
713 HandleInfo::new(
714 unsafe { Handle::from_raw(raw.handle) },
716 ObjectType(raw.ty),
717 Rights::from_bits_retain(raw.rights),
718 )
719 }
720}
721
722#[cfg(test)]
723mod tests {
724 use super::*;
725 use zx::{
728 AsHandleRef, Channel, Handle, HandleBased, HandleDisposition, HandleInfo, HandleOp, Name,
729 ObjectType, Rights, Vmo,
730 };
731 use zx_sys as sys;
732
733 #[test]
734 fn into_raw() {
735 let vmo = Vmo::create(1).unwrap();
736 let h = vmo.into_raw();
737 let vmo2 = Vmo::from(unsafe { Handle::from_raw(h) });
738 assert!(vmo2.write(b"1", 0).is_ok());
739 }
740
741 #[test]
743 fn duplicate() {
744 let hello_length: usize = 5;
745
746 let vmo = Vmo::create(hello_length as u64).unwrap();
748 assert!(vmo.write(b"hello", 0).is_ok());
749
750 let readonly_vmo = vmo.duplicate_handle(Rights::READ).unwrap();
752 let mut read_vec = vec![0; hello_length];
754 assert!(readonly_vmo.read(&mut read_vec, 0).is_ok());
755 assert_eq!(read_vec, b"hello");
756 assert_eq!(readonly_vmo.write(b"", 0), Err(Status::ACCESS_DENIED));
757
758 assert!(vmo.write(b"bye", 0).is_ok());
760 assert!(readonly_vmo.read(&mut read_vec, 0).is_ok());
761 assert_eq!(read_vec, b"byelo");
762 }
763
764 #[test]
766 fn replace() {
767 let hello_length: usize = 5;
768
769 let vmo = Vmo::create(hello_length as u64).unwrap();
771 assert!(vmo.write(b"hello", 0).is_ok());
772
773 let readonly_vmo = vmo.replace_handle(Rights::READ).unwrap();
775 let mut read_vec = vec![0; hello_length];
777 assert!(readonly_vmo.read(&mut read_vec, 0).is_ok());
778 assert_eq!(read_vec, b"hello");
779 assert_eq!(readonly_vmo.write(b"", 0), Err(Status::ACCESS_DENIED));
780 }
781
782 #[test]
783 fn set_get_name() {
784 let vmo = Vmo::create(1).unwrap();
786 let short_name = Name::new("v").unwrap();
787 assert!(vmo.set_name(&short_name).is_ok());
788 assert_eq!(vmo.get_name().unwrap(), short_name);
789 }
790
791 #[test]
792 fn set_get_max_len_name() {
793 let vmo = Vmo::create(1).unwrap();
794 let max_len_name = Name::new("a_great_maximum_length_vmo_name").unwrap(); assert!(vmo.set_name(&max_len_name).is_ok());
796 assert_eq!(vmo.get_name().unwrap(), max_len_name);
797 }
798
799 #[test]
800 fn basic_info_channel() {
801 let (side1, side2) = Channel::create();
802 let info1 = side1.basic_info().expect("side1 basic_info failed");
803 let info2 = side2.basic_info().expect("side2 basic_info failed");
804
805 assert_eq!(info1.koid, info2.related_koid);
806 assert_eq!(info2.koid, info1.related_koid);
807
808 for info in &[info1, info2] {
809 assert!(info.koid.raw_koid() >= sys::ZX_KOID_FIRST);
810 assert_eq!(info.object_type, ObjectType::CHANNEL);
811 assert!(info.rights.contains(Rights::READ | Rights::WRITE | Rights::WAIT));
812 }
813
814 let side1_repl = side1.replace_handle(Rights::READ).expect("side1 replace_handle failed");
815 let info1_repl = side1_repl.basic_info().expect("side1_repl basic_info failed");
816 assert_eq!(info1_repl.koid, info1.koid);
817 assert_eq!(info1_repl.rights, Rights::READ);
818 }
819
820 #[test]
821 fn basic_info_vmar() {
822 let root_vmar = fuchsia_runtime::vmar_root_self();
824 let info = root_vmar.basic_info().expect("vmar basic_info failed");
825 assert_eq!(info.object_type, ObjectType::VMAR);
826 assert!(!info.rights.contains(Rights::WAIT));
827 }
828
829 #[test]
830 fn count_info() {
831 let vmo0 = Vmo::create(1).unwrap();
832 let count_info = vmo0.count_info().expect("vmo0 count_info failed");
833 assert_eq!(count_info.handle_count, 1);
834
835 let vmo1 = vmo0.duplicate_handle(Rights::SAME_RIGHTS).expect("vmo duplicate_handle failed");
836 let count_info = vmo1.count_info().expect("vmo1 count_info failed");
837 assert_eq!(count_info.handle_count, 2);
838 }
839
840 #[test]
841 fn raw_handle_disposition() {
842 const RAW_HANDLE: sys::zx_handle_t = 1;
843 let hd = HandleDisposition::new(
844 HandleOp::Move(unsafe { Handle::from_raw(RAW_HANDLE) }),
845 ObjectType::VMO,
846 Rights::EXECUTE,
847 Status::OK,
848 );
849 let raw_hd = hd.into_raw();
850 assert_eq!(raw_hd.operation, sys::ZX_HANDLE_OP_MOVE);
851 assert_eq!(raw_hd.handle, RAW_HANDLE);
852 assert_eq!(raw_hd.rights, sys::ZX_RIGHT_EXECUTE);
853 assert_eq!(raw_hd.type_, sys::ZX_OBJ_TYPE_VMO);
854 assert_eq!(raw_hd.result, sys::ZX_OK);
855 }
856
857 #[test]
858 fn handle_info_from_raw() {
859 const RAW_HANDLE: sys::zx_handle_t = 1;
860 let raw_hi = sys::zx_handle_info_t {
861 handle: RAW_HANDLE,
862 ty: sys::ZX_OBJ_TYPE_VMO,
863 rights: sys::ZX_RIGHT_EXECUTE,
864 unused: 128,
865 };
866 let hi = unsafe { HandleInfo::from_raw(raw_hi) };
867 assert_eq!(hi.handle.into_raw(), RAW_HANDLE);
868 assert_eq!(hi.object_type, ObjectType::VMO);
869 assert_eq!(hi.rights, Rights::EXECUTE);
870 }
871
872 #[test]
873 fn basic_peer_closed() {
874 let (lhs, rhs) = crate::EventPair::create();
875 assert!(!lhs.is_closed().unwrap());
876 assert!(!rhs.is_closed().unwrap());
877 drop(rhs);
878 assert!(lhs.is_closed().unwrap());
879 }
880}