From fc15179aeef9ce40599b4de6a3f9c37ae31587af Mon Sep 17 00:00:00 2001 From: Nikolai Vazquez Date: Tue, 22 Dec 2020 16:04:36 -0500 Subject: [PATCH 1/2] Add `as_{,mut_}ptr` methods to `Option` These enable simpler conversion from `Option<&{,mut} T>` to `*const T` and `Option<&mut T>` to `*mut T`. These operations are the opposite of `<*const T>::as_ref` and `<*mut T>::as_mut`. In FFI, the types `Option<&T>` and `Option<&mut T>` are semantically equivalent to `*const T` and `*mut T`, and they can even be safely used in place of those types. The `self` type in each method is a reference because `Option<&mut T>` does not implement `Copy`. These methods would otherwise move `self`, making them inconvenient or sometimes impossible to use. --- library/core/src/option.rs | 78 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 78 insertions(+) diff --git a/library/core/src/option.rs b/library/core/src/option.rs index 1afa30f5843f8..95656b1c808c6 100644 --- a/library/core/src/option.rs +++ b/library/core/src/option.rs @@ -152,6 +152,7 @@ use crate::pin::Pin; use crate::{ convert, fmt, hint, mem, ops::{self, Deref, DerefMut}, + ptr, }; /// The `Option` type. See [the module level documentation](self) for more. @@ -985,6 +986,83 @@ impl Option { } } +impl Option<&T> { + /// Converts from `Option<&T>` (or `&Option<&T>`) to `*const T`. + /// + /// This is the opposite of `<*const T>::as_ref`. + /// + /// # Examples + /// + /// ``` + /// #![feature(option_as_ptr)] + /// + /// let opt = Some(&3); + /// let ptr = opt.as_ptr(); + /// + /// assert_eq!(opt, unsafe { ptr.as_ref() }); + /// ``` + #[unstable(feature = "option_as_ptr", issue = "none")] + #[inline] + pub const fn as_ptr(&self) -> *const T { + match self { + Some(x) => *x, + None => ptr::null(), + } + } +} + +impl Option<&mut T> { + /// Converts from `Option<&mut T>` (or `&Option<&mut T>`) to `*const T`. + /// + /// # Examples + /// + /// ``` + /// #![feature(option_as_ptr)] + /// + /// let mut x = 3; + /// let opt = Some(&mut x); + /// let ptr = opt.as_ptr(); + /// + /// assert_eq!(x, unsafe { *ptr }); + /// ``` + #[unstable(feature = "option_as_ptr", issue = "none")] + #[rustc_const_unstable(feature = "option_as_ptr", issue = "none")] + #[inline] + pub const fn as_ptr(&self) -> *const T { + match self { + Some(x) => *x, + None => ptr::null(), + } + } + + /// Converts from `Option<&mut T>` (or `&mut Option<&T>`) to `*mut T`. + /// + /// This is the opposite of `<*mut T>::as_mut`. + /// + /// # Examples + /// + /// ``` + /// #![feature(option_as_ptr)] + /// + /// let mut x = 3; + /// let mut opt = Some(&mut x); + /// + /// let ptr = opt.as_mut_ptr(); + /// unsafe { *ptr = 4 }; + /// + /// assert_eq!(x, 4); + /// ``` + #[unstable(feature = "option_as_ptr", issue = "none")] + #[rustc_const_unstable(feature = "option_as_ptr", issue = "none")] + #[inline] + pub const fn as_mut_ptr(&mut self) -> *mut T { + match self { + Some(x) => *x, + None => ptr::null_mut(), + } + } +} + impl Option<&T> { /// Maps an `Option<&T>` to an `Option` by copying the contents of the /// option. From 1e0627ec3f49c028c752f7216e0ff4a2ee2aee50 Mon Sep 17 00:00:00 2001 From: Nikolai Vazquez Date: Tue, 22 Dec 2020 16:41:47 -0500 Subject: [PATCH 2/2] Add missing "mut" to docs --- library/core/src/option.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/core/src/option.rs b/library/core/src/option.rs index 95656b1c808c6..f0c75813624b1 100644 --- a/library/core/src/option.rs +++ b/library/core/src/option.rs @@ -1035,7 +1035,7 @@ impl Option<&mut T> { } } - /// Converts from `Option<&mut T>` (or `&mut Option<&T>`) to `*mut T`. + /// Converts from `Option<&mut T>` (or `&mut Option<&mut T>`) to `*mut T`. /// /// This is the opposite of `<*mut T>::as_mut`. ///