Skip to content

Commit 4aa92c2

Browse files
committed
Implement ptr::try_cast_aligned
`ptr::try_cast_aligned`: link tracking issue `ptr::try_cast_aligned`: remove forgotten `const` `NonNull::try_cast_aligned`: fix doctest `ptr::try_cast_aligned`: #[inline] ptr::`try_cast_aligned`: fix doc Implement `ptr::try_cast_aligned` and `NonNull::try_cast_aligned`.
1 parent ae3b909 commit 4aa92c2

File tree

3 files changed

+85
-0
lines changed

3 files changed

+85
-0
lines changed

library/core/src/ptr/const_ptr.rs

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,34 @@ impl<T: ?Sized> *const T {
6666
self as _
6767
}
6868

69+
/// Try to cast to a pointer of another type by checking aligment.
70+
///
71+
/// If the pointer is properly aligned to the target type, it will be
72+
/// cast to the target type. Otherwise, `None` is returned.
73+
///
74+
/// # Examples
75+
///
76+
/// ```rust
77+
/// #![feature(pointer_try_cast_aligned)]
78+
///
79+
/// let aligned: *const u8 = 0x1000 as _;
80+
///
81+
/// // i32 has at most 4-byte alignment, so this will succeed
82+
/// assert!(aligned.try_cast_aligned::<i32>().is_some());
83+
///
84+
/// let unaligned: *const u8 = 0x1001 as _;
85+
///
86+
/// // i32 has at least 2-byte alignment, so this will fail
87+
/// assert!(unaligned.try_cast_aligned::<i32>().is_none());
88+
/// ```
89+
#[unstable(feature = "pointer_try_cast_aligned", issue = "141221")]
90+
#[must_use = "this returns the result of the operation, \
91+
without modifying the original"]
92+
#[inline]
93+
pub fn try_cast_aligned<U>(self) -> Option<*const U> {
94+
if self.is_aligned_to(align_of::<U>()) { Some(self.cast()) } else { None }
95+
}
96+
6997
/// Uses the address value in a new pointer of another type.
7098
///
7199
/// This operation will ignore the address part of its `meta` operand and discard existing

library/core/src/ptr/mut_ptr.rs

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,34 @@ impl<T: ?Sized> *mut T {
4848
self as _
4949
}
5050

51+
/// Try to cast to a pointer of another type by checking aligment.
52+
///
53+
/// If the pointer is properly aligned to the target type, it will be
54+
/// cast to the target type. Otherwise, `None` is returned.
55+
///
56+
/// # Examples
57+
///
58+
/// ```rust
59+
/// #![feature(pointer_try_cast_aligned)]
60+
///
61+
/// let aligned: *mut u8 = 0x1000 as _;
62+
///
63+
/// // i32 has at most 4-byte alignment, so this will succeed
64+
/// assert!(aligned.try_cast_aligned::<i32>().is_some());
65+
///
66+
/// let unaligned: *mut u8 = 0x1001 as _;
67+
///
68+
/// // i32 has at least 2-byte alignment, so this will fail
69+
/// assert!(unaligned.try_cast_aligned::<i32>().is_none());
70+
/// ```
71+
#[unstable(feature = "pointer_try_cast_aligned", issue = "141221")]
72+
#[must_use = "this returns the result of the operation, \
73+
without modifying the original"]
74+
#[inline]
75+
pub fn try_cast_aligned<U>(self) -> Option<*mut U> {
76+
if self.is_aligned_to(align_of::<U>()) { Some(self.cast()) } else { None }
77+
}
78+
5179
/// Uses the address value in a new pointer of another type.
5280
///
5381
/// This operation will ignore the address part of its `meta` operand and discard existing

library/core/src/ptr/non_null.rs

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -488,6 +488,35 @@ impl<T: ?Sized> NonNull<T> {
488488
unsafe { NonNull { pointer: self.as_ptr() as *mut U } }
489489
}
490490

491+
/// Try to cast to a pointer of another type by checking aligment.
492+
///
493+
/// If the pointer is properly aligned to the target type, it will be
494+
/// cast to the target type. Otherwise, `None` is returned.
495+
///
496+
/// # Examples
497+
///
498+
/// ```rust
499+
/// #![feature(pointer_try_cast_aligned)]
500+
/// use std::ptr::NonNull;
501+
///
502+
/// let aligned: NonNull<u8> = NonNull::new(0x1000 as _).unwrap();
503+
///
504+
/// // i32 has at most 4-byte alignment, so this will succeed
505+
/// assert!(aligned.try_cast_aligned::<i32>().is_some());
506+
///
507+
/// let unaligned: NonNull<u8> = NonNull::new(0x1001 as _).unwrap();
508+
///
509+
/// // i32 has at least 2-byte alignment, so this will fail
510+
/// assert!(unaligned.try_cast_aligned::<i32>().is_none());
511+
/// ```
512+
#[unstable(feature = "pointer_try_cast_aligned", issue = "141221")]
513+
#[must_use = "this returns the result of the operation, \
514+
without modifying the original"]
515+
#[inline]
516+
pub fn try_cast_aligned<U>(self) -> Option<NonNull<U>> {
517+
if self.is_aligned_to(align_of::<U>()) { Some(self.cast()) } else { None }
518+
}
519+
491520
/// Adds an offset to a pointer.
492521
///
493522
/// `count` is in units of T; e.g., a `count` of 3 represents a pointer

0 commit comments

Comments
 (0)