deferred_reference/pointer_length.rs
1/// A trait which is only implemented for pointers for which the length of the pointee
2/// can be determined without creating a reference to the pointee and without accessing
3/// the pointee. This means that the pointer is not dereferenced.
4///
5/// # Example
6/// ```
7/// use deferred_reference::PointerLength;
8/// let array = [0usize; 1024];
9/// assert_eq!(1024, PointerLength::len(core::ptr::addr_of!(array)));
10/// ```
11///
12/// # Safety
13/// This trait is unsafe. The implementor must promise never to access or create a reference
14/// to the pointee.
15pub unsafe trait PointerLength {
16 /// Obtains the length of the pointee, without creating an intermediate reference.
17 fn len(ptr: *const Self) -> usize;
18}
19
20// SAFETY: <*const [T]>::len() extracts the length from the fat pointer without
21// SAFETY: dereferencing the pointer, so this is safe.
22#[cfg(feature = "slice_ptr_len")]
23unsafe impl<T> PointerLength for [T] {
24 #[inline]
25 fn len(ptr: *const Self) -> usize {
26 // requires #![feature(slice_ptr_len)] at crate level
27 <*const [T]>::len(ptr)
28 }
29}
30
31// SAFETY: this impl does not create any references, it merely panics
32#[cfg(not(feature = "slice_ptr_len"))]
33unsafe impl<T> PointerLength for [T] {
34 #[track_caller]
35 #[cold]
36 fn len(_: *const Self) -> usize {
37 // without the `slice_ptr_len` feature, all we can do is panic in order to keep the implementation sound.
38 panic!("calling this method on slice pointers requires the `slice_ptr_len` feature to be enabled")
39 }
40}
41
42// SAFETY: the array length is known at compile time due to the `const N: usize`.
43// SAFETY: the pointer is not needed nor dereferenced when returning a constant.
44unsafe impl <T, const N: usize> PointerLength for [T; N] {
45 #[inline]
46 fn len(_: *const Self) -> usize {
47 N
48 }
49}