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}