rel_ptr/traits.rs
1
2use std::ptr::NonNull;
3
4/// A nullable pointer, using NonNull<T>
5pub type Ptr<T> = Option<NonNull<T>>;
6
7/**
8 * `Delta` trait generalizes differences in
9 * memory locations to types like i8 and i16
10 *
11 * Note: certain invariants must be upheld to fulfill
12 * the unsafe contract of this trait, these invariants
13 * are detailed in each function
14 *
15 * This trait is intended to be used with `RelPtr`
16 */
17pub unsafe trait Delta: Copy + Eq {
18 /// Error of `Delta::sub`
19 type Error;
20
21 /**
22 * The difference between two pointers
23 *
24 * Note: for all values of `a: *mut u8`,
25 * you must enforce that `Delta::sub(a, a) == Delta::ZERO`
26 * and that the following function does not panic for all values
27 * of `a` and `b`
28 *
29 * ```ignore
30 * fn for_all_a_b(a: *mut u8, b: *mut u8) {
31 * if let Some(x) = Self::sub(a, b) {
32 * unsafe { assert_eq!(Self::add(x, b), a) }
33 * }
34 * }
35 * ```
36 */
37 fn sub(a: *mut u8, b: *mut u8) -> Result<Self, Self::Error>;
38
39 /**
40 * The difference between two pointers
41 *
42 * Note: for all values of `a: *mut u8`,
43 * you must enforce that `Delta::sub(a, a) == Delta::ZERO`
44 * and that the following function does not panic for all values
45 * of `a` and `b` if the difference between `a` and `b` is valid
46 *
47 * ```ignore
48 * fn for_all_a_b(a: *mut u8, b: *mut u8) {
49 * unsafe { assert_eq!(Self::add(Self::sub_unchecked(a, b), b), a) }
50 * }
51 * ```
52 *
53 * Safety:
54 *
55 * If the difference between `a` and `b` is not
56 * representable by `Self` is UB
57 */
58 unsafe fn sub_unchecked(a: *mut u8, b: *mut u8) -> Self;
59
60 /**
61 * Adds the difference (in `self`) to the pointer `a`
62 *
63 * Note: for all values of `a: *mut u8`,
64 * you must enforce that `Delta::add(Delta::ZERO, a) == a`
65 * and that the following function does not panic for all values
66 * of `a` and `b`
67 *
68 * ```ignore
69 * fn for_all_a_b(a: *mut u8, b: *mut u8) {
70 * if let Some(x) = Self::sub(a, b) {
71 * unsafe { assert_eq!(Self::add(x, b), a) }
72 * }
73 * }
74 * ```
75 *
76 * # Safety
77 * TODO
78 */
79 unsafe fn add(self, a: *const u8) -> *mut u8;
80}
81
82/// A index which can contain null
83///
84/// # Safety
85///
86/// ```ignore
87/// fn for_all_a(a: *mut u8) {
88/// assert_eq!(a, <Self as Delta>::add(Self::NULL, a));
89/// assert_eq!(Self::NULL, <Self as Delta>::sub(a, a));
90/// assert_eq!(Self::NULL, <Self as Delta>::sub_unchecked(a, a));
91/// }
92/// ```
93pub trait Nullable: Delta {
94 /// The value No change in two pointer locations,
95 const NULL: Self;
96}
97
98/**
99 * A trait to abstract over the sizedness of types,
100 * and to access metadata about a type
101 *
102 * If [Custom DST](https://github.com/rust-lang/rfcs/pull/2594) lands and stablizes,
103 * then it will replace `MetaData`
104 */
105pub unsafe trait MetaData {
106 /// the type of meta data a type carries
107 type Data: Copy + Eq;
108
109 /// decompose a type into a thin pointer and some metadata
110 fn data(this: &Self) -> Self::Data;
111
112 /// recompose a type from a thin pointer and some metadata
113 ///
114 /// it is guarenteed that the metadata is
115 /// * `ptr == None` `Self::Data` is undefined
116 /// * `ptr != None` generated from `MetaData::data`
117 unsafe fn compose(ptr: Ptr<u8>, data: Self::Data) -> Ptr<Self>;
118}
119
120// Thin pointers
121unsafe impl<T> MetaData for T {
122 type Data = ();
123
124 #[inline]
125 fn data(_: &Self) -> Self::Data {}
126
127 #[inline]
128 unsafe fn compose(ptr: Ptr<u8>, (): Self::Data) -> Ptr<Self> {
129 ptr.map(NonNull::cast)
130 }
131}
132
133// slices = ptr + len
134unsafe impl<T> MetaData for [T] {
135 type Data = usize;
136
137 #[inline]
138 fn data(this: &Self) -> Self::Data {
139 this.len()
140 }
141
142 #[inline]
143 unsafe fn compose(ptr: Ptr<u8>, data: Self::Data) -> Ptr<Self> {
144 Some(NonNull::from(
145 std::slice::from_raw_parts_mut(
146 ptr?.as_ptr() as *mut T,
147 data
148 )
149 ))
150 }
151}
152
153// str slices = ptr + len
154unsafe impl MetaData for str {
155 type Data = usize;
156
157 #[inline]
158 fn data(this: &Self) -> Self::Data {
159 this.len()
160 }
161
162 #[inline]
163 unsafe fn compose(ptr: Ptr<u8>, data: Self::Data) -> Ptr<Self> {
164 Some(NonNull::from(
165 std::str::from_utf8_unchecked_mut(std::slice::from_raw_parts_mut(
166 ptr?.as_ptr(),
167 data
168 ))
169 ))
170 }
171}