summaryrefslogtreecommitdiffstats
path: root/third_party/rust/fuchsia-zircon/src/handle.rs
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/rust/fuchsia-zircon/src/handle.rs')
-rw-r--r--third_party/rust/fuchsia-zircon/src/handle.rs243
1 files changed, 243 insertions, 0 deletions
diff --git a/third_party/rust/fuchsia-zircon/src/handle.rs b/third_party/rust/fuchsia-zircon/src/handle.rs
new file mode 100644
index 0000000000..5c50f29f0e
--- /dev/null
+++ b/third_party/rust/fuchsia-zircon/src/handle.rs
@@ -0,0 +1,243 @@
+use {Port, Rights, Signals, Status, Time, WaitAsyncOpts, ok, sys};
+use std::marker::PhantomData;
+use std::mem;
+
+/// An object representing a Zircon
+/// [handle](https://fuchsia.googlesource.com/zircon/+/master/docs/handles.md).
+///
+/// Internally, it is represented as a 32-bit integer, but this wrapper enforces
+/// strict ownership semantics. The `Drop` implementation closes the handle.
+///
+/// This type represents the most general reference to a kernel object, and can
+/// be interconverted to and from more specific types. Those conversions are not
+/// enforced in the type system; attempting to use them will result in errors
+/// returned by the kernel. These conversions don't change the underlying
+/// representation, but do change the type and thus what operations are available.
+#[derive(Debug, Eq, PartialEq, Hash)]
+pub struct Handle(sys::zx_handle_t);
+
+impl AsHandleRef for Handle {
+ fn as_handle_ref(&self) -> HandleRef {
+ HandleRef { handle: self.0, phantom: Default::default() }
+ }
+}
+
+impl HandleBased for Handle {}
+
+impl Drop for Handle {
+ fn drop(&mut self) {
+ if self.0 != sys::ZX_HANDLE_INVALID {
+ unsafe { sys::zx_handle_close(self.0) };
+ }
+ }
+}
+
+impl Handle {
+ /// Initialize a handle backed by ZX_HANDLE_INVALID, the only safe non-handle.
+ pub fn invalid() -> Handle {
+ Handle(sys::ZX_HANDLE_INVALID)
+ }
+
+ /// If a raw handle is obtained from some other source, this method converts
+ /// it into a type-safe owned handle.
+ pub unsafe fn from_raw(raw: sys::zx_handle_t) -> Handle {
+ Handle(raw)
+ }
+
+ pub fn is_invalid(&self) -> bool {
+ self.0 == sys::ZX_HANDLE_INVALID
+ }
+
+ pub fn replace(self, rights: Rights) -> Result<Handle, Status> {
+ let handle = self.0;
+ let mut out = 0;
+ let status = unsafe { sys::zx_handle_replace(handle, rights.bits(), &mut out) };
+ ok(status).map(|()| Handle(out))
+ }
+}
+
+/// A borrowed reference to a `Handle`.
+///
+/// Mostly useful as part of a `WaitItem`.
+#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
+pub struct HandleRef<'a> {
+ handle: sys::zx_handle_t,
+ phantom: PhantomData<&'a sys::zx_handle_t>,
+}
+
+impl<'a> HandleRef<'a> {
+ pub fn raw_handle(&self) -> sys::zx_handle_t {
+ self.handle
+ }
+
+ pub fn duplicate(&self, rights: Rights) -> Result<Handle, Status> {
+ let handle = self.handle;
+ let mut out = 0;
+ let status = unsafe { sys::zx_handle_duplicate(handle, rights.bits(), &mut out) };
+ ok(status).map(|()| Handle(out))
+ }
+
+ pub fn signal(&self, clear_mask: Signals, set_mask: Signals) -> Result<(), Status> {
+ let handle = self.handle;
+ let status = unsafe { sys::zx_object_signal(handle, clear_mask.bits(), set_mask.bits()) };
+ ok(status)
+ }
+
+ pub fn wait(&self, signals: Signals, deadline: Time) -> Result<Signals, Status> {
+ let handle = self.handle;
+ let mut pending = Signals::empty().bits();
+ let status = unsafe {
+ sys::zx_object_wait_one(handle, signals.bits(), deadline.nanos(), &mut pending)
+ };
+ ok(status).map(|()| Signals::from_bits_truncate(pending))
+ }
+
+ pub fn wait_async(&self, port: &Port, key: u64, signals: Signals, options: WaitAsyncOpts)
+ -> Result<(), Status>
+ {
+ let handle = self.handle;
+ let status = unsafe {
+ sys::zx_object_wait_async(
+ handle, port.raw_handle(), key, signals.bits(), options as u32)
+ };
+ ok(status)
+ }
+}
+
+/// A trait to get a reference to the underlying handle of an object.
+pub trait AsHandleRef {
+ /// Get a reference to the handle. One important use of such a reference is
+ /// for `object_wait_many`.
+ fn as_handle_ref(&self) -> HandleRef;
+
+ /// Interpret the reference as a raw handle (an integer type). Two distinct
+ /// handles will have different raw values (so it can perhaps be used as a
+ /// key in a data structure).
+ fn raw_handle(&self) -> sys::zx_handle_t {
+ self.as_handle_ref().raw_handle()
+ }
+
+ /// Set and clear userspace-accessible signal bits on an object. Wraps the
+ /// [zx_object_signal](https://fuchsia.googlesource.com/zircon/+/master/docs/syscalls/object_signal.md)
+ /// syscall.
+ fn signal_handle(&self, clear_mask: Signals, set_mask: Signals) -> Result<(), Status> {
+ self.as_handle_ref().signal(clear_mask, set_mask)
+ }
+
+ /// Waits on a handle. Wraps the
+ /// [zx_object_wait_one](https://fuchsia.googlesource.com/zircon/+/master/docs/syscalls/object_wait_one.md)
+ /// syscall.
+ fn wait_handle(&self, signals: Signals, deadline: Time) -> Result<Signals, Status> {
+ self.as_handle_ref().wait(signals, deadline)
+ }
+
+ /// Causes packet delivery on the given port when the object changes state and matches signals.
+ /// [zx_object_wait_async](https://fuchsia.googlesource.com/zircon/+/master/docs/syscalls/object_wait_async.md)
+ /// syscall.
+ fn wait_async_handle(&self, port: &Port, key: u64, signals: Signals, options: WaitAsyncOpts)
+ -> Result<(), Status>
+ {
+ self.as_handle_ref().wait_async(port, key, signals, options)
+ }
+}
+
+impl<'a> AsHandleRef for HandleRef<'a> {
+ fn as_handle_ref(&self) -> HandleRef { *self }
+}
+
+/// A trait implemented by all handle-based types.
+///
+/// Note: it is reasonable for user-defined objects wrapping a handle to implement
+/// this trait. For example, a specific interface in some protocol might be
+/// represented as a newtype of `Channel`, and implement the `as_handle_ref`
+/// method and the `From<Handle>` trait to facilitate conversion from and to the
+/// interface.
+pub trait HandleBased: AsHandleRef + From<Handle> + Into<Handle> {
+ /// Duplicate a handle, possibly reducing the rights available. Wraps the
+ /// [zx_handle_duplicate](https://fuchsia.googlesource.com/zircon/+/master/docs/syscalls/handle_duplicate.md)
+ /// syscall.
+ fn duplicate_handle(&self, rights: Rights) -> Result<Self, Status> {
+ self.as_handle_ref().duplicate(rights).map(|handle| Self::from(handle))
+ }
+
+ /// Create a replacement for a handle, possibly reducing the rights available. This invalidates
+ /// the original handle. Wraps the
+ /// [zx_handle_replace](https://fuchsia.googlesource.com/zircon/+/master/docs/syscalls/handle_replace.md)
+ /// syscall.
+ fn replace_handle(self, rights: Rights) -> Result<Self, Status> {
+ <Self as Into<Handle>>::into(self)
+ .replace(rights).map(|handle| Self::from(handle))
+ }
+
+ /// Converts the value into its inner handle.
+ ///
+ /// This is a convenience function which simply forwards to the `Into` trait.
+ fn into_handle(self) -> Handle {
+ self.into()
+ }
+
+ /// Converts the handle into it's raw representation.
+ ///
+ /// The caller takes ownership over the raw handle, and must close or transfer it to avoid a handle leak.
+ fn into_raw(self) -> sys::zx_handle_t {
+ let h = self.into_handle();
+ let r = h.0;
+ mem::forget(h);
+ r
+ }
+
+ /// Creates an instance of this type from a handle.
+ ///
+ /// This is a convenience function which simply forwards to the `From` trait.
+ fn from_handle(handle: Handle) -> Self {
+ Self::from(handle)
+ }
+
+ /// Creates an instance of another handle-based type from this value's inner handle.
+ fn into_handle_based<H: HandleBased>(self) -> H {
+ H::from_handle(self.into_handle())
+ }
+
+ /// Creates an instance of this type from the inner handle of another
+ /// handle-based type.
+ fn from_handle_based<H: HandleBased>(h: H) -> Self {
+ Self::from_handle(h.into_handle())
+ }
+}
+
+/// A trait implemented by all handles for objects which have a peer.
+pub trait Peered: HandleBased {
+ /// Set and clear userspace-accessible signal bits on the object's peer. Wraps the
+ /// [zx_object_signal_peer](https://fuchsia.googlesource.com/zircon/+/master/docs/syscalls/object_signal.md)
+ /// syscall.
+ fn signal_peer(&self, clear_mask: Signals, set_mask: Signals) -> Result<(), Status> {
+ let handle = self.as_handle_ref().handle;
+ let status = unsafe {
+ sys::zx_object_signal_peer(handle, clear_mask.bits(), set_mask.bits())
+ };
+ ok(status)
+ }
+}
+
+/// A trait implemented by all handles for objects which can have a cookie attached.
+pub trait Cookied: HandleBased {
+ /// Get the cookie attached to this object, if any. Wraps the
+ /// [zx_object_get_cookie](https://fuchsia.googlesource.com/zircon/+/HEAD/docs/syscalls/object_get_cookie.md)
+ /// syscall.
+ fn get_cookie(&self, scope: &HandleRef) -> Result<u64, Status> {
+ let handle = self.as_handle_ref().handle;
+ let mut cookie = 0;
+ let status = unsafe { sys::zx_object_get_cookie(handle, scope.handle, &mut cookie) };
+ ok(status).map(|()| cookie)
+ }
+
+ /// Attach an opaque cookie to this object with the given scope. The cookie may be read or
+ /// changed in future only with the same scope. Wraps the
+ /// [zx_object_set_cookie](https://fuchsia.googlesource.com/zircon/+/HEAD/docs/syscalls/object_set_cookie.md)
+ /// syscall.
+ fn set_cookie(&self, scope: &HandleRef, cookie: u64) -> Result<(), Status> {
+ let handle = self.as_handle_ref().handle;
+ let status = unsafe { sys::zx_object_set_cookie(handle, scope.handle, cookie) };
+ ok(status)
+ }
+}