Add new_checked(…) -> Option<Self> to NonZero, Unique, and Shared.

This commit is contained in:
Simon Sapin
2017-06-29 01:00:00 +02:00
parent f8d485f53d
commit e9af03a222
2 changed files with 64 additions and 18 deletions

View File

@@ -16,22 +16,48 @@
use ops::CoerceUnsized; use ops::CoerceUnsized;
/// Unsafe trait to indicate what types are usable with the NonZero struct /// Unsafe trait to indicate what types are usable with the NonZero struct
pub unsafe trait Zeroable {} pub unsafe trait Zeroable {
/// Whether this value is zero
fn is_zero(&self) -> bool;
}
unsafe impl<T:?Sized> Zeroable for *const T {} macro_rules! impl_zeroable_for_pointer_types {
unsafe impl<T:?Sized> Zeroable for *mut T {} ( $( $Ptr: ty )+ ) => {
unsafe impl Zeroable for isize {} $(
unsafe impl Zeroable for usize {} /// For fat pointers to be considered "zero", only the "data" part needs to be null.
unsafe impl Zeroable for i8 {} unsafe impl<T: ?Sized> Zeroable for $Ptr {
unsafe impl Zeroable for u8 {} #[inline]
unsafe impl Zeroable for i16 {} fn is_zero(&self) -> bool {
unsafe impl Zeroable for u16 {} // Cast because `is_null` is only available on thin pointers
unsafe impl Zeroable for i32 {} (*self as *mut u8).is_null()
unsafe impl Zeroable for u32 {} }
unsafe impl Zeroable for i64 {} }
unsafe impl Zeroable for u64 {} )+
unsafe impl Zeroable for i128 {} }
unsafe impl Zeroable for u128 {} }
macro_rules! impl_zeroable_for_integer_types {
( $( $Int: ty )+ ) => {
$(
unsafe impl Zeroable for $Int {
#[inline]
fn is_zero(&self) -> bool {
*self == 0
}
}
)+
}
}
impl_zeroable_for_pointer_types! {
*const T
*mut T
}
impl_zeroable_for_integer_types! {
usize u8 u16 u32 u64 u128
isize i8 i16 i32 i64 i128
}
/// A wrapper type for raw pointers and integers that will never be /// A wrapper type for raw pointers and integers that will never be
/// NULL or 0 that might allow certain optimizations. /// NULL or 0 that might allow certain optimizations.
@@ -43,10 +69,20 @@ impl<T: Zeroable> NonZero<T> {
/// Creates an instance of NonZero with the provided value. /// Creates an instance of NonZero with the provided value.
/// You must indeed ensure that the value is actually "non-zero". /// You must indeed ensure that the value is actually "non-zero".
#[inline] #[inline]
pub const unsafe fn new(inner: T) -> NonZero<T> { pub const unsafe fn new(inner: T) -> Self {
NonZero(inner) NonZero(inner)
} }
/// Creates an instance of NonZero with the provided value.
#[inline]
pub fn new_checked(inner: T) -> Option<Self> {
if inner.is_zero() {
None
} else {
Some(NonZero(inner))
}
}
/// Gets the inner value. /// Gets the inner value.
pub fn get(self) -> T { pub fn get(self) -> T {
self.0 self.0

View File

@@ -1110,10 +1110,15 @@ impl<T: ?Sized> Unique<T> {
/// # Safety /// # Safety
/// ///
/// `ptr` must be non-null. /// `ptr` must be non-null.
pub const unsafe fn new(ptr: *mut T) -> Unique<T> { pub const unsafe fn new(ptr: *mut T) -> Self {
Unique { pointer: NonZero::new(ptr), _marker: PhantomData } Unique { pointer: NonZero::new(ptr), _marker: PhantomData }
} }
/// Creates a new `Unique` if `ptr` is non-null.
pub fn new_checked(ptr: *mut T) -> Option<Self> {
NonZero::new_checked(ptr as *const T).map(|nz| Unique { pointer: nz, _marker: PhantomData })
}
/// Acquires the underlying `*mut` pointer. /// Acquires the underlying `*mut` pointer.
pub fn as_ptr(self) -> *mut T { pub fn as_ptr(self) -> *mut T {
self.pointer.get() as *mut T self.pointer.get() as *mut T
@@ -1224,10 +1229,15 @@ impl<T: ?Sized> Shared<T> {
/// # Safety /// # Safety
/// ///
/// `ptr` must be non-null. /// `ptr` must be non-null.
pub unsafe fn new(ptr: *mut T) -> Self { pub const unsafe fn new(ptr: *mut T) -> Self {
Shared { pointer: NonZero::new(ptr), _marker: PhantomData } Shared { pointer: NonZero::new(ptr), _marker: PhantomData }
} }
/// Creates a new `Shared` if `ptr` is non-null.
pub fn new_checked(ptr: *mut T) -> Option<Self> {
NonZero::new_checked(ptr as *const T).map(|nz| Shared { pointer: nz, _marker: PhantomData })
}
/// Acquires the underlying `*mut` pointer. /// Acquires the underlying `*mut` pointer.
pub fn as_ptr(self) -> *mut T { pub fn as_ptr(self) -> *mut T {
self.pointer.get() as *mut T self.pointer.get() as *mut T