optional
optional copied to clipboard
Usage of Optioned for raw pointers
Can Optioned be used for raw pointers across FFI boundaries?
I was thinking of something like this:
diff --git a/src/lib.rs b/src/lib.rs
index fed33fb..ed09e1e 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -913,6 +913,14 @@ impl Noned for char {
fn get_none() -> char { unsafe { std::char::from_u32_unchecked(std::u32::MAX) } }
}
+impl<T> Noned for *const T {
+ #[inline]
+ fn is_none(&self) -> bool { self.is_null() }
+
+ #[inline]
+ fn get_none() -> *const T { std::ptr::null() }
+}
+
///Equality within Optioned
pub trait OptEq {
/// Is the other optioned equal to this one?
diff --git a/tests/optioned.rs b/tests/optioned.rs
index fbc8259..e50ebdf 100644
--- a/tests/optioned.rs
+++ b/tests/optioned.rs
@@ -10,3 +10,15 @@ fn optioned_is_some_or_none() {
let opt_u32_none : Optioned<u32> = Optioned::none();
assert!(opt_u32_none.is_none());
}
+
+#[test]
+fn optioned_ptr() {
+ struct Foo;
+
+ let foo_box = Box::new(Foo{});
+ let opt_ptr : Optioned<*const Foo> = Optioned::some(Box::into_raw(foo_box));
+ assert!(opt_ptr.is_some());
+
+ let opt_ptr_none : Optioned<*const Foo> = Optioned::none();
+ assert!(opt_ptr_none.is_none());
+}
Will that work for returning nullable raw pointers from FFI functions, or would that not work?
(I can provide a pull request if this is sound.)
That would be wildly unsafe and provide no benefit over Option<&T>
(which is already using the implicit null for the None).
Ok. Where is the unsafety coming from? (I'm thinking about an FFI context where pointer handling is already unsafe.)
My main use case was replacing this:
#[no_mangle]
extern "C" fn foo() -> *const Foo {
if asdf() {
return ptr::null();
}
...
}
...with an approach where the possibility of a null pointer is already visible in the signature (like an Option<&Foo>
), but where the behavior when interacting with the function from C is the same.
That is exactly the problem: Your pointers carry no information about their validity. But I guess we don't add any unsafety in the FFI case.
Ok. Would you be willing to accept a pull request with such a change?
As written above, it would allow me to replace this:
#[no_mangle]
extern "C" fn foo() -> *const Foo {
if asdf() {
return ptr::null();
}
...
}
...with this:
#[no_mangle]
extern "C" fn foo() -> Optioned<*const Foo> {
if asdf() {
return Optioned::none();
}
}
...in an FFI context where the signature is pre-defined (e.g. when dealing with JNI).
I think this would be more idiomatic Rust than just return ptr::null()
, and it would provide the additional benefit that returning a null pointer with Optioned::some(...)
would panic at runtime.
Your pointers carry no information about their validity.
Dereferencing raw pointers must be done in an unsafe block, so the user should be aware.
Sorry for letting you wait so long. My internet connection is a bit wonky these days (changing providers), so I'll have to look into it later.