1use crate::{
8 Koid, MonotonicInstant, Name, ObjectQuery, ObjectType, Port, Property, PropertyQuery, Rights,
9 Signals, Status, Topic, WaitAsyncOpts, object_get_info_single, object_get_property,
10 object_set_property, ok, 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(Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
121#[repr(transparent)]
122pub struct NullableHandle(Option<Handle>);
123
124impl AsHandleRef for NullableHandle {
125 fn as_handle_ref(&self) -> HandleRef<'_> {
126 if let Some(inner) = &self.0 {
127 unsafe { Unowned::from_raw_handle(inner.raw_handle()) }
129 } else {
130 unsafe { Unowned::from_raw_handle(sys::ZX_HANDLE_INVALID) }
132 }
133 }
134
135 fn raw_handle(&self) -> sys::zx_handle_t {
136 self.0.as_ref().map(|h| h.raw_handle()).unwrap_or(sys::ZX_HANDLE_INVALID)
137 }
138}
139
140impl HandleBased for NullableHandle {
141 fn into_raw(self) -> sys::zx_handle_t {
142 if let Some(inner) = self.0 { inner.into_raw() } else { sys::ZX_HANDLE_INVALID }
143 }
144}
145
146impl NullableHandle {
147 #[inline(always)]
149 pub const fn invalid() -> Self {
150 Self(None)
151 }
152
153 pub const unsafe fn from_raw(raw: sys::zx_handle_t) -> Self {
165 if let Some(inner) = NonZeroU32::new(raw) { Self(Some(Handle(inner))) } else { Self(None) }
169 }
170
171 pub fn is_invalid(&self) -> bool {
172 self.0.is_none()
173 }
174
175 pub fn replace(mut self, rights: Rights) -> Result<Self, Status> {
176 if let Some(inner) = self.0.take() {
177 let inner = inner.replace(rights)?;
178 Ok(Self(Some(inner)))
179 } else {
180 Ok(Self(None))
181 }
182 }
183}
184struct NameProperty();
185unsafe impl PropertyQuery for NameProperty {
186 const PROPERTY: Property = Property::NAME;
187 type PropTy = Name;
190}
191
192#[derive(Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
196#[repr(transparent)]
197pub struct Unowned<'a, T: Into<NullableHandle>> {
198 inner: ManuallyDrop<T>,
199 marker: PhantomData<&'a T>,
200}
201
202impl<T: Into<NullableHandle>> Drop for Unowned<'_, T> {
203 fn drop(&mut self) {
204 let handle: NullableHandle = unsafe { ManuallyDrop::take(&mut self.inner).into() };
206 mem::forget(handle);
207 }
208}
209
210impl<'a, T: Into<NullableHandle>> ::std::ops::Deref for Unowned<'a, T> {
211 type Target = T;
212
213 fn deref(&self) -> &Self::Target {
214 &*self.inner
215 }
216}
217
218impl<T: HandleBased> Clone for Unowned<'_, T> {
219 fn clone(&self) -> Self {
220 unsafe { Self::from_raw_handle(self.inner.as_handle_ref().raw_handle()) }
221 }
222}
223
224pub type HandleRef<'a> = Unowned<'a, NullableHandle>;
225
226impl<'a, T: Into<NullableHandle>> Unowned<'a, T> {
227 pub fn new<U: AsHandleRef + From<NullableHandle>>(inner: &'a U) -> Self
231 where
232 T: From<U>,
233 {
234 Unowned {
237 inner: ManuallyDrop::new(T::from(U::from(unsafe {
238 NullableHandle::from_raw(inner.as_handle_ref().raw_handle())
239 }))),
240 marker: PhantomData,
241 }
242 }
243}
244
245impl<'a, T: HandleBased> Unowned<'a, T> {
246 pub unsafe fn from_raw_handle(handle: sys::zx_handle_t) -> Self {
258 Unowned {
259 inner: ManuallyDrop::new(T::from(unsafe { NullableHandle::from_raw(handle) })),
260 marker: PhantomData,
261 }
262 }
263
264 pub fn raw_handle(&self) -> sys::zx_handle_t {
265 self.inner.raw_handle()
266 }
267
268 pub fn duplicate(&self, rights: Rights) -> Result<T, Status> {
269 let mut out = 0;
270 let status =
272 unsafe { sys::zx_handle_duplicate(self.raw_handle(), rights.bits(), &mut out) };
273 ok(status)?;
274
275 Ok(T::from(unsafe { NullableHandle::from_raw(out) }))
277 }
278
279 pub fn signal(&self, clear_mask: Signals, set_mask: Signals) -> Result<(), Status> {
280 let status =
281 unsafe { sys::zx_object_signal(self.raw_handle(), clear_mask.bits(), set_mask.bits()) };
282 ok(status)
283 }
284
285 pub fn wait(&self, signals: Signals, deadline: MonotonicInstant) -> WaitResult {
286 let mut pending = Signals::empty().bits();
287 let status = unsafe {
288 sys::zx_object_wait_one(
289 self.raw_handle(),
290 signals.bits(),
291 deadline.into_nanos(),
292 &mut pending,
293 )
294 };
295 let signals = Signals::from_bits_truncate(pending);
296 match ok(status) {
297 Ok(()) => WaitResult::Ok(signals),
298 Err(Status::TIMED_OUT) => WaitResult::TimedOut(signals),
299 Err(Status::CANCELED) => WaitResult::Canceled(signals),
300 Err(e) => WaitResult::Err(e),
301 }
302 }
303
304 pub fn wait_async(
305 &self,
306 port: &Port,
307 key: u64,
308 signals: Signals,
309 options: WaitAsyncOpts,
310 ) -> Result<(), Status> {
311 let status = unsafe {
312 sys::zx_object_wait_async(
313 self.raw_handle(),
314 port.raw_handle(),
315 key,
316 signals.bits(),
317 options.bits(),
318 )
319 };
320 ok(status)
321 }
322}
323
324#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
330pub enum WaitResult {
331 Ok(Signals),
333
334 TimedOut(Signals),
338
339 Canceled(Signals),
346
347 Err(Status),
350}
351
352impl WaitResult {
353 pub const fn to_result(self) -> Result<Signals, Status> {
356 match self {
357 WaitResult::Ok(signals) => Ok(signals),
358 WaitResult::TimedOut(_signals) => Err(Status::TIMED_OUT),
359 WaitResult::Canceled(_signals) => Err(Status::CANCELED),
360 WaitResult::Err(status) => Err(status),
361 }
362 }
363
364 #[must_use = "if you intended to assert that this is ok, consider `.unwrap()` instead"]
369 #[inline]
370 pub const fn is_ok(&self) -> bool {
371 self.to_result().is_ok()
372 }
373
374 #[must_use = "if you intended to assert that this is err, consider `.unwrap_err()` instead"]
375 #[inline]
376 pub const fn is_err(&self) -> bool {
377 self.to_result().is_err()
378 }
379
380 #[inline]
381 pub fn map<U, F: FnOnce(Signals) -> U>(self, op: F) -> Result<U, Status> {
382 self.to_result().map(op)
383 }
384
385 #[inline]
386 pub fn map_err<F, O: FnOnce(Status) -> F>(self, op: O) -> Result<Signals, F> {
387 self.to_result().map_err(op)
388 }
389
390 #[inline]
391 #[track_caller]
392 pub fn expect(self, msg: &str) -> Signals {
393 self.to_result().expect(msg)
394 }
395
396 #[inline]
397 #[track_caller]
398 pub fn expect_err(self, msg: &str) -> Status {
399 self.to_result().expect_err(msg)
400 }
401
402 #[inline(always)]
403 #[track_caller]
404 pub fn unwrap(self) -> Signals {
405 self.to_result().unwrap()
406 }
407}
408
409impl<'a> Unowned<'a, NullableHandle> {
410 pub fn cast<T: HandleBased>(self) -> Unowned<'a, T> {
412 unsafe { Unowned::from_raw_handle(self.raw_handle()) }
414 }
415}
416
417pub trait AsHandleRef {
419 fn as_handle_ref(&self) -> HandleRef<'_>;
422
423 fn raw_handle(&self) -> sys::zx_handle_t {
427 self.as_handle_ref().inner.raw_handle()
428 }
429
430 fn signal_handle(&self, clear_mask: Signals, set_mask: Signals) -> Result<(), Status> {
434 self.as_handle_ref().signal(clear_mask, set_mask)
435 }
436
437 fn wait_handle(&self, signals: Signals, deadline: MonotonicInstant) -> WaitResult {
441 self.as_handle_ref().wait(signals, deadline)
442 }
443
444 fn wait_async_handle(
448 &self,
449 port: &Port,
450 key: u64,
451 signals: Signals,
452 options: WaitAsyncOpts,
453 ) -> Result<(), Status> {
454 self.as_handle_ref().wait_async(port, key, signals, options)
455 }
456
457 fn get_name(&self) -> Result<Name, Status> {
463 object_get_property::<NameProperty>(self.as_handle_ref())
464 }
465
466 fn set_name(&self, name: &Name) -> Result<(), Status> {
476 object_set_property::<NameProperty>(self.as_handle_ref(), &name)
477 }
478
479 fn basic_info(&self) -> Result<HandleBasicInfo, Status> {
483 Ok(HandleBasicInfo::from(object_get_info_single::<HandleBasicInfoQuery>(
484 self.as_handle_ref(),
485 )?))
486 }
487
488 fn count_info(&self) -> Result<HandleCountInfo, Status> {
492 Ok(HandleCountInfo::from(object_get_info_single::<HandleCountInfoQuery>(
493 self.as_handle_ref(),
494 )?))
495 }
496
497 fn get_koid(&self) -> Result<Koid, Status> {
499 self.basic_info().map(|info| info.koid)
500 }
501}
502
503impl<'a, T: HandleBased> AsHandleRef for Unowned<'a, T> {
504 fn as_handle_ref(&self) -> HandleRef<'_> {
505 self.inner.as_handle_ref()
506 }
507}
508
509impl<T: AsHandleRef> AsHandleRef for &T {
510 fn as_handle_ref(&self) -> HandleRef<'_> {
511 (*self).as_handle_ref()
512 }
513}
514
515pub trait HandleBased: AsHandleRef + From<NullableHandle> + Into<NullableHandle> {
523 fn duplicate_handle(&self, rights: Rights) -> Result<Self, Status> {
527 self.as_handle_ref().duplicate(rights).map(|handle| Self::from(handle))
528 }
529
530 fn replace_handle(self, rights: Rights) -> Result<Self, Status> {
535 <Self as Into<NullableHandle>>::into(self).replace(rights).map(|handle| Self::from(handle))
536 }
537
538 fn into_handle(self) -> NullableHandle {
542 self.into()
543 }
544
545 fn into_raw(self) -> sys::zx_handle_t {
549 self.into_handle().into_raw()
550 }
551
552 fn from_handle(handle: NullableHandle) -> Self {
556 Self::from(handle)
557 }
558
559 fn into_handle_based<H: HandleBased>(self) -> H {
561 H::from_handle(self.into_handle())
562 }
563
564 fn from_handle_based<H: HandleBased>(h: H) -> Self {
567 Self::from_handle(h.into_handle())
568 }
569
570 fn is_invalid_handle(&self) -> bool {
571 self.as_handle_ref().is_invalid()
572 }
573}
574
575pub trait Peered: HandleBased {
577 fn signal_peer(&self, clear_mask: Signals, set_mask: Signals) -> Result<(), Status> {
582 let handle = self.raw_handle();
583 let status =
584 unsafe { sys::zx_object_signal_peer(handle, clear_mask.bits(), set_mask.bits()) };
585 ok(status)
586 }
587
588 fn is_closed(&self) -> Result<bool, Status> {
596 match self.wait_handle(Signals::OBJECT_PEER_CLOSED, MonotonicInstant::INFINITE_PAST) {
597 WaitResult::Ok(signals) => Ok(signals.contains(Signals::OBJECT_PEER_CLOSED)),
598 WaitResult::TimedOut(_) => Ok(false),
599 WaitResult::Canceled(_) => Err(Status::CANCELED),
600 WaitResult::Err(e) => Err(e),
601 }
602 }
603}
604
605#[derive(Debug, Copy, Clone, Eq, PartialEq)]
609pub struct HandleBasicInfo {
610 pub koid: Koid,
611 pub rights: Rights,
612 pub object_type: ObjectType,
613 pub related_koid: Koid,
614}
615
616impl Default for HandleBasicInfo {
617 fn default() -> Self {
618 Self::from(sys::zx_info_handle_basic_t::default())
619 }
620}
621
622impl From<sys::zx_info_handle_basic_t> for HandleBasicInfo {
623 fn from(info: sys::zx_info_handle_basic_t) -> Self {
624 let sys::zx_info_handle_basic_t { koid, rights, type_, related_koid, .. } = info;
625
626 HandleBasicInfo {
629 koid: Koid::from_raw(koid),
630 rights: Rights::from_bits_truncate(rights),
631 object_type: ObjectType::from_raw(type_),
632 related_koid: Koid::from_raw(related_koid),
633 }
634 }
635}
636
637struct HandleBasicInfoQuery;
640unsafe impl ObjectQuery for HandleBasicInfoQuery {
641 const TOPIC: Topic = Topic::HANDLE_BASIC;
642 type InfoTy = sys::zx_info_handle_basic_t;
643}
644
645sys::zx_info_handle_count_t!(HandleCountInfo);
646
647impl From<sys::zx_info_handle_count_t> for HandleCountInfo {
648 fn from(sys::zx_info_handle_count_t { handle_count }: sys::zx_info_handle_count_t) -> Self {
649 HandleCountInfo { handle_count }
650 }
651}
652
653struct HandleCountInfoQuery;
656unsafe impl ObjectQuery for HandleCountInfoQuery {
657 const TOPIC: Topic = Topic::HANDLE_COUNT;
658 type InfoTy = sys::zx_info_handle_count_t;
659}
660
661#[derive(Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
663pub enum HandleOp<'a> {
664 Move(NullableHandle),
665 Duplicate(HandleRef<'a>),
666}
667
668#[derive(Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
670#[repr(C)]
671pub struct HandleDisposition<'a> {
672 operation: sys::zx_handle_op_t,
674 handle: sys::zx_handle_t,
676 _handle_lifetime: std::marker::PhantomData<&'a ()>,
678
679 pub object_type: ObjectType,
680 pub rights: Rights,
681 pub result: Status,
682}
683
684static_assertions::assert_eq_size!(HandleDisposition<'_>, sys::zx_handle_disposition_t);
685static_assertions::const_assert_eq!(
686 std::mem::offset_of!(HandleDisposition<'_>, operation),
687 std::mem::offset_of!(sys::zx_handle_disposition_t, operation)
688);
689static_assertions::const_assert_eq!(
690 std::mem::offset_of!(HandleDisposition<'_>, handle),
691 std::mem::offset_of!(sys::zx_handle_disposition_t, handle)
692);
693static_assertions::const_assert_eq!(
694 std::mem::offset_of!(HandleDisposition<'_>, object_type),
695 std::mem::offset_of!(sys::zx_handle_disposition_t, type_)
696);
697static_assertions::const_assert_eq!(
698 std::mem::offset_of!(HandleDisposition<'_>, rights),
699 std::mem::offset_of!(sys::zx_handle_disposition_t, rights)
700);
701static_assertions::const_assert_eq!(
702 std::mem::offset_of!(HandleDisposition<'_>, result),
703 std::mem::offset_of!(sys::zx_handle_disposition_t, result)
704);
705
706impl<'a> HandleDisposition<'a> {
707 #[inline]
708 pub fn new(
709 handle_op: HandleOp<'a>,
710 object_type: ObjectType,
711 rights: Rights,
712 status: Status,
713 ) -> Self {
714 let (operation, handle) = match handle_op {
715 HandleOp::Move(h) => (sys::ZX_HANDLE_OP_MOVE, h.into_raw()),
716 HandleOp::Duplicate(h) => (sys::ZX_HANDLE_OP_DUPLICATE, h.raw_handle()),
717 };
718
719 Self {
720 operation,
721 handle,
722 _handle_lifetime: std::marker::PhantomData,
723 object_type,
724 rights: rights,
725 result: status,
726 }
727 }
728
729 pub fn raw_handle(&self) -> sys::zx_handle_t {
730 self.handle
731 }
732
733 pub fn is_move(&self) -> bool {
734 self.operation == sys::ZX_HANDLE_OP_MOVE
735 }
736
737 pub fn is_duplicate(&self) -> bool {
738 self.operation == sys::ZX_HANDLE_OP_DUPLICATE
739 }
740
741 pub fn take_op(&mut self) -> HandleOp<'a> {
742 match self.operation {
743 sys::ZX_HANDLE_OP_MOVE => {
744 HandleOp::Move(unsafe {
747 NullableHandle::from_raw(std::mem::replace(
748 &mut self.handle,
749 sys::ZX_HANDLE_INVALID,
750 ))
751 })
752 }
753 sys::ZX_HANDLE_OP_DUPLICATE => {
754 HandleOp::Duplicate(unsafe { Unowned::from_raw_handle(self.handle) })
757 }
758 _ => unreachable!(),
759 }
760 }
761
762 pub fn into_raw(mut self) -> sys::zx_handle_disposition_t {
763 match self.take_op() {
764 HandleOp::Move(mut handle) => sys::zx_handle_disposition_t {
765 operation: sys::ZX_HANDLE_OP_MOVE,
766 handle: std::mem::replace(&mut handle, NullableHandle::invalid()).into_raw(),
767 type_: self.object_type.into_raw(),
768 rights: self.rights.bits(),
769 result: self.result.into_raw(),
770 },
771 HandleOp::Duplicate(handle_ref) => sys::zx_handle_disposition_t {
772 operation: sys::ZX_HANDLE_OP_DUPLICATE,
773 handle: handle_ref.raw_handle(),
774 type_: self.object_type.into_raw(),
775 rights: self.rights.bits(),
776 result: self.result.into_raw(),
777 },
778 }
779 }
780}
781
782impl<'a> Drop for HandleDisposition<'a> {
783 fn drop(&mut self) {
784 if self.operation == sys::ZX_HANDLE_OP_MOVE {
786 unsafe { drop(NullableHandle::from_raw(self.handle)) };
787 }
788 }
789}
790
791#[derive(Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
795#[repr(C)]
796pub struct HandleInfo {
797 pub handle: NullableHandle,
798 pub object_type: ObjectType,
799 pub rights: Rights,
800
801 pub(crate) _unused: u32,
803}
804
805static_assertions::assert_eq_size!(HandleInfo, sys::zx_handle_info_t);
806static_assertions::const_assert_eq!(
807 std::mem::offset_of!(HandleInfo, handle),
808 std::mem::offset_of!(sys::zx_handle_info_t, handle)
809);
810static_assertions::const_assert_eq!(
811 std::mem::offset_of!(HandleInfo, object_type),
812 std::mem::offset_of!(sys::zx_handle_info_t, ty)
813);
814static_assertions::const_assert_eq!(
815 std::mem::offset_of!(HandleInfo, rights),
816 std::mem::offset_of!(sys::zx_handle_info_t, rights)
817);
818static_assertions::const_assert_eq!(
819 std::mem::offset_of!(HandleInfo, _unused),
820 std::mem::offset_of!(sys::zx_handle_info_t, unused)
821);
822
823impl HandleInfo {
824 pub const fn new(handle: NullableHandle, object_type: ObjectType, rights: Rights) -> Self {
826 Self { handle, object_type, rights, _unused: 0 }
827 }
828
829 pub const unsafe fn from_raw(raw: sys::zx_handle_info_t) -> HandleInfo {
837 HandleInfo::new(
838 unsafe { NullableHandle::from_raw(raw.handle) },
840 ObjectType::from_raw(raw.ty),
841 Rights::from_bits_retain(raw.rights),
842 )
843 }
844}
845
846#[cfg(test)]
847mod tests {
848 use super::*;
849 use zx::{
852 AsHandleRef, Channel, HandleBased, HandleDisposition, HandleInfo, HandleOp, Name,
853 NullableHandle, ObjectType, Rights, Vmo,
854 };
855 use zx_sys as sys;
856
857 #[test]
858 fn into_raw() {
859 let vmo = Vmo::create(1).unwrap();
860 let h = vmo.into_raw();
861 let vmo2 = Vmo::from(unsafe { NullableHandle::from_raw(h) });
862 assert!(vmo2.write(b"1", 0).is_ok());
863 }
864
865 #[test]
866 fn check_raw_valid() {
867 assert!(Handle::check_raw_valid(sys::ZX_HANDLE_INVALID).is_err());
868 let vmo = Vmo::create(1).unwrap();
869 let vmo_raw = vmo.raw_handle();
870 assert!(Handle::check_raw_valid(vmo_raw).is_ok());
871 drop(vmo);
872 assert!(Handle::check_raw_valid(vmo_raw).is_err());
873 }
874
875 #[test]
877 fn duplicate() {
878 let hello_length: usize = 5;
879
880 let vmo = Vmo::create(hello_length as u64).unwrap();
882 assert!(vmo.write(b"hello", 0).is_ok());
883
884 let readonly_vmo = vmo.duplicate_handle(Rights::READ).unwrap();
886 let mut read_vec = vec![0; hello_length];
888 assert!(readonly_vmo.read(&mut read_vec, 0).is_ok());
889 assert_eq!(read_vec, b"hello");
890 assert_eq!(readonly_vmo.write(b"", 0), Err(Status::ACCESS_DENIED));
891
892 assert!(vmo.write(b"bye", 0).is_ok());
894 assert!(readonly_vmo.read(&mut read_vec, 0).is_ok());
895 assert_eq!(read_vec, b"byelo");
896 }
897
898 #[test]
900 fn replace() {
901 let hello_length: usize = 5;
902
903 let vmo = Vmo::create(hello_length as u64).unwrap();
905 assert!(vmo.write(b"hello", 0).is_ok());
906
907 let readonly_vmo = vmo.replace_handle(Rights::READ).unwrap();
909 let mut read_vec = vec![0; hello_length];
911 assert!(readonly_vmo.read(&mut read_vec, 0).is_ok());
912 assert_eq!(read_vec, b"hello");
913 assert_eq!(readonly_vmo.write(b"", 0), Err(Status::ACCESS_DENIED));
914 }
915
916 #[test]
917 fn set_get_name() {
918 let vmo = Vmo::create(1).unwrap();
920 let short_name = Name::new("v").unwrap();
921 assert!(vmo.set_name(&short_name).is_ok());
922 assert_eq!(vmo.get_name().unwrap(), short_name);
923 }
924
925 #[test]
926 fn set_get_max_len_name() {
927 let vmo = Vmo::create(1).unwrap();
928 let max_len_name = Name::new("a_great_maximum_length_vmo_name").unwrap(); assert!(vmo.set_name(&max_len_name).is_ok());
930 assert_eq!(vmo.get_name().unwrap(), max_len_name);
931 }
932
933 #[test]
934 fn basic_info_channel() {
935 let (side1, side2) = Channel::create();
936 let info1 = side1.basic_info().expect("side1 basic_info failed");
937 let info2 = side2.basic_info().expect("side2 basic_info failed");
938
939 assert_eq!(info1.koid, info2.related_koid);
940 assert_eq!(info2.koid, info1.related_koid);
941
942 for info in &[info1, info2] {
943 assert!(info.koid.raw_koid() >= sys::ZX_KOID_FIRST);
944 assert_eq!(info.object_type, ObjectType::CHANNEL);
945 assert!(info.rights.contains(Rights::READ | Rights::WRITE | Rights::WAIT));
946 }
947
948 let side1_repl = side1.replace_handle(Rights::READ).expect("side1 replace_handle failed");
949 let info1_repl = side1_repl.basic_info().expect("side1_repl basic_info failed");
950 assert_eq!(info1_repl.koid, info1.koid);
951 assert_eq!(info1_repl.rights, Rights::READ);
952 }
953
954 #[test]
955 fn basic_info_vmar() {
956 let root_vmar = fuchsia_runtime::vmar_root_self();
958 let info = root_vmar.basic_info().expect("vmar basic_info failed");
959 assert_eq!(info.object_type, ObjectType::VMAR);
960 assert!(!info.rights.contains(Rights::WAIT));
961 }
962
963 #[test]
964 fn count_info() {
965 let vmo0 = Vmo::create(1).unwrap();
966 let count_info = vmo0.count_info().expect("vmo0 count_info failed");
967 assert_eq!(count_info.handle_count, 1);
968
969 let vmo1 = vmo0.duplicate_handle(Rights::SAME_RIGHTS).expect("vmo duplicate_handle failed");
970 let count_info = vmo1.count_info().expect("vmo1 count_info failed");
971 assert_eq!(count_info.handle_count, 2);
972 }
973
974 #[test]
975 fn raw_handle_disposition() {
976 const RAW_HANDLE: sys::zx_handle_t = 1;
977 let hd = HandleDisposition::new(
978 HandleOp::Move(unsafe { NullableHandle::from_raw(RAW_HANDLE) }),
979 ObjectType::VMO,
980 Rights::EXECUTE,
981 Status::OK,
982 );
983 let raw_hd = hd.into_raw();
984 assert_eq!(raw_hd.operation, sys::ZX_HANDLE_OP_MOVE);
985 assert_eq!(raw_hd.handle, RAW_HANDLE);
986 assert_eq!(raw_hd.rights, sys::ZX_RIGHT_EXECUTE);
987 assert_eq!(raw_hd.type_, sys::ZX_OBJ_TYPE_VMO);
988 assert_eq!(raw_hd.result, sys::ZX_OK);
989 }
990
991 #[test]
992 fn regression_nullable_handle_into_raw_recursion() {
993 let h = NullableHandle::invalid();
994 assert_eq!(h.into_raw(), sys::ZX_HANDLE_INVALID);
996
997 let vmo = Vmo::create(1).unwrap();
998 let raw = vmo.raw_handle();
999 let h = vmo.into_handle();
1000 assert_eq!(h.into_raw(), raw);
1002 }
1003
1004 #[test]
1005 fn handle_info_from_raw() {
1006 const RAW_HANDLE: sys::zx_handle_t = 1;
1007 let raw_hi = sys::zx_handle_info_t {
1008 handle: RAW_HANDLE,
1009 ty: sys::ZX_OBJ_TYPE_VMO,
1010 rights: sys::ZX_RIGHT_EXECUTE,
1011 unused: 128,
1012 };
1013 let hi = unsafe { HandleInfo::from_raw(raw_hi) };
1014 assert_eq!(hi.handle.into_raw(), RAW_HANDLE);
1015 assert_eq!(hi.object_type, ObjectType::VMO);
1016 assert_eq!(hi.rights, Rights::EXECUTE);
1017 }
1018
1019 #[test]
1020 fn basic_peer_closed() {
1021 let (lhs, rhs) = crate::EventPair::create();
1022 assert!(!lhs.is_closed().unwrap());
1023 assert!(!rhs.is_closed().unwrap());
1024 drop(rhs);
1025 assert!(lhs.is_closed().unwrap());
1026 }
1027}