rust: types: add `try_from_foreign()` method
authorObei Sideg <linux@obei.io>
Mon, 29 Jan 2024 06:45:27 +0000 (06:45 +0000)
committerMiguel Ojeda <ojeda@kernel.org>
Sun, 25 Feb 2024 18:17:31 +0000 (19:17 +0100)
Currently `ForeignOwnable::from_foreign()` only works for non-null
pointers for the existing `impl`s (e.g. `Box`, `Arc`). In turn, this
means callers may write code like:

```rust
// `p` is a pointer that may be null.
if p.is_null() {
    None
} else {
    unsafe { Some(Self::from_foreign(ptr)) }
}
```

Add a `try_from_foreign()` method to the trait with a default
implementation that returns `None` if `ptr` is null, otherwise
`Some(from_foreign(ptr))`, so that it can be used by callers instead.

Link: https://github.com/Rust-for-Linux/linux/issues/1057
Signed-off-by: Obei Sideg <linux@obei.io>
Reviewed-by: Alice Ryhl <aliceryhl@google.com>
Reviewed-by: Trevor Gross <tmgross@umich.edu>
Link: https://lore.kernel.org/r/0100018d53f737f8-80c1fe97-0019-40d7-ab69-b1b192785cd7-000000@email.amazonses.com
[ Fixed intra-doc links, improved `SAFETY` comment and reworded commit. ]
Signed-off-by: Miguel Ojeda <ojeda@kernel.org>
rust/kernel/types.rs

index 8aabe348b19473e9deefd59a93e2d9c1b717caac..aa77bad9bce48655fa1b7ddb700710172cca759a 100644 (file)
@@ -46,6 +46,25 @@ pub trait ForeignOwnable: Sized {
     /// Additionally, all instances (if any) of values returned by [`ForeignOwnable::borrow`] for
     /// this object must have been dropped.
     unsafe fn from_foreign(ptr: *const core::ffi::c_void) -> Self;
+
+    /// Tries to convert a foreign-owned object back to a Rust-owned one.
+    ///
+    /// A convenience wrapper over [`ForeignOwnable::from_foreign`] that returns [`None`] if `ptr`
+    /// is null.
+    ///
+    /// # Safety
+    ///
+    /// `ptr` must either be null or satisfy the safety requirements for
+    /// [`ForeignOwnable::from_foreign`].
+    unsafe fn try_from_foreign(ptr: *const core::ffi::c_void) -> Option<Self> {
+        if ptr.is_null() {
+            None
+        } else {
+            // SAFETY: Since `ptr` is not null here, then `ptr` satisfies the safety requirements
+            // of `from_foreign` given the safety requirements of this function.
+            unsafe { Some(Self::from_foreign(ptr)) }
+        }
+    }
 }
 
 impl<T: 'static> ForeignOwnable for Box<T> {