xref: /relibc/ralloc/src/ptr.rs (revision 146a5db98f2dcff608e1f3a30330e0cf1527786e)
1 //! Pointer wrappers.
2 
3 use core::nonzero::NonZero;
4 use core::{ops, marker};
5 
6 /// A pointer wrapper type.
7 ///
8 /// A wrapper around a raw non-null `*mut T` that indicates that the possessor of this wrapper owns
9 /// the referent.
10 #[derive(PartialEq, Debug, Clone)]
11 pub struct Pointer<T> {
12     /// The internal pointer.
13     ptr: NonZero<*mut T>,
14     /// Associated phantom data.
15     ///
16     /// This indicates that we _own_ T.
17     _phantom: marker::PhantomData<T>,
18 }
19 
20 impl<T> Pointer<T> {
21     /// Create a new `Pointer` from a raw pointer.
22     ///
23     /// # Safety
24     ///
25     /// This function is unsafe since a null pointer can cause UB, due to `Pointer` being
26     /// non-nullable.
27     #[inline]
28     pub unsafe fn new(ptr: *mut T) -> Pointer<T> {
29         // For the sake of nice debugging, make some assertions.
30         debug_assert!(!ptr.is_null(), "Null pointer!");
31 
32         Pointer {
33             ptr: NonZero::new(ptr),
34             _phantom: marker::PhantomData,
35         }
36     }
37 
38     /// Create an "empty" `Pointer`.
39     ///
40     /// This acts as a null pointer, although it is represented by 0x1 instead of 0x0.
41     #[inline]
42     pub const fn empty() -> Pointer<T> {
43         Pointer {
44             ptr: unsafe { NonZero::new(0x1 as *mut T) },
45             _phantom: marker::PhantomData,
46         }
47     }
48 
49     /// Cast this pointer into a pointer to another type.
50     ///
51     /// This will simply transmute the pointer, leaving the actual data unmodified.
52     #[inline]
53     pub fn cast<U>(self) -> Pointer<U> {
54         Pointer {
55             ptr: unsafe { NonZero::new(*self as *mut U) },
56             _phantom: marker::PhantomData,
57         }
58     }
59 
60     /// Offset this pointer.
61     ///
62     /// This will add some value multiplied by the size of T to the pointer.
63     ///
64     /// # Safety
65     ///
66     /// This is unsafe, due to OOB offsets being undefined behavior.
67     #[inline]
68     pub unsafe fn offset(self, diff: isize) -> Pointer<T> {
69         Pointer::new(self.ptr.offset(diff))
70     }
71 }
72 
73 unsafe impl<T: Send> Send for Pointer<T> {}
74 unsafe impl<T: Sync> Sync for Pointer<T> {}
75 
76 impl<'a, T> From<&'a [T]> for Pointer<T> {
77     fn from(from: &[T]) -> Pointer<T> {
78         unsafe { Pointer::new(from.as_ptr() as *mut T) }
79     }
80 }
81 
82 impl<T> ops::Deref for Pointer<T> {
83     type Target = *mut T;
84 
85     #[inline]
86     fn deref(&self) -> &*mut T {
87         &self.ptr
88     }
89 }
90 
91 #[cfg(test)]
92 mod test {
93     use super::*;
94 
95     #[test]
96     fn test_pointer() {
97         let mut x = [b'a', b'b'];
98 
99         unsafe {
100             let ptr = Pointer::new(&mut x[0] as *mut u8);
101             assert_eq!(**ptr, b'a');
102             assert_eq!(**ptr.clone().cast::<[u8; 1]>(), [b'a']);
103             assert_eq!(**ptr.offset(1), b'b');
104         }
105     }
106 
107     #[test]
108     fn test_empty() {
109         assert_eq!(*Pointer::<u8>::empty() as usize, 1);
110     }
111 }
112