Skip to content

Commit e9af03a

Browse files
committed
Add new_checked(…) -> Option<Self> to NonZero, Unique, and Shared.
1 parent f8d485f commit e9af03a

File tree

2 files changed

+65
-19
lines changed

2 files changed

+65
-19
lines changed

src/libcore/nonzero.rs

Lines changed: 53 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -16,22 +16,48 @@
1616
use ops::CoerceUnsized;
1717

1818
/// Unsafe trait to indicate what types are usable with the NonZero struct
19-
pub unsafe trait Zeroable {}
20-
21-
unsafe impl<T:?Sized> Zeroable for *const T {}
22-
unsafe impl<T:?Sized> Zeroable for *mut T {}
23-
unsafe impl Zeroable for isize {}
24-
unsafe impl Zeroable for usize {}
25-
unsafe impl Zeroable for i8 {}
26-
unsafe impl Zeroable for u8 {}
27-
unsafe impl Zeroable for i16 {}
28-
unsafe impl Zeroable for u16 {}
29-
unsafe impl Zeroable for i32 {}
30-
unsafe impl Zeroable for u32 {}
31-
unsafe impl Zeroable for i64 {}
32-
unsafe impl Zeroable for u64 {}
33-
unsafe impl Zeroable for i128 {}
34-
unsafe impl Zeroable for u128 {}
19+
pub unsafe trait Zeroable {
20+
/// Whether this value is zero
21+
fn is_zero(&self) -> bool;
22+
}
23+
24+
macro_rules! impl_zeroable_for_pointer_types {
25+
( $( $Ptr: ty )+ ) => {
26+
$(
27+
/// For fat pointers to be considered "zero", only the "data" part needs to be null.
28+
unsafe impl<T: ?Sized> Zeroable for $Ptr {
29+
#[inline]
30+
fn is_zero(&self) -> bool {
31+
// Cast because `is_null` is only available on thin pointers
32+
(*self as *mut u8).is_null()
33+
}
34+
}
35+
)+
36+
}
37+
}
38+
39+
macro_rules! impl_zeroable_for_integer_types {
40+
( $( $Int: ty )+ ) => {
41+
$(
42+
unsafe impl Zeroable for $Int {
43+
#[inline]
44+
fn is_zero(&self) -> bool {
45+
*self == 0
46+
}
47+
}
48+
)+
49+
}
50+
}
51+
52+
impl_zeroable_for_pointer_types! {
53+
*const T
54+
*mut T
55+
}
56+
57+
impl_zeroable_for_integer_types! {
58+
usize u8 u16 u32 u64 u128
59+
isize i8 i16 i32 i64 i128
60+
}
3561

3662
/// A wrapper type for raw pointers and integers that will never be
3763
/// NULL or 0 that might allow certain optimizations.
@@ -43,10 +69,20 @@ impl<T: Zeroable> NonZero<T> {
4369
/// Creates an instance of NonZero with the provided value.
4470
/// You must indeed ensure that the value is actually "non-zero".
4571
#[inline]
46-
pub const unsafe fn new(inner: T) -> NonZero<T> {
72+
pub const unsafe fn new(inner: T) -> Self {
4773
NonZero(inner)
4874
}
4975

76+
/// Creates an instance of NonZero with the provided value.
77+
#[inline]
78+
pub fn new_checked(inner: T) -> Option<Self> {
79+
if inner.is_zero() {
80+
None
81+
} else {
82+
Some(NonZero(inner))
83+
}
84+
}
85+
5086
/// Gets the inner value.
5187
pub fn get(self) -> T {
5288
self.0

src/libcore/ptr.rs

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1110,10 +1110,15 @@ impl<T: ?Sized> Unique<T> {
11101110
/// # Safety
11111111
///
11121112
/// `ptr` must be non-null.
1113-
pub const unsafe fn new(ptr: *mut T) -> Unique<T> {
1113+
pub const unsafe fn new(ptr: *mut T) -> Self {
11141114
Unique { pointer: NonZero::new(ptr), _marker: PhantomData }
11151115
}
11161116

1117+
/// Creates a new `Unique` if `ptr` is non-null.
1118+
pub fn new_checked(ptr: *mut T) -> Option<Self> {
1119+
NonZero::new_checked(ptr as *const T).map(|nz| Unique { pointer: nz, _marker: PhantomData })
1120+
}
1121+
11171122
/// Acquires the underlying `*mut` pointer.
11181123
pub fn as_ptr(self) -> *mut T {
11191124
self.pointer.get() as *mut T
@@ -1224,10 +1229,15 @@ impl<T: ?Sized> Shared<T> {
12241229
/// # Safety
12251230
///
12261231
/// `ptr` must be non-null.
1227-
pub unsafe fn new(ptr: *mut T) -> Self {
1232+
pub const unsafe fn new(ptr: *mut T) -> Self {
12281233
Shared { pointer: NonZero::new(ptr), _marker: PhantomData }
12291234
}
12301235

1236+
/// Creates a new `Shared` if `ptr` is non-null.
1237+
pub fn new_checked(ptr: *mut T) -> Option<Self> {
1238+
NonZero::new_checked(ptr as *const T).map(|nz| Shared { pointer: nz, _marker: PhantomData })
1239+
}
1240+
12311241
/// Acquires the underlying `*mut` pointer.
12321242
pub fn as_ptr(self) -> *mut T {
12331243
self.pointer.get() as *mut T

0 commit comments

Comments
 (0)