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) -> WaitResult {
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 let signals = Signals::from_bits_truncate(pending);
213 match ok(status) {
214 Ok(()) => WaitResult::Ok(signals),
215 Err(Status::TIMED_OUT) => WaitResult::TimedOut(signals),
216 Err(Status::CANCELED) => WaitResult::Canceled(signals),
217 Err(e) => WaitResult::Err(e),
218 }
219 }
220
221 pub fn wait_async(
222 &self,
223 port: &Port,
224 key: u64,
225 signals: Signals,
226 options: WaitAsyncOpts,
227 ) -> Result<(), Status> {
228 let status = unsafe {
229 sys::zx_object_wait_async(
230 self.raw_handle(),
231 port.raw_handle(),
232 key,
233 signals.bits(),
234 options.bits(),
235 )
236 };
237 ok(status)
238 }
239}
240
241#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
247pub enum WaitResult {
248 Ok(Signals),
250
251 TimedOut(Signals),
255
256 Canceled(Signals),
263
264 Err(Status),
267}
268
269impl WaitResult {
270 pub const fn to_result(self) -> Result<Signals, Status> {
273 match self {
274 WaitResult::Ok(signals) => Ok(signals),
275 WaitResult::TimedOut(_signals) => Err(Status::TIMED_OUT),
276 WaitResult::Canceled(_signals) => Err(Status::CANCELED),
277 WaitResult::Err(status) => Err(status),
278 }
279 }
280
281 #[must_use = "if you intended to assert that this is ok, consider `.unwrap()` instead"]
286 #[inline]
287 pub const fn is_ok(&self) -> bool {
288 self.to_result().is_ok()
289 }
290
291 #[must_use = "if you intended to assert that this is err, consider `.unwrap_err()` instead"]
292 #[inline]
293 pub const fn is_err(&self) -> bool {
294 self.to_result().is_err()
295 }
296
297 #[inline]
298 pub fn map<U, F: FnOnce(Signals) -> U>(self, op: F) -> Result<U, Status> {
299 self.to_result().map(op)
300 }
301
302 #[inline]
303 pub fn map_err<F, O: FnOnce(Status) -> F>(self, op: O) -> Result<Signals, F> {
304 self.to_result().map_err(op)
305 }
306
307 #[inline]
308 #[track_caller]
309 pub fn expect(self, msg: &str) -> Signals {
310 self.to_result().expect(msg)
311 }
312
313 #[inline]
314 #[track_caller]
315 pub fn expect_err(self, msg: &str) -> Status {
316 self.to_result().expect_err(msg)
317 }
318
319 #[inline(always)]
320 #[track_caller]
321 pub fn unwrap(self) -> Signals {
322 self.to_result().unwrap()
323 }
324}
325
326impl<'a> Unowned<'a, Handle> {
327 pub fn cast<T: HandleBased>(self) -> Unowned<'a, T> {
329 unsafe { Unowned::from_raw_handle(self.raw_handle()) }
331 }
332}
333
334pub trait AsHandleRef {
336 fn as_handle_ref(&self) -> HandleRef<'_>;
339
340 fn raw_handle(&self) -> sys::zx_handle_t {
344 self.as_handle_ref().inner.0
345 }
346
347 fn signal_handle(&self, clear_mask: Signals, set_mask: Signals) -> Result<(), Status> {
351 self.as_handle_ref().signal(clear_mask, set_mask)
352 }
353
354 fn wait_handle(&self, signals: Signals, deadline: MonotonicInstant) -> WaitResult {
358 self.as_handle_ref().wait(signals, deadline)
359 }
360
361 fn wait_async_handle(
365 &self,
366 port: &Port,
367 key: u64,
368 signals: Signals,
369 options: WaitAsyncOpts,
370 ) -> Result<(), Status> {
371 self.as_handle_ref().wait_async(port, key, signals, options)
372 }
373
374 fn get_name(&self) -> Result<Name, Status> {
380 object_get_property::<NameProperty>(self.as_handle_ref())
381 }
382
383 fn set_name(&self, name: &Name) -> Result<(), Status> {
393 object_set_property::<NameProperty>(self.as_handle_ref(), &name)
394 }
395
396 fn basic_info(&self) -> Result<HandleBasicInfo, Status> {
400 Ok(HandleBasicInfo::from(object_get_info_single::<HandleBasicInfoQuery>(
401 self.as_handle_ref(),
402 )?))
403 }
404
405 fn count_info(&self) -> Result<HandleCountInfo, Status> {
409 Ok(HandleCountInfo::from(object_get_info_single::<HandleCountInfoQuery>(
410 self.as_handle_ref(),
411 )?))
412 }
413
414 fn get_koid(&self) -> Result<Koid, Status> {
416 self.basic_info().map(|info| info.koid)
417 }
418}
419
420impl<'a, T: HandleBased> AsHandleRef for Unowned<'a, T> {
421 fn as_handle_ref(&self) -> HandleRef<'_> {
422 Unowned { inner: ManuallyDrop::new(Handle(self.raw_handle())), marker: PhantomData }
423 }
424}
425
426impl<T: AsHandleRef> AsHandleRef for &T {
427 fn as_handle_ref(&self) -> HandleRef<'_> {
428 (*self).as_handle_ref()
429 }
430}
431
432pub trait HandleBased: AsHandleRef + From<Handle> + Into<Handle> {
440 fn duplicate_handle(&self, rights: Rights) -> Result<Self, Status> {
444 self.as_handle_ref().duplicate(rights).map(|handle| Self::from(handle))
445 }
446
447 fn replace_handle(self, rights: Rights) -> Result<Self, Status> {
452 <Self as Into<Handle>>::into(self).replace(rights).map(|handle| Self::from(handle))
453 }
454
455 fn into_handle(self) -> Handle {
459 self.into()
460 }
461
462 fn into_raw(self) -> sys::zx_handle_t {
466 let h = self.into_handle();
467 let r = h.0;
468 mem::forget(h);
469 r
470 }
471
472 fn from_handle(handle: Handle) -> Self {
476 Self::from(handle)
477 }
478
479 fn into_handle_based<H: HandleBased>(self) -> H {
481 H::from_handle(self.into_handle())
482 }
483
484 fn from_handle_based<H: HandleBased>(h: H) -> Self {
487 Self::from_handle(h.into_handle())
488 }
489
490 fn is_invalid_handle(&self) -> bool {
491 self.as_handle_ref().is_invalid()
492 }
493}
494
495pub trait Peered: HandleBased {
497 fn signal_peer(&self, clear_mask: Signals, set_mask: Signals) -> Result<(), Status> {
502 let handle = self.raw_handle();
503 let status =
504 unsafe { sys::zx_object_signal_peer(handle, clear_mask.bits(), set_mask.bits()) };
505 ok(status)
506 }
507
508 fn is_closed(&self) -> Result<bool, Status> {
516 match self.wait_handle(Signals::OBJECT_PEER_CLOSED, MonotonicInstant::INFINITE_PAST) {
517 WaitResult::Ok(signals) => Ok(signals.contains(Signals::OBJECT_PEER_CLOSED)),
518 WaitResult::TimedOut(_) => Ok(false),
519 WaitResult::Canceled(_) => Err(Status::CANCELED),
520 WaitResult::Err(e) => Err(e),
521 }
522 }
523}
524
525#[derive(Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash)]
527#[repr(transparent)]
528pub struct ObjectType(sys::zx_obj_type_t);
529
530assoc_values!(ObjectType, [
531 NONE = sys::ZX_OBJ_TYPE_NONE;
532 PROCESS = sys::ZX_OBJ_TYPE_PROCESS;
533 THREAD = sys::ZX_OBJ_TYPE_THREAD;
534 VMO = sys::ZX_OBJ_TYPE_VMO;
535 CHANNEL = sys::ZX_OBJ_TYPE_CHANNEL;
536 EVENT = sys::ZX_OBJ_TYPE_EVENT;
537 PORT = sys::ZX_OBJ_TYPE_PORT;
538 INTERRUPT = sys::ZX_OBJ_TYPE_INTERRUPT;
539 PCI_DEVICE = sys::ZX_OBJ_TYPE_PCI_DEVICE;
540 DEBUGLOG = sys::ZX_OBJ_TYPE_DEBUGLOG;
541 SOCKET = sys::ZX_OBJ_TYPE_SOCKET;
542 RESOURCE = sys::ZX_OBJ_TYPE_RESOURCE;
543 EVENTPAIR = sys::ZX_OBJ_TYPE_EVENTPAIR;
544 JOB = sys::ZX_OBJ_TYPE_JOB;
545 VMAR = sys::ZX_OBJ_TYPE_VMAR;
546 FIFO = sys::ZX_OBJ_TYPE_FIFO;
547 GUEST = sys::ZX_OBJ_TYPE_GUEST;
548 VCPU = sys::ZX_OBJ_TYPE_VCPU;
549 TIMER = sys::ZX_OBJ_TYPE_TIMER;
550 IOMMU = sys::ZX_OBJ_TYPE_IOMMU;
551 BTI = sys::ZX_OBJ_TYPE_BTI;
552 PROFILE = sys::ZX_OBJ_TYPE_PROFILE;
553 PMT = sys::ZX_OBJ_TYPE_PMT;
554 SUSPEND_TOKEN = sys::ZX_OBJ_TYPE_SUSPEND_TOKEN;
555 PAGER = sys::ZX_OBJ_TYPE_PAGER;
556 EXCEPTION = sys::ZX_OBJ_TYPE_EXCEPTION;
557 CLOCK = sys::ZX_OBJ_TYPE_CLOCK;
558 STREAM = sys::ZX_OBJ_TYPE_STREAM;
559 MSI = sys::ZX_OBJ_TYPE_MSI;
560 IOB = sys::ZX_OBJ_TYPE_IOB;
561 COUNTER = sys::ZX_OBJ_TYPE_COUNTER;
562]);
563
564impl ObjectType {
565 pub const fn from_raw(raw: sys::zx_obj_type_t) -> Self {
567 Self(raw)
568 }
569
570 pub const fn into_raw(self) -> sys::zx_obj_type_t {
572 self.0
573 }
574}
575
576#[derive(Debug, Copy, Clone, Eq, PartialEq)]
580pub struct HandleBasicInfo {
581 pub koid: Koid,
582 pub rights: Rights,
583 pub object_type: ObjectType,
584 pub related_koid: Koid,
585}
586
587impl Default for HandleBasicInfo {
588 fn default() -> Self {
589 Self::from(sys::zx_info_handle_basic_t::default())
590 }
591}
592
593impl From<sys::zx_info_handle_basic_t> for HandleBasicInfo {
594 fn from(info: sys::zx_info_handle_basic_t) -> Self {
595 let sys::zx_info_handle_basic_t { koid, rights, type_, related_koid, .. } = info;
596
597 HandleBasicInfo {
600 koid: Koid(koid),
601 rights: Rights::from_bits_truncate(rights),
602 object_type: ObjectType(type_),
603 related_koid: Koid(related_koid),
604 }
605 }
606}
607
608struct HandleBasicInfoQuery;
611unsafe impl ObjectQuery for HandleBasicInfoQuery {
612 const TOPIC: Topic = Topic::HANDLE_BASIC;
613 type InfoTy = sys::zx_info_handle_basic_t;
614}
615
616sys::zx_info_handle_count_t!(HandleCountInfo);
617
618impl From<sys::zx_info_handle_count_t> for HandleCountInfo {
619 fn from(sys::zx_info_handle_count_t { handle_count }: sys::zx_info_handle_count_t) -> Self {
620 HandleCountInfo { handle_count }
621 }
622}
623
624struct HandleCountInfoQuery;
627unsafe impl ObjectQuery for HandleCountInfoQuery {
628 const TOPIC: Topic = Topic::HANDLE_COUNT;
629 type InfoTy = sys::zx_info_handle_count_t;
630}
631
632#[derive(Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
634pub enum HandleOp<'a> {
635 Move(Handle),
636 Duplicate(HandleRef<'a>),
637}
638
639#[derive(Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
641#[repr(C)]
642pub struct HandleDisposition<'a> {
643 operation: sys::zx_handle_op_t,
645 handle: sys::zx_handle_t,
647 _handle_lifetime: std::marker::PhantomData<&'a ()>,
649
650 pub object_type: ObjectType,
651 pub rights: Rights,
652 pub result: Status,
653}
654
655static_assertions::assert_eq_size!(HandleDisposition<'_>, sys::zx_handle_disposition_t);
656static_assertions::const_assert_eq!(
657 std::mem::offset_of!(HandleDisposition<'_>, operation),
658 std::mem::offset_of!(sys::zx_handle_disposition_t, operation)
659);
660static_assertions::const_assert_eq!(
661 std::mem::offset_of!(HandleDisposition<'_>, handle),
662 std::mem::offset_of!(sys::zx_handle_disposition_t, handle)
663);
664static_assertions::const_assert_eq!(
665 std::mem::offset_of!(HandleDisposition<'_>, object_type),
666 std::mem::offset_of!(sys::zx_handle_disposition_t, type_)
667);
668static_assertions::const_assert_eq!(
669 std::mem::offset_of!(HandleDisposition<'_>, rights),
670 std::mem::offset_of!(sys::zx_handle_disposition_t, rights)
671);
672static_assertions::const_assert_eq!(
673 std::mem::offset_of!(HandleDisposition<'_>, result),
674 std::mem::offset_of!(sys::zx_handle_disposition_t, result)
675);
676
677impl<'a> HandleDisposition<'a> {
678 #[inline]
679 pub fn new(
680 handle_op: HandleOp<'a>,
681 object_type: ObjectType,
682 rights: Rights,
683 status: Status,
684 ) -> Self {
685 let (operation, handle) = match handle_op {
686 HandleOp::Move(h) => (sys::ZX_HANDLE_OP_MOVE, h.into_raw()),
687 HandleOp::Duplicate(h) => (sys::ZX_HANDLE_OP_DUPLICATE, h.raw_handle()),
688 };
689
690 Self {
691 operation,
692 handle,
693 _handle_lifetime: std::marker::PhantomData,
694 object_type,
695 rights: rights,
696 result: status,
697 }
698 }
699
700 pub fn raw_handle(&self) -> sys::zx_handle_t {
701 self.handle
702 }
703
704 pub fn is_move(&self) -> bool {
705 self.operation == sys::ZX_HANDLE_OP_MOVE
706 }
707
708 pub fn is_duplicate(&self) -> bool {
709 self.operation == sys::ZX_HANDLE_OP_DUPLICATE
710 }
711
712 pub fn take_op(&mut self) -> HandleOp<'a> {
713 match self.operation {
714 sys::ZX_HANDLE_OP_MOVE => {
715 HandleOp::Move(unsafe {
718 Handle::from_raw(std::mem::replace(&mut self.handle, sys::ZX_HANDLE_INVALID))
719 })
720 }
721 sys::ZX_HANDLE_OP_DUPLICATE => {
722 HandleOp::Duplicate(unsafe { Unowned::from_raw_handle(self.handle) })
725 }
726 _ => unreachable!(),
727 }
728 }
729
730 pub fn into_raw(mut self) -> sys::zx_handle_disposition_t {
731 match self.take_op() {
732 HandleOp::Move(mut handle) => sys::zx_handle_disposition_t {
733 operation: sys::ZX_HANDLE_OP_MOVE,
734 handle: std::mem::replace(&mut handle, Handle::invalid()).into_raw(),
735 type_: self.object_type.0,
736 rights: self.rights.bits(),
737 result: self.result.into_raw(),
738 },
739 HandleOp::Duplicate(handle_ref) => sys::zx_handle_disposition_t {
740 operation: sys::ZX_HANDLE_OP_DUPLICATE,
741 handle: handle_ref.raw_handle(),
742 type_: self.object_type.0,
743 rights: self.rights.bits(),
744 result: self.result.into_raw(),
745 },
746 }
747 }
748}
749
750impl<'a> Drop for HandleDisposition<'a> {
751 fn drop(&mut self) {
752 if self.operation == sys::ZX_HANDLE_OP_MOVE {
754 unsafe { drop(Handle::from_raw(self.handle)) };
755 }
756 }
757}
758
759#[derive(Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
763#[repr(C)]
764pub struct HandleInfo {
765 pub handle: Handle,
766 pub object_type: ObjectType,
767 pub rights: Rights,
768
769 pub(crate) _unused: u32,
771}
772
773static_assertions::assert_eq_size!(HandleInfo, sys::zx_handle_info_t);
774static_assertions::const_assert_eq!(
775 std::mem::offset_of!(HandleInfo, handle),
776 std::mem::offset_of!(sys::zx_handle_info_t, handle)
777);
778static_assertions::const_assert_eq!(
779 std::mem::offset_of!(HandleInfo, object_type),
780 std::mem::offset_of!(sys::zx_handle_info_t, ty)
781);
782static_assertions::const_assert_eq!(
783 std::mem::offset_of!(HandleInfo, rights),
784 std::mem::offset_of!(sys::zx_handle_info_t, rights)
785);
786static_assertions::const_assert_eq!(
787 std::mem::offset_of!(HandleInfo, _unused),
788 std::mem::offset_of!(sys::zx_handle_info_t, unused)
789);
790
791impl HandleInfo {
792 pub const fn new(handle: Handle, object_type: ObjectType, rights: Rights) -> Self {
794 Self { handle, object_type, rights, _unused: 0 }
795 }
796
797 pub const unsafe fn from_raw(raw: sys::zx_handle_info_t) -> HandleInfo {
805 HandleInfo::new(
806 unsafe { Handle::from_raw(raw.handle) },
808 ObjectType(raw.ty),
809 Rights::from_bits_retain(raw.rights),
810 )
811 }
812}
813
814#[cfg(test)]
815mod tests {
816 use super::*;
817 use zx::{
820 AsHandleRef, Channel, Handle, HandleBased, HandleDisposition, HandleInfo, HandleOp, Name,
821 ObjectType, Rights, Vmo,
822 };
823 use zx_sys as sys;
824
825 #[test]
826 fn into_raw() {
827 let vmo = Vmo::create(1).unwrap();
828 let h = vmo.into_raw();
829 let vmo2 = Vmo::from(unsafe { Handle::from_raw(h) });
830 assert!(vmo2.write(b"1", 0).is_ok());
831 }
832
833 #[test]
835 fn duplicate() {
836 let hello_length: usize = 5;
837
838 let vmo = Vmo::create(hello_length as u64).unwrap();
840 assert!(vmo.write(b"hello", 0).is_ok());
841
842 let readonly_vmo = vmo.duplicate_handle(Rights::READ).unwrap();
844 let mut read_vec = vec![0; hello_length];
846 assert!(readonly_vmo.read(&mut read_vec, 0).is_ok());
847 assert_eq!(read_vec, b"hello");
848 assert_eq!(readonly_vmo.write(b"", 0), Err(Status::ACCESS_DENIED));
849
850 assert!(vmo.write(b"bye", 0).is_ok());
852 assert!(readonly_vmo.read(&mut read_vec, 0).is_ok());
853 assert_eq!(read_vec, b"byelo");
854 }
855
856 #[test]
858 fn replace() {
859 let hello_length: usize = 5;
860
861 let vmo = Vmo::create(hello_length as u64).unwrap();
863 assert!(vmo.write(b"hello", 0).is_ok());
864
865 let readonly_vmo = vmo.replace_handle(Rights::READ).unwrap();
867 let mut read_vec = vec![0; hello_length];
869 assert!(readonly_vmo.read(&mut read_vec, 0).is_ok());
870 assert_eq!(read_vec, b"hello");
871 assert_eq!(readonly_vmo.write(b"", 0), Err(Status::ACCESS_DENIED));
872 }
873
874 #[test]
875 fn set_get_name() {
876 let vmo = Vmo::create(1).unwrap();
878 let short_name = Name::new("v").unwrap();
879 assert!(vmo.set_name(&short_name).is_ok());
880 assert_eq!(vmo.get_name().unwrap(), short_name);
881 }
882
883 #[test]
884 fn set_get_max_len_name() {
885 let vmo = Vmo::create(1).unwrap();
886 let max_len_name = Name::new("a_great_maximum_length_vmo_name").unwrap(); assert!(vmo.set_name(&max_len_name).is_ok());
888 assert_eq!(vmo.get_name().unwrap(), max_len_name);
889 }
890
891 #[test]
892 fn basic_info_channel() {
893 let (side1, side2) = Channel::create();
894 let info1 = side1.basic_info().expect("side1 basic_info failed");
895 let info2 = side2.basic_info().expect("side2 basic_info failed");
896
897 assert_eq!(info1.koid, info2.related_koid);
898 assert_eq!(info2.koid, info1.related_koid);
899
900 for info in &[info1, info2] {
901 assert!(info.koid.raw_koid() >= sys::ZX_KOID_FIRST);
902 assert_eq!(info.object_type, ObjectType::CHANNEL);
903 assert!(info.rights.contains(Rights::READ | Rights::WRITE | Rights::WAIT));
904 }
905
906 let side1_repl = side1.replace_handle(Rights::READ).expect("side1 replace_handle failed");
907 let info1_repl = side1_repl.basic_info().expect("side1_repl basic_info failed");
908 assert_eq!(info1_repl.koid, info1.koid);
909 assert_eq!(info1_repl.rights, Rights::READ);
910 }
911
912 #[test]
913 fn basic_info_vmar() {
914 let root_vmar = fuchsia_runtime::vmar_root_self();
916 let info = root_vmar.basic_info().expect("vmar basic_info failed");
917 assert_eq!(info.object_type, ObjectType::VMAR);
918 assert!(!info.rights.contains(Rights::WAIT));
919 }
920
921 #[test]
922 fn count_info() {
923 let vmo0 = Vmo::create(1).unwrap();
924 let count_info = vmo0.count_info().expect("vmo0 count_info failed");
925 assert_eq!(count_info.handle_count, 1);
926
927 let vmo1 = vmo0.duplicate_handle(Rights::SAME_RIGHTS).expect("vmo duplicate_handle failed");
928 let count_info = vmo1.count_info().expect("vmo1 count_info failed");
929 assert_eq!(count_info.handle_count, 2);
930 }
931
932 #[test]
933 fn raw_handle_disposition() {
934 const RAW_HANDLE: sys::zx_handle_t = 1;
935 let hd = HandleDisposition::new(
936 HandleOp::Move(unsafe { Handle::from_raw(RAW_HANDLE) }),
937 ObjectType::VMO,
938 Rights::EXECUTE,
939 Status::OK,
940 );
941 let raw_hd = hd.into_raw();
942 assert_eq!(raw_hd.operation, sys::ZX_HANDLE_OP_MOVE);
943 assert_eq!(raw_hd.handle, RAW_HANDLE);
944 assert_eq!(raw_hd.rights, sys::ZX_RIGHT_EXECUTE);
945 assert_eq!(raw_hd.type_, sys::ZX_OBJ_TYPE_VMO);
946 assert_eq!(raw_hd.result, sys::ZX_OK);
947 }
948
949 #[test]
950 fn handle_info_from_raw() {
951 const RAW_HANDLE: sys::zx_handle_t = 1;
952 let raw_hi = sys::zx_handle_info_t {
953 handle: RAW_HANDLE,
954 ty: sys::ZX_OBJ_TYPE_VMO,
955 rights: sys::ZX_RIGHT_EXECUTE,
956 unused: 128,
957 };
958 let hi = unsafe { HandleInfo::from_raw(raw_hi) };
959 assert_eq!(hi.handle.into_raw(), RAW_HANDLE);
960 assert_eq!(hi.object_type, ObjectType::VMO);
961 assert_eq!(hi.rights, Rights::EXECUTE);
962 }
963
964 #[test]
965 fn basic_peer_closed() {
966 let (lhs, rhs) = crate::EventPair::create();
967 assert!(!lhs.is_closed().unwrap());
968 assert!(!rhs.is_closed().unwrap());
969 drop(rhs);
970 assert!(lhs.is_closed().unwrap());
971 }
972}