Skip to content

Commit

Permalink
Change how handles are constructed, so that we can ensure non-null ha…
Browse files Browse the repository at this point in the history
…ndles (#136)

* Change how handles are constructed, to ensure non-null handles

* Make Win32WindowHandle.hinstance properly optional

* Add changelog entries

* breaking: Make integer handles use non-zero types

* Make X display and connection handles nullable

This is a conservative choice for now; we can later iterate on this decision, and figure out if the handles should actually be non-null.
  • Loading branch information
madsmtm committed Aug 31, 2023
1 parent 4611ee8 commit 69d9eac
Show file tree
Hide file tree
Showing 10 changed files with 462 additions and 324 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

## Unreleased

* **Breaking:** Raw pointer handles now use `NonNull` where appropriate, to avoid null pointer dereferences.
* **Breaking:** Renamed `empty` methods to `new`, and take parameters in most of those, to better match normal Rust semantics.
* **Breaking:** `HasRaw(Display/Window)Handle::raw_(display/window)_handle` returns a result indicating if fetching the window handle failed (#122).
* **Breaking:** Remove the `Active/ActiveHandle` types from the public API (#126).
* **Breaking:** Remove `AppKitWindowHandle::ns_window` and `UiKitWindowHandle::ui_window` since they can be retrieved from the view (#129).
Expand Down
51 changes: 29 additions & 22 deletions src/android.rs
Original file line number Diff line number Diff line change
@@ -1,43 +1,50 @@
use core::ffi::c_void;
use core::ptr;
use core::ptr::NonNull;

/// Raw display handle for Android.
///
/// ## Construction
/// ```
/// # use raw_window_handle::AndroidDisplayHandle;
/// let mut display_handle = AndroidDisplayHandle::empty();
/// /* set fields */
/// ```
#[non_exhaustive]
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct AndroidDisplayHandle;
pub struct AndroidDisplayHandle {}

impl AndroidDisplayHandle {
pub fn empty() -> Self {
/// Create a new empty display handle.
///
///
/// # Example
///
/// ```
/// # use raw_window_handle::AndroidDisplayHandle;
/// let handle = AndroidDisplayHandle::new();
/// ```
pub fn new() -> Self {
Self {}
}
}

/// Raw window handle for Android NDK.
///
/// ## Construction
/// ```
/// # use raw_window_handle::AndroidNdkWindowHandle;
/// let mut window_handle = AndroidNdkWindowHandle::empty();
/// /* set fields */
/// ```
#[non_exhaustive]
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct AndroidNdkWindowHandle {
/// A pointer to an `ANativeWindow`.
pub a_native_window: *mut c_void,
pub a_native_window: NonNull<c_void>,
}

impl AndroidNdkWindowHandle {
pub fn empty() -> Self {
Self {
a_native_window: ptr::null_mut(),
}
/// Create a new handle to an `ANativeWindow`.
///
///
/// # Example
///
/// ```
/// # use core::ptr::NonNull;
/// # use raw_window_handle::AndroidNdkWindowHandle;
/// # type ANativeWindow = ();
/// #
/// let ptr: NonNull<ANativeWindow>;
/// # ptr = NonNull::from(&());
/// let handle = AndroidNdkWindowHandle::new(ptr.cast());
/// ```
pub fn new(a_native_window: NonNull<c_void>) -> Self {
Self { a_native_window }
}
}
51 changes: 29 additions & 22 deletions src/appkit.rs
Original file line number Diff line number Diff line change
@@ -1,43 +1,50 @@
use core::ffi::c_void;
use core::ptr;
use core::ptr::NonNull;

/// Raw display handle for AppKit.
///
/// ## Construction
/// ```
/// # use raw_window_handle::AppKitDisplayHandle;
/// let mut display_handle = AppKitDisplayHandle::empty();
/// /* set fields */
/// ```
#[non_exhaustive]
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct AppKitDisplayHandle;
pub struct AppKitDisplayHandle {}

impl AppKitDisplayHandle {
pub fn empty() -> Self {
/// Create a new empty display handle.
///
///
/// # Example
///
/// ```
/// # use raw_window_handle::AppKitDisplayHandle;
/// let handle = AppKitDisplayHandle::new();
/// ```
pub fn new() -> Self {
Self {}
}
}

/// Raw window handle for AppKit.
///
/// ## Construction
/// ```
/// # use raw_window_handle::AppKitWindowHandle;
/// let mut window_handle = AppKitWindowHandle::empty();
/// /* set fields */
/// ```
#[non_exhaustive]
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct AppKitWindowHandle {
/// A pointer to an `NSView` object.
pub ns_view: *mut c_void,
pub ns_view: NonNull<c_void>,
}

impl AppKitWindowHandle {
pub fn empty() -> Self {
Self {
ns_view: ptr::null_mut(),
}
/// Create a new handle to a view.
///
///
/// # Example
///
/// ```
/// # use core::ptr::NonNull;
/// # use raw_window_handle::AppKitWindowHandle;
/// # type NSView = ();
/// #
/// let view: &NSView;
/// # view = &();
/// let handle = AppKitWindowHandle::new(NonNull::from(view).cast());
/// ```
pub fn new(ns_view: NonNull<c_void>) -> Self {
Self { ns_view }
}
}
55 changes: 33 additions & 22 deletions src/haiku.rs
Original file line number Diff line number Diff line change
@@ -1,46 +1,57 @@
use core::ffi::c_void;
use core::ptr;
use core::ptr::NonNull;

/// Raw display handle for Haiku.
///
/// ## Construction
/// ```
/// # use raw_window_handle::HaikuDisplayHandle;
/// let mut display_handle = HaikuDisplayHandle::empty();
/// /* set fields */
/// ```
#[non_exhaustive]
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct HaikuDisplayHandle;
pub struct HaikuDisplayHandle {}

impl HaikuDisplayHandle {
pub fn empty() -> Self {
/// Create a new empty display handle.
///
///
/// # Example
///
/// ```
/// # use raw_window_handle::HaikuDisplayHandle;
/// let handle = HaikuDisplayHandle::new();
/// ```
pub fn new() -> Self {
Self {}
}
}

/// Raw window handle for Haiku.
///
/// ## Construction
/// ```
/// # use raw_window_handle::HaikuWindowHandle;
/// let mut window_handle = HaikuWindowHandle::empty();
/// /* set fields */
/// ```
#[non_exhaustive]
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct HaikuWindowHandle {
/// A pointer to a BWindow object
pub b_window: *mut c_void,
pub b_window: NonNull<c_void>,
/// A pointer to a BDirectWindow object that might be null
pub b_direct_window: *mut c_void,
pub b_direct_window: Option<NonNull<c_void>>,
}

impl HaikuWindowHandle {
pub fn empty() -> Self {
/// Create a new handle to a window.
///
///
/// # Example
///
/// ```
/// # use core::ptr::NonNull;
/// # use raw_window_handle::HaikuWindowHandle;
/// # type BWindow = ();
/// #
/// let b_window: NonNull<BWindow>;
/// # b_window = NonNull::from(&());
/// let mut handle = HaikuWindowHandle::new(b_window.cast());
/// // Optionally set `b_direct_window`.
/// handle.b_direct_window = None;
/// ```
pub fn new(b_window: NonNull<c_void>) -> Self {
Self {
b_window: ptr::null_mut(),
b_direct_window: ptr::null_mut(),
b_window,
b_direct_window: None,
}
}
}
4 changes: 2 additions & 2 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ use core::fmt;
///
/// # Safety
///
/// Users can safely assume that non-`null`/`0` fields are valid handles, and it is up to the
/// Users can safely assume that pointers and non-zero fields are valid, and it is up to the
/// implementer of this trait to ensure that condition is upheld.
///
/// Despite that qualification, implementers should still make a best-effort attempt to fill in all
Expand Down Expand Up @@ -205,7 +205,7 @@ pub enum RawWindowHandle {
///
/// # Safety
///
/// Users can safely assume that non-`null`/`0` fields are valid handles, and it is up to the
/// Users can safely assume that pointers and non-zero fields are valid, and it is up to the
/// implementer of this trait to ensure that condition is upheld.
///
/// Despite that qualification, implementers should still make a best-effort attempt to fill in all
Expand Down
53 changes: 31 additions & 22 deletions src/redox.rs
Original file line number Diff line number Diff line change
@@ -1,43 +1,52 @@
use core::ffi::c_void;
use core::ptr;
use core::ptr::NonNull;

/// Raw display handle for the Redox operating system.
///
/// ## Construction
/// ```
/// # use raw_window_handle::OrbitalDisplayHandle;
/// let mut display_handle = OrbitalDisplayHandle::empty();
/// /* set fields */
/// ```
#[non_exhaustive]
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct OrbitalDisplayHandle;
pub struct OrbitalDisplayHandle {}

impl OrbitalDisplayHandle {
pub fn empty() -> Self {
/// Create a new empty display handle.
///
///
/// # Example
///
/// ```
/// # use raw_window_handle::OrbitalDisplayHandle;
/// let handle = OrbitalDisplayHandle::new();
/// ```
pub fn new() -> Self {
Self {}
}
}

/// Raw window handle for the Redox operating system.
///
/// ## Construction
/// ```
/// # use raw_window_handle::OrbitalWindowHandle;
/// let mut window_handle = OrbitalWindowHandle::empty();
/// /* set fields */
/// ```
#[non_exhaustive]
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct OrbitalWindowHandle {
/// A pointer to an orbclient window.
pub window: *mut c_void,
// TODO(madsmtm): I think this is a file descriptor, so perhaps it should
// actually use `std::os::fd::RawFd`, or some sort of integer instead?
pub window: NonNull<c_void>,
}

impl OrbitalWindowHandle {
pub fn empty() -> Self {
Self {
window: ptr::null_mut(),
}
/// Create a new handle to a window.
///
///
/// # Example
///
/// ```
/// # use core::ptr::NonNull;
/// # use raw_window_handle::OrbitalWindowHandle;
/// # type Window = ();
/// #
/// let window: NonNull<Window>;
/// # window = NonNull::from(&());
/// let mut handle = OrbitalWindowHandle::new(window.cast());
/// ```
pub fn new(window: NonNull<c_void>) -> Self {
Self { window }
}
}

0 comments on commit 69d9eac

Please sign in to comment.