Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Ptr::to_option method #6604

Closed
wants to merge 2 commits into from
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 51 additions & 0 deletions src/libcore/ptr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
use cast;
use libc;
use libc::{c_void, size_t};
use option::{Option, Some, None};
use sys;

#[cfg(not(test))] use cmp::{Eq, Ord};
Expand Down Expand Up @@ -209,6 +210,7 @@ pub unsafe fn array_each<T>(arr: **T, cb: &fn(*T)) {
pub trait Ptr<T> {
fn is_null(&const self) -> bool;
fn is_not_null(&const self) -> bool;
unsafe fn to_option(&const self) -> Option<&T>;
fn offset(&self, count: uint) -> Self;
}

Expand All @@ -222,6 +224,23 @@ impl<T> Ptr<T> for *T {
#[inline(always)]
fn is_not_null(&const self) -> bool { is_not_null(*self) }

///
/// Returns `None` if the pointer is null, or else returns the value wrapped
/// in `Some`.
///
/// # Safety Notes
///
/// While this method is useful for null-safety, it is important to note
/// that this is still an unsafe operation because the returned value could
/// be pointing to invalid memory.
///
#[inline(always)]
unsafe fn to_option(&const self) -> Option<&T> {
if self.is_null() { None } else {
Some(cast::transmute(*self))
}
}

/// Calculates the offset from a pointer.
#[inline(always)]
fn offset(&self, count: uint) -> *T { offset(*self, count) }
Expand All @@ -237,6 +256,23 @@ impl<T> Ptr<T> for *mut T {
#[inline(always)]
fn is_not_null(&const self) -> bool { is_not_null(*self) }

///
/// Returns `None` if the pointer is null, or else returns the value wrapped
/// in `Some`.
///
/// # Safety Notes
///
/// While this method is useful for null-safety, it is important to note
/// that this is still an unsafe operation because the returned value could
/// be pointing to invalid memory.
///
#[inline(always)]
unsafe fn to_option(&const self) -> Option<&T> {
if self.is_null() { None } else {
Some(cast::transmute(*self))
}
}

/// Calculates the offset from a mutable pointer.
#[inline(always)]
fn offset(&self, count: uint) -> *mut T { mut_offset(*self, count) }
Expand Down Expand Up @@ -423,6 +459,21 @@ pub mod ptr_tests {
assert!(mq.is_not_null());
}

#[test]
fn test_to_option() {
let p: *int = null();
// FIXME (#6641): Usage of unsafe methods in safe code doesn't cause an error.
assert_eq!(p.to_option(), None);

let q: *int = &2;
assert_eq!(q.to_option().unwrap(), &2); // FIXME (#6641)

let p: *mut int = mut_null();
assert_eq!(p.to_option(), None); // FIXME (#6641)

let q: *mut int = &mut 2;
assert_eq!(q.to_option().unwrap(), &2); // FIXME (#6641)
}

#[test]
fn test_ptr_array_each_with_len() {
Expand Down