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}