diff options
| author | Simon Sapin <simon.sapin@exyr.org> | 2017-06-29 01:00:00 +0200 |
|---|---|---|
| committer | Simon Sapin <simon.sapin@exyr.org> | 2017-07-22 20:37:52 +0200 |
| commit | e9af03a22279b62ded4c7ea897d5ac3a9b54728c (patch) | |
| tree | 74c970d0be0c79dab61ba3196d808aa665a05a44 | |
| parent | f8d485f53dbe87e0d7b4ad14904fd7b0447a8cbe (diff) | |
| download | rust-e9af03a22279b62ded4c7ea897d5ac3a9b54728c.tar.gz rust-e9af03a22279b62ded4c7ea897d5ac3a9b54728c.zip | |
Add `new_checked(…) -> Option<Self>` to NonZero, Unique, and Shared.
| -rw-r--r-- | src/libcore/nonzero.rs | 70 | ||||
| -rw-r--r-- | src/libcore/ptr.rs | 14 |
2 files changed, 65 insertions, 19 deletions
diff --git a/src/libcore/nonzero.rs b/src/libcore/nonzero.rs index 977438051d9..0564d73dd6d 100644 --- a/src/libcore/nonzero.rs +++ b/src/libcore/nonzero.rs @@ -16,22 +16,48 @@ use ops::CoerceUnsized; /// Unsafe trait to indicate what types are usable with the NonZero struct -pub unsafe trait Zeroable {} - -unsafe impl<T:?Sized> Zeroable for *const T {} -unsafe impl<T:?Sized> Zeroable for *mut T {} -unsafe impl Zeroable for isize {} -unsafe impl Zeroable for usize {} -unsafe impl Zeroable for i8 {} -unsafe impl Zeroable for u8 {} -unsafe impl Zeroable for i16 {} -unsafe impl Zeroable for u16 {} -unsafe impl Zeroable for i32 {} -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 {} +pub unsafe trait Zeroable { + /// Whether this value is zero + fn is_zero(&self) -> bool; +} + +macro_rules! impl_zeroable_for_pointer_types { + ( $( $Ptr: ty )+ ) => { + $( + /// For fat pointers to be considered "zero", only the "data" part needs to be null. + unsafe impl<T: ?Sized> Zeroable for $Ptr { + #[inline] + fn is_zero(&self) -> bool { + // Cast because `is_null` is only available on thin pointers + (*self as *mut u8).is_null() + } + } + )+ + } +} + +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 /// 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. /// You must indeed ensure that the value is actually "non-zero". #[inline] - pub const unsafe fn new(inner: T) -> NonZero<T> { + pub const unsafe fn new(inner: T) -> Self { 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. pub fn get(self) -> T { self.0 diff --git a/src/libcore/ptr.rs b/src/libcore/ptr.rs index b19e07b8578..e83ca63834a 100644 --- a/src/libcore/ptr.rs +++ b/src/libcore/ptr.rs @@ -1110,10 +1110,15 @@ impl<T: ?Sized> Unique<T> { /// # Safety /// /// `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 } } + /// 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. pub fn as_ptr(self) -> *mut T { self.pointer.get() as *mut T @@ -1224,10 +1229,15 @@ impl<T: ?Sized> Shared<T> { /// # Safety /// /// `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 } } + /// 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. pub fn as_ptr(self) -> *mut T { self.pointer.get() as *mut T |
