diff options
Diffstat (limited to 'third_party/rust/cubeb-core/src/ffi_types.rs')
-rw-r--r-- | third_party/rust/cubeb-core/src/ffi_types.rs | 242 |
1 files changed, 242 insertions, 0 deletions
diff --git a/third_party/rust/cubeb-core/src/ffi_types.rs b/third_party/rust/cubeb-core/src/ffi_types.rs new file mode 100644 index 0000000000..221dccfa28 --- /dev/null +++ b/third_party/rust/cubeb-core/src/ffi_types.rs @@ -0,0 +1,242 @@ +// Copyright © 2017-2018 Mozilla Foundation +// +// This program is made available under an ISC-style license. See the +// accompanying file LICENSE for details. + +use std::cell::UnsafeCell; +pub struct Opaque(UnsafeCell<()>); + +/// Generate a newtype wrapper `$owned` and reference wrapper +/// `$borrowed` around a POD FFI type that lives on the heap. +macro_rules! ffi_type_heap { + ( + $(#[$impl_attr:meta])* + type CType = $ctype:ty; + $(fn drop = $drop:expr;)* + $(fn clone = $clone:expr;)* + $(#[$owned_attr:meta])* + pub struct $owned:ident; + $(#[$borrowed_attr:meta])* + pub struct $borrowed:ident; + ) => { + $(#[$owned_attr])* + pub struct $owned(*mut $ctype); + + impl $owned { + /// # Safety + /// + /// This function is unsafe because it dereferences the given `ptr` pointer. + /// The caller should ensure that pointer is valid. + #[inline] + pub unsafe fn from_ptr(ptr: *mut $ctype) -> $owned { + $owned(ptr) + } + + #[inline] + pub fn as_ptr(&self) -> *mut $ctype { + self.0 + } + } + + $( + impl Drop for $owned { + #[inline] + fn drop(&mut self) { + unsafe { $drop(self.0) } + } + } + )* + + $( + impl Clone for $owned { + #[inline] + fn clone(&self) -> $owned { + unsafe { + let handle: *mut $ctype = $clone(self.0); + $owned::from_ptr(handle) + } + } + } + + impl ::std::borrow::ToOwned for $borrowed { + type Owned = $owned; + #[inline] + fn to_owned(&self) -> $owned { + unsafe { + let handle: *mut $ctype = $clone(self.as_ptr()); + $owned::from_ptr(handle) + } + } + } + )* + + impl ::std::ops::Deref for $owned { + type Target = $borrowed; + + #[inline] + fn deref(&self) -> &$borrowed { + unsafe { $borrowed::from_ptr(self.0) } + } + } + + impl ::std::ops::DerefMut for $owned { + #[inline] + fn deref_mut(&mut self) -> &mut $borrowed { + unsafe { $borrowed::from_ptr_mut(self.0) } + } + } + + impl ::std::borrow::Borrow<$borrowed> for $owned { + #[inline] + fn borrow(&self) -> &$borrowed { + &**self + } + } + + impl ::std::convert::AsRef<$borrowed> for $owned { + #[inline] + fn as_ref(&self) -> &$borrowed { + &**self + } + } + + $(#[$borrowed_attr])* + pub struct $borrowed($crate::ffi_types::Opaque); + + impl $borrowed { + /// # Safety + /// + /// This function is unsafe because it dereferences the given `ptr` pointer. + /// The caller should ensure that pointer is valid. + #[inline] + pub unsafe fn from_ptr<'a>(ptr: *mut $ctype) -> &'a Self { + &*(ptr as *mut _) + } + + /// # Safety + /// + /// This function is unsafe because it dereferences the given `ptr` pointer. + /// The caller should ensure that pointer is valid. + #[inline] + pub unsafe fn from_ptr_mut<'a>(ptr: *mut $ctype) -> &'a mut Self { + &mut *(ptr as *mut _) + } + + #[inline] + pub fn as_ptr(&self) -> *mut $ctype { + self as *const _ as *mut _ + } + } + + impl ::std::fmt::Debug for $borrowed { + fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { + let ptr = self as *const $borrowed as usize; + f.debug_tuple(stringify!($borrowed)) + .field(&ptr) + .finish() + } + } + } +} + +/// Generate a newtype wrapper `$owned` and reference wrapper +/// `$borrowed` around a POD FFI type that lives on the stack. +macro_rules! ffi_type_stack { + ($(#[$impl_attr:meta])* + type CType = $ctype:ty; + $(#[$owned_attr:meta])* + pub struct $owned:ident; + $(#[$borrowed_attr:meta])* + pub struct $borrowed:ident; + ) => { + $(#[$owned_attr])* + pub struct $owned($ctype); + + impl $owned { + pub fn as_ptr(&self) -> *mut $ctype { + &self.0 as *const $ctype as *mut $ctype + } + } + + impl Default for $owned { + fn default() -> $owned { + $owned(Default::default()) + } + } + + impl From<$ctype> for $owned { + fn from(x: $ctype) -> $owned { + $owned(x) + } + } + + impl ::std::ops::Deref for $owned { + type Target = $borrowed; + + #[inline] + fn deref(&self) -> &$borrowed { + let ptr = &self.0 as *const $ctype as *mut $ctype; + unsafe { $borrowed::from_ptr(ptr) } + } + } + + impl ::std::ops::DerefMut for $owned { + #[inline] + fn deref_mut(&mut self) -> &mut $borrowed { + let ptr = &self.0 as *const $ctype as *mut $ctype; + unsafe { $borrowed::from_ptr_mut(ptr) } + } + } + + impl ::std::borrow::Borrow<$borrowed> for $owned { + #[inline] + fn borrow(&self) -> &$borrowed { + &**self + } + } + + impl ::std::convert::AsRef<$borrowed> for $owned { + #[inline] + fn as_ref(&self) -> &$borrowed { + &**self + } + } + + $(#[$borrowed_attr])* + pub struct $borrowed($crate::ffi_types::Opaque); + + impl $borrowed { + /// # Safety + /// + /// This function is unsafe because it dereferences the given `ptr` pointer. + /// The caller should ensure that pointer is valid. + #[inline] + pub unsafe fn from_ptr<'a>(ptr: *mut $ctype) -> &'a Self { + &*(ptr as *mut _) + } + + /// # Safety + /// + /// This function is unsafe because it dereferences the given `ptr` pointer. + /// The caller should ensure that pointer is valid. + #[inline] + pub unsafe fn from_ptr_mut<'a>(ptr: *mut $ctype) -> &'a mut Self { + &mut *(ptr as *mut _) + } + + #[inline] + pub fn as_ptr(&self) -> *mut $ctype { + self as *const _ as *mut _ + } + } + + impl ::std::fmt::Debug for $borrowed { + fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { + let ptr = self as *const $borrowed as usize; + f.debug_tuple(stringify!($borrowed)) + .field(&ptr) + .finish() + } + } + } +} |