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};
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 {
183 inner: ManuallyDrop::new(T::from(unsafe { Handle::from_raw(handle) })),
184 marker: PhantomData,
185 }
186 }
187
188 pub fn raw_handle(&self) -> sys::zx_handle_t {
189 self.inner.raw_handle()
190 }
191
192 pub fn duplicate(&self, rights: Rights) -> Result<T, Status> {
193 let mut out = 0;
194 let status =
195 unsafe { sys::zx_handle_duplicate(self.raw_handle(), rights.bits(), &mut out) };
196 ok(status).map(|()| T::from(Handle(out)))
197 }
198
199 pub fn signal(&self, clear_mask: Signals, set_mask: Signals) -> Result<(), Status> {
200 let status =
201 unsafe { sys::zx_object_signal(self.raw_handle(), clear_mask.bits(), set_mask.bits()) };
202 ok(status)
203 }
204
205 pub fn wait(&self, signals: Signals, deadline: MonotonicInstant) -> WaitResult {
206 let mut pending = Signals::empty().bits();
207 let status = unsafe {
208 sys::zx_object_wait_one(
209 self.raw_handle(),
210 signals.bits(),
211 deadline.into_nanos(),
212 &mut pending,
213 )
214 };
215 let signals = Signals::from_bits_truncate(pending);
216 match ok(status) {
217 Ok(()) => WaitResult::Ok(signals),
218 Err(Status::TIMED_OUT) => WaitResult::TimedOut(signals),
219 Err(Status::CANCELED) => WaitResult::Canceled(signals),
220 Err(e) => WaitResult::Err(e),
221 }
222 }
223
224 pub fn wait_async(
225 &self,
226 port: &Port,
227 key: u64,
228 signals: Signals,
229 options: WaitAsyncOpts,
230 ) -> Result<(), Status> {
231 let status = unsafe {
232 sys::zx_object_wait_async(
233 self.raw_handle(),
234 port.raw_handle(),
235 key,
236 signals.bits(),
237 options.bits(),
238 )
239 };
240 ok(status)
241 }
242}
243
244#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
250pub enum WaitResult {
251 Ok(Signals),
253
254 TimedOut(Signals),
258
259 Canceled(Signals),
266
267 Err(Status),
270}
271
272impl WaitResult {
273 pub const fn to_result(self) -> Result<Signals, Status> {
276 match self {
277 WaitResult::Ok(signals) => Ok(signals),
278 WaitResult::TimedOut(_signals) => Err(Status::TIMED_OUT),
279 WaitResult::Canceled(_signals) => Err(Status::CANCELED),
280 WaitResult::Err(status) => Err(status),
281 }
282 }
283
284 #[must_use = "if you intended to assert that this is ok, consider `.unwrap()` instead"]
289 #[inline]
290 pub const fn is_ok(&self) -> bool {
291 self.to_result().is_ok()
292 }
293
294 #[must_use = "if you intended to assert that this is err, consider `.unwrap_err()` instead"]
295 #[inline]
296 pub const fn is_err(&self) -> bool {
297 self.to_result().is_err()
298 }
299
300 #[inline]
301 pub fn map<U, F: FnOnce(Signals) -> U>(self, op: F) -> Result<U, Status> {
302 self.to_result().map(op)
303 }
304
305 #[inline]
306 pub fn map_err<F, O: FnOnce(Status) -> F>(self, op: O) -> Result<Signals, F> {
307 self.to_result().map_err(op)
308 }
309
310 #[inline]
311 #[track_caller]
312 pub fn expect(self, msg: &str) -> Signals {
313 self.to_result().expect(msg)
314 }
315
316 #[inline]
317 #[track_caller]
318 pub fn expect_err(self, msg: &str) -> Status {
319 self.to_result().expect_err(msg)
320 }
321
322 #[inline(always)]
323 #[track_caller]
324 pub fn unwrap(self) -> Signals {
325 self.to_result().unwrap()
326 }
327}
328
329impl<'a> Unowned<'a, Handle> {
330 pub fn cast<T: HandleBased>(self) -> Unowned<'a, T> {
332 unsafe { Unowned::from_raw_handle(self.raw_handle()) }
334 }
335}
336
337pub trait AsHandleRef {
339 fn as_handle_ref(&self) -> HandleRef<'_>;
342
343 fn raw_handle(&self) -> sys::zx_handle_t {
347 self.as_handle_ref().inner.0
348 }
349
350 fn signal_handle(&self, clear_mask: Signals, set_mask: Signals) -> Result<(), Status> {
354 self.as_handle_ref().signal(clear_mask, set_mask)
355 }
356
357 fn wait_handle(&self, signals: Signals, deadline: MonotonicInstant) -> WaitResult {
361 self.as_handle_ref().wait(signals, deadline)
362 }
363
364 fn wait_async_handle(
368 &self,
369 port: &Port,
370 key: u64,
371 signals: Signals,
372 options: WaitAsyncOpts,
373 ) -> Result<(), Status> {
374 self.as_handle_ref().wait_async(port, key, signals, options)
375 }
376
377 fn get_name(&self) -> Result<Name, Status> {
383 object_get_property::<NameProperty>(self.as_handle_ref())
384 }
385
386 fn set_name(&self, name: &Name) -> Result<(), Status> {
396 object_set_property::<NameProperty>(self.as_handle_ref(), &name)
397 }
398
399 fn basic_info(&self) -> Result<HandleBasicInfo, Status> {
403 Ok(HandleBasicInfo::from(object_get_info_single::<HandleBasicInfoQuery>(
404 self.as_handle_ref(),
405 )?))
406 }
407
408 fn count_info(&self) -> Result<HandleCountInfo, Status> {
412 Ok(HandleCountInfo::from(object_get_info_single::<HandleCountInfoQuery>(
413 self.as_handle_ref(),
414 )?))
415 }
416
417 fn get_koid(&self) -> Result<Koid, Status> {
419 self.basic_info().map(|info| info.koid)
420 }
421}
422
423impl<'a, T: HandleBased> AsHandleRef for Unowned<'a, T> {
424 fn as_handle_ref(&self) -> HandleRef<'_> {
425 Unowned { inner: ManuallyDrop::new(Handle(self.raw_handle())), marker: PhantomData }
426 }
427}
428
429impl<T: AsHandleRef> AsHandleRef for &T {
430 fn as_handle_ref(&self) -> HandleRef<'_> {
431 (*self).as_handle_ref()
432 }
433}
434
435pub trait HandleBased: AsHandleRef + From<Handle> + Into<Handle> {
443 fn duplicate_handle(&self, rights: Rights) -> Result<Self, Status> {
447 self.as_handle_ref().duplicate(rights).map(|handle| Self::from(handle))
448 }
449
450 fn replace_handle(self, rights: Rights) -> Result<Self, Status> {
455 <Self as Into<Handle>>::into(self).replace(rights).map(|handle| Self::from(handle))
456 }
457
458 fn into_handle(self) -> Handle {
462 self.into()
463 }
464
465 fn into_raw(self) -> sys::zx_handle_t {
469 let h = self.into_handle();
470 let r = h.0;
471 mem::forget(h);
472 r
473 }
474
475 fn from_handle(handle: Handle) -> Self {
479 Self::from(handle)
480 }
481
482 fn into_handle_based<H: HandleBased>(self) -> H {
484 H::from_handle(self.into_handle())
485 }
486
487 fn from_handle_based<H: HandleBased>(h: H) -> Self {
490 Self::from_handle(h.into_handle())
491 }
492
493 fn is_invalid_handle(&self) -> bool {
494 self.as_handle_ref().is_invalid()
495 }
496}
497
498pub trait Peered: HandleBased {
500 fn signal_peer(&self, clear_mask: Signals, set_mask: Signals) -> Result<(), Status> {
505 let handle = self.raw_handle();
506 let status =
507 unsafe { sys::zx_object_signal_peer(handle, clear_mask.bits(), set_mask.bits()) };
508 ok(status)
509 }
510
511 fn is_closed(&self) -> Result<bool, Status> {
519 match self.wait_handle(Signals::OBJECT_PEER_CLOSED, MonotonicInstant::INFINITE_PAST) {
520 WaitResult::Ok(signals) => Ok(signals.contains(Signals::OBJECT_PEER_CLOSED)),
521 WaitResult::TimedOut(_) => Ok(false),
522 WaitResult::Canceled(_) => Err(Status::CANCELED),
523 WaitResult::Err(e) => Err(e),
524 }
525 }
526}
527
528#[derive(Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash)]
530#[repr(transparent)]
531pub struct ObjectType(sys::zx_obj_type_t);
532
533assoc_values!(ObjectType, [
534 NONE = sys::ZX_OBJ_TYPE_NONE;
535 PROCESS = sys::ZX_OBJ_TYPE_PROCESS;
536 THREAD = sys::ZX_OBJ_TYPE_THREAD;
537 VMO = sys::ZX_OBJ_TYPE_VMO;
538 CHANNEL = sys::ZX_OBJ_TYPE_CHANNEL;
539 EVENT = sys::ZX_OBJ_TYPE_EVENT;
540 PORT = sys::ZX_OBJ_TYPE_PORT;
541 INTERRUPT = sys::ZX_OBJ_TYPE_INTERRUPT;
542 PCI_DEVICE = sys::ZX_OBJ_TYPE_PCI_DEVICE;
543 DEBUGLOG = sys::ZX_OBJ_TYPE_DEBUGLOG;
544 SOCKET = sys::ZX_OBJ_TYPE_SOCKET;
545 RESOURCE = sys::ZX_OBJ_TYPE_RESOURCE;
546 EVENTPAIR = sys::ZX_OBJ_TYPE_EVENTPAIR;
547 JOB = sys::ZX_OBJ_TYPE_JOB;
548 VMAR = sys::ZX_OBJ_TYPE_VMAR;
549 FIFO = sys::ZX_OBJ_TYPE_FIFO;
550 GUEST = sys::ZX_OBJ_TYPE_GUEST;
551 VCPU = sys::ZX_OBJ_TYPE_VCPU;
552 TIMER = sys::ZX_OBJ_TYPE_TIMER;
553 IOMMU = sys::ZX_OBJ_TYPE_IOMMU;
554 BTI = sys::ZX_OBJ_TYPE_BTI;
555 PROFILE = sys::ZX_OBJ_TYPE_PROFILE;
556 PMT = sys::ZX_OBJ_TYPE_PMT;
557 SUSPEND_TOKEN = sys::ZX_OBJ_TYPE_SUSPEND_TOKEN;
558 PAGER = sys::ZX_OBJ_TYPE_PAGER;
559 EXCEPTION = sys::ZX_OBJ_TYPE_EXCEPTION;
560 CLOCK = sys::ZX_OBJ_TYPE_CLOCK;
561 STREAM = sys::ZX_OBJ_TYPE_STREAM;
562 MSI = sys::ZX_OBJ_TYPE_MSI;
563 IOB = sys::ZX_OBJ_TYPE_IOB;
564 COUNTER = sys::ZX_OBJ_TYPE_COUNTER;
565]);
566
567impl ObjectType {
568 pub const fn from_raw(raw: sys::zx_obj_type_t) -> Self {
570 Self(raw)
571 }
572
573 pub const fn into_raw(self) -> sys::zx_obj_type_t {
575 self.0
576 }
577}
578
579#[derive(Debug, Copy, Clone, Eq, PartialEq)]
583pub struct HandleBasicInfo {
584 pub koid: Koid,
585 pub rights: Rights,
586 pub object_type: ObjectType,
587 pub related_koid: Koid,
588}
589
590impl Default for HandleBasicInfo {
591 fn default() -> Self {
592 Self::from(sys::zx_info_handle_basic_t::default())
593 }
594}
595
596impl From<sys::zx_info_handle_basic_t> for HandleBasicInfo {
597 fn from(info: sys::zx_info_handle_basic_t) -> Self {
598 let sys::zx_info_handle_basic_t { koid, rights, type_, related_koid, .. } = info;
599
600 HandleBasicInfo {
603 koid: Koid(koid),
604 rights: Rights::from_bits_truncate(rights),
605 object_type: ObjectType(type_),
606 related_koid: Koid(related_koid),
607 }
608 }
609}
610
611struct HandleBasicInfoQuery;
614unsafe impl ObjectQuery for HandleBasicInfoQuery {
615 const TOPIC: Topic = Topic::HANDLE_BASIC;
616 type InfoTy = sys::zx_info_handle_basic_t;
617}
618
619sys::zx_info_handle_count_t!(HandleCountInfo);
620
621impl From<sys::zx_info_handle_count_t> for HandleCountInfo {
622 fn from(sys::zx_info_handle_count_t { handle_count }: sys::zx_info_handle_count_t) -> Self {
623 HandleCountInfo { handle_count }
624 }
625}
626
627struct HandleCountInfoQuery;
630unsafe impl ObjectQuery for HandleCountInfoQuery {
631 const TOPIC: Topic = Topic::HANDLE_COUNT;
632 type InfoTy = sys::zx_info_handle_count_t;
633}
634
635#[derive(Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
637pub enum HandleOp<'a> {
638 Move(Handle),
639 Duplicate(HandleRef<'a>),
640}
641
642#[derive(Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
644#[repr(C)]
645pub struct HandleDisposition<'a> {
646 operation: sys::zx_handle_op_t,
648 handle: sys::zx_handle_t,
650 _handle_lifetime: std::marker::PhantomData<&'a ()>,
652
653 pub object_type: ObjectType,
654 pub rights: Rights,
655 pub result: Status,
656}
657
658static_assertions::assert_eq_size!(HandleDisposition<'_>, sys::zx_handle_disposition_t);
659static_assertions::const_assert_eq!(
660 std::mem::offset_of!(HandleDisposition<'_>, operation),
661 std::mem::offset_of!(sys::zx_handle_disposition_t, operation)
662);
663static_assertions::const_assert_eq!(
664 std::mem::offset_of!(HandleDisposition<'_>, handle),
665 std::mem::offset_of!(sys::zx_handle_disposition_t, handle)
666);
667static_assertions::const_assert_eq!(
668 std::mem::offset_of!(HandleDisposition<'_>, object_type),
669 std::mem::offset_of!(sys::zx_handle_disposition_t, type_)
670);
671static_assertions::const_assert_eq!(
672 std::mem::offset_of!(HandleDisposition<'_>, rights),
673 std::mem::offset_of!(sys::zx_handle_disposition_t, rights)
674);
675static_assertions::const_assert_eq!(
676 std::mem::offset_of!(HandleDisposition<'_>, result),
677 std::mem::offset_of!(sys::zx_handle_disposition_t, result)
678);
679
680impl<'a> HandleDisposition<'a> {
681 #[inline]
682 pub fn new(
683 handle_op: HandleOp<'a>,
684 object_type: ObjectType,
685 rights: Rights,
686 status: Status,
687 ) -> Self {
688 let (operation, handle) = match handle_op {
689 HandleOp::Move(h) => (sys::ZX_HANDLE_OP_MOVE, h.into_raw()),
690 HandleOp::Duplicate(h) => (sys::ZX_HANDLE_OP_DUPLICATE, h.raw_handle()),
691 };
692
693 Self {
694 operation,
695 handle,
696 _handle_lifetime: std::marker::PhantomData,
697 object_type,
698 rights: rights,
699 result: status,
700 }
701 }
702
703 pub fn raw_handle(&self) -> sys::zx_handle_t {
704 self.handle
705 }
706
707 pub fn is_move(&self) -> bool {
708 self.operation == sys::ZX_HANDLE_OP_MOVE
709 }
710
711 pub fn is_duplicate(&self) -> bool {
712 self.operation == sys::ZX_HANDLE_OP_DUPLICATE
713 }
714
715 pub fn take_op(&mut self) -> HandleOp<'a> {
716 match self.operation {
717 sys::ZX_HANDLE_OP_MOVE => {
718 HandleOp::Move(unsafe {
721 Handle::from_raw(std::mem::replace(&mut self.handle, sys::ZX_HANDLE_INVALID))
722 })
723 }
724 sys::ZX_HANDLE_OP_DUPLICATE => {
725 HandleOp::Duplicate(unsafe { Unowned::from_raw_handle(self.handle) })
728 }
729 _ => unreachable!(),
730 }
731 }
732
733 pub fn into_raw(mut self) -> sys::zx_handle_disposition_t {
734 match self.take_op() {
735 HandleOp::Move(mut handle) => sys::zx_handle_disposition_t {
736 operation: sys::ZX_HANDLE_OP_MOVE,
737 handle: std::mem::replace(&mut handle, Handle::invalid()).into_raw(),
738 type_: self.object_type.0,
739 rights: self.rights.bits(),
740 result: self.result.into_raw(),
741 },
742 HandleOp::Duplicate(handle_ref) => sys::zx_handle_disposition_t {
743 operation: sys::ZX_HANDLE_OP_DUPLICATE,
744 handle: handle_ref.raw_handle(),
745 type_: self.object_type.0,
746 rights: self.rights.bits(),
747 result: self.result.into_raw(),
748 },
749 }
750 }
751}
752
753impl<'a> Drop for HandleDisposition<'a> {
754 fn drop(&mut self) {
755 if self.operation == sys::ZX_HANDLE_OP_MOVE {
757 unsafe { drop(Handle::from_raw(self.handle)) };
758 }
759 }
760}
761
762#[derive(Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
766#[repr(C)]
767pub struct HandleInfo {
768 pub handle: Handle,
769 pub object_type: ObjectType,
770 pub rights: Rights,
771
772 pub(crate) _unused: u32,
774}
775
776static_assertions::assert_eq_size!(HandleInfo, sys::zx_handle_info_t);
777static_assertions::const_assert_eq!(
778 std::mem::offset_of!(HandleInfo, handle),
779 std::mem::offset_of!(sys::zx_handle_info_t, handle)
780);
781static_assertions::const_assert_eq!(
782 std::mem::offset_of!(HandleInfo, object_type),
783 std::mem::offset_of!(sys::zx_handle_info_t, ty)
784);
785static_assertions::const_assert_eq!(
786 std::mem::offset_of!(HandleInfo, rights),
787 std::mem::offset_of!(sys::zx_handle_info_t, rights)
788);
789static_assertions::const_assert_eq!(
790 std::mem::offset_of!(HandleInfo, _unused),
791 std::mem::offset_of!(sys::zx_handle_info_t, unused)
792);
793
794impl HandleInfo {
795 pub const fn new(handle: Handle, object_type: ObjectType, rights: Rights) -> Self {
797 Self { handle, object_type, rights, _unused: 0 }
798 }
799
800 pub const unsafe fn from_raw(raw: sys::zx_handle_info_t) -> HandleInfo {
808 HandleInfo::new(
809 unsafe { Handle::from_raw(raw.handle) },
811 ObjectType(raw.ty),
812 Rights::from_bits_retain(raw.rights),
813 )
814 }
815}
816
817#[cfg(test)]
818mod tests {
819 use super::*;
820 use zx::{
823 AsHandleRef, Channel, Handle, HandleBased, HandleDisposition, HandleInfo, HandleOp, Name,
824 ObjectType, Rights, Vmo,
825 };
826 use zx_sys as sys;
827
828 #[test]
829 fn into_raw() {
830 let vmo = Vmo::create(1).unwrap();
831 let h = vmo.into_raw();
832 let vmo2 = Vmo::from(unsafe { Handle::from_raw(h) });
833 assert!(vmo2.write(b"1", 0).is_ok());
834 }
835
836 #[test]
838 fn duplicate() {
839 let hello_length: usize = 5;
840
841 let vmo = Vmo::create(hello_length as u64).unwrap();
843 assert!(vmo.write(b"hello", 0).is_ok());
844
845 let readonly_vmo = vmo.duplicate_handle(Rights::READ).unwrap();
847 let mut read_vec = vec![0; hello_length];
849 assert!(readonly_vmo.read(&mut read_vec, 0).is_ok());
850 assert_eq!(read_vec, b"hello");
851 assert_eq!(readonly_vmo.write(b"", 0), Err(Status::ACCESS_DENIED));
852
853 assert!(vmo.write(b"bye", 0).is_ok());
855 assert!(readonly_vmo.read(&mut read_vec, 0).is_ok());
856 assert_eq!(read_vec, b"byelo");
857 }
858
859 #[test]
861 fn replace() {
862 let hello_length: usize = 5;
863
864 let vmo = Vmo::create(hello_length as u64).unwrap();
866 assert!(vmo.write(b"hello", 0).is_ok());
867
868 let readonly_vmo = vmo.replace_handle(Rights::READ).unwrap();
870 let mut read_vec = vec![0; hello_length];
872 assert!(readonly_vmo.read(&mut read_vec, 0).is_ok());
873 assert_eq!(read_vec, b"hello");
874 assert_eq!(readonly_vmo.write(b"", 0), Err(Status::ACCESS_DENIED));
875 }
876
877 #[test]
878 fn set_get_name() {
879 let vmo = Vmo::create(1).unwrap();
881 let short_name = Name::new("v").unwrap();
882 assert!(vmo.set_name(&short_name).is_ok());
883 assert_eq!(vmo.get_name().unwrap(), short_name);
884 }
885
886 #[test]
887 fn set_get_max_len_name() {
888 let vmo = Vmo::create(1).unwrap();
889 let max_len_name = Name::new("a_great_maximum_length_vmo_name").unwrap(); assert!(vmo.set_name(&max_len_name).is_ok());
891 assert_eq!(vmo.get_name().unwrap(), max_len_name);
892 }
893
894 #[test]
895 fn basic_info_channel() {
896 let (side1, side2) = Channel::create();
897 let info1 = side1.basic_info().expect("side1 basic_info failed");
898 let info2 = side2.basic_info().expect("side2 basic_info failed");
899
900 assert_eq!(info1.koid, info2.related_koid);
901 assert_eq!(info2.koid, info1.related_koid);
902
903 for info in &[info1, info2] {
904 assert!(info.koid.raw_koid() >= sys::ZX_KOID_FIRST);
905 assert_eq!(info.object_type, ObjectType::CHANNEL);
906 assert!(info.rights.contains(Rights::READ | Rights::WRITE | Rights::WAIT));
907 }
908
909 let side1_repl = side1.replace_handle(Rights::READ).expect("side1 replace_handle failed");
910 let info1_repl = side1_repl.basic_info().expect("side1_repl basic_info failed");
911 assert_eq!(info1_repl.koid, info1.koid);
912 assert_eq!(info1_repl.rights, Rights::READ);
913 }
914
915 #[test]
916 fn basic_info_vmar() {
917 let root_vmar = fuchsia_runtime::vmar_root_self();
919 let info = root_vmar.basic_info().expect("vmar basic_info failed");
920 assert_eq!(info.object_type, ObjectType::VMAR);
921 assert!(!info.rights.contains(Rights::WAIT));
922 }
923
924 #[test]
925 fn count_info() {
926 let vmo0 = Vmo::create(1).unwrap();
927 let count_info = vmo0.count_info().expect("vmo0 count_info failed");
928 assert_eq!(count_info.handle_count, 1);
929
930 let vmo1 = vmo0.duplicate_handle(Rights::SAME_RIGHTS).expect("vmo duplicate_handle failed");
931 let count_info = vmo1.count_info().expect("vmo1 count_info failed");
932 assert_eq!(count_info.handle_count, 2);
933 }
934
935 #[test]
936 fn raw_handle_disposition() {
937 const RAW_HANDLE: sys::zx_handle_t = 1;
938 let hd = HandleDisposition::new(
939 HandleOp::Move(unsafe { Handle::from_raw(RAW_HANDLE) }),
940 ObjectType::VMO,
941 Rights::EXECUTE,
942 Status::OK,
943 );
944 let raw_hd = hd.into_raw();
945 assert_eq!(raw_hd.operation, sys::ZX_HANDLE_OP_MOVE);
946 assert_eq!(raw_hd.handle, RAW_HANDLE);
947 assert_eq!(raw_hd.rights, sys::ZX_RIGHT_EXECUTE);
948 assert_eq!(raw_hd.type_, sys::ZX_OBJ_TYPE_VMO);
949 assert_eq!(raw_hd.result, sys::ZX_OK);
950 }
951
952 #[test]
953 fn handle_info_from_raw() {
954 const RAW_HANDLE: sys::zx_handle_t = 1;
955 let raw_hi = sys::zx_handle_info_t {
956 handle: RAW_HANDLE,
957 ty: sys::ZX_OBJ_TYPE_VMO,
958 rights: sys::ZX_RIGHT_EXECUTE,
959 unused: 128,
960 };
961 let hi = unsafe { HandleInfo::from_raw(raw_hi) };
962 assert_eq!(hi.handle.into_raw(), RAW_HANDLE);
963 assert_eq!(hi.object_type, ObjectType::VMO);
964 assert_eq!(hi.rights, Rights::EXECUTE);
965 }
966
967 #[test]
968 fn basic_peer_closed() {
969 let (lhs, rhs) = crate::EventPair::create();
970 assert!(!lhs.is_closed().unwrap());
971 assert!(!rhs.is_closed().unwrap());
972 drop(rhs);
973 assert!(lhs.is_closed().unwrap());
974 }
975}