element_ptr/
lib.rs

1#![no_std]
2extern crate core;
3
4/// Returns the address of an inner element without creating unneeded
5/// intermediate references.
6///
7/// The general syntax is
8#[cfg_attr(doctest, doc = "````notest")] // don't doctest this.
9/// ```
10/// element_ptr!(base_ptr => /* element accesses */ )
11/// ````
12/// where `base_ptr` may be any expression that evaluates to a value of the following types:
13/// * [`*const T`]
14/// * [`*mut T`]
15/// * [`NonNull<T>`]
16/// 
17/// All accesses (besides a dereference) will maintain that pointer type of the input pointer.
18/// This is especially nice with [`NonNull<T>`] because it makes everything involving it much
19/// more ergonomic.
20/// 
21/// ### Element accesses
22/// 
23/// The following a table describes each of the possible accesses that can be inside the macro.
24/// These can all be chained by simply putting one after another.
25/// 
26/// | Access Kind     | Syntax        |           | Equivalent Pointer Expression                  |
27/// |-----------------|---------------|-----------|------------------------------------------------|
28/// | Field           | `.field`      |           | <code>[addr_of!]\((*ptr).field)</code>         |
29/// | Index           | `[index]`     |           | <code>ptr.[cast::\<T>]\().[add]\(index)</code> |
30/// | Add Offset      | `+ count`     | [1](#sl1) | <code>ptr.[add]\(count)</code>                 |
31/// | Sub Offset      | `- count`     | [1](#sl1) | <code>ptr.[sub]\(count)</code>                 |
32/// | Byte Add Offset | `u8+ bytes`   | [1](#sl1) | <code>ptr.[byte_add]\(bytes)</code>            |
33/// | Byte Sub Offset | `u8- bytes`   | [1](#sl1) | <code>ptr.[byte_sub]\(bytes)</code>            |
34/// | Cast            | `as T =>`     | [2](#sl2) | <code>ptr.[cast::\<T>]\()</code>               |
35/// | Dereference     | `.*`          | [3](#sl3) | <code>ptr.[read]\()</code>                     |
36/// | Grouping        | `( ... )`     |           | Just groups the inner accesses for clarity.    |
37/// 
38/// 1. <span id="sl1">
39///     `count`/`bytes` may either be an integer literal or an expression wrapped in parentheses.
40///     </span>
41/// 2. <span id="sl2">
42///     The `=>` may be omitted if the cast is the last access in a group.
43///     </span>
44/// 3. <span id="sl3">
45///     A dereference may return a value that is not a pointer only if it is the final access in the macro.
46///     In general it is encouraged to not do this and only use deferencing for inner pointers.
47///     </span>
48///
49/// # Safety
50/// * All of the [requirements][offsetreq] for [`offset()`] must be upheld. This is relevant for every
51///     access except for dereferencing, grouping, and casting.
52/// * The derefence access (`.*`) unconditionally reads from the pointer, and must not violate
53///     any [requirements][readreq] related to that.
54/// 
55/// # Examples
56/// 
57/// The following example should give you a general sense of what the macro is capable of,
58/// as well as a pretty good reference for how to use it.
59/// 
60/// ```
61/// use element_ptr::element_ptr;
62/// 
63/// use std::{
64///     alloc::{alloc, dealloc, Layout, handle_alloc_error},
65///     ptr,
66/// };
67/// 
68/// struct Example {
69///     field_one: u32,
70///     uninit: u32,
71///     child_struct: ChildStruct,
72///     another: *mut Example,
73/// }
74/// 
75/// struct ChildStruct {
76///     data: [&'static str; 6],
77/// }
78/// 
79/// let example = unsafe {
80///     // allocate two `Example`s on the heap, and then initialize them part by part.
81///     let layout = Layout::new::<Example>();
82///     
83///     let example = alloc(layout).cast::<Example>();
84///     if example.is_null() { handle_alloc_error(layout) };
85/// 
86///     let other_example = alloc(layout).cast::<Example>();
87///     if other_example.is_null() { handle_alloc_error(layout) };
88///     
89///     // Get the pointer to `field_one` and initialize it.
90///     element_ptr!(example => .field_one).write(100u32);
91///     // But the `uninit` field isn't initialized.
92///     // We can't take a reference to the struct without causing UB!
93///     
94///     // Now initialize the child struct.
95///     let string = "It is normally such a pain to manipulate raw pointers, isn't it?";
96///     
97///     // Get each word from the sentence
98///     for (index, word) in string.split(' ').enumerate() {
99///         // and push alternating words to each child struct.
100///         if index % 2 == 0 {
101///             // The index can be any arbitrary expression that evaluates to an usize.
102///             element_ptr!(example => .child_struct.data[index / 2]).write(word);
103///         } else {
104///             element_ptr!(other_example => .child_struct.data[index / 2]).write(word);
105///         }
106///     }
107///     
108///     element_ptr!(example => .another).write(other_example);
109///     
110///     example
111/// };
112/// 
113/// 
114/// // Now that the data is initialized, we can read data from the structs.
115/// 
116/// unsafe {
117///     // The `element_ptr!` macro will get a raw pointer to the data.
118///     let field_one_ptr: *mut u32 = element_ptr!(example => .field_one);
119///     
120///     // This means you can even get a pointer to a field that is not initialized.
121///     let uninit_field_ptr: *mut u32 = element_ptr!(example => .uninit);
122///     
123///     assert_eq!(*field_one_ptr, 100);
124/// 
125///     let seventh_word = element_ptr!(example => .child_struct.data[3]);
126///     
127///     assert_eq!(*seventh_word, "to");
128///     
129///     // The `.*` access is used here to go into the pointer to `other_example`.
130///     // Note that this requires the field `another` to be initialized, but not any
131///     // of the other fields in `example`.
132///     // As long as you don't use `.*`, you can be confident that no data will ever
133///     // be dereferenced.
134///     
135///     let second_word = element_ptr!(
136///         example => .another.*.child_struct.data[0]
137///     );
138/// 
139///     assert_eq!(*second_word, "is");
140/// 
141///     // Now lets deallocate everything so MIRI doesn't yell at me for leaking memory.
142///     let layout = Layout::new::<Example>();
143///     
144///     // Here as a convenience, we can cast the pointer to another type using `as T`.
145///     dealloc(element_ptr!(example => .another.* as u8), layout);
146///     // Of course this is simply the same as using `as *mut T`
147///     dealloc(example as *mut u8, layout);
148/// }
149/// ```
150/// 
151// the following links need to be explicitly put because rustdoc cannot refer to pointer methods.
152/// [addr_of!]: core::ptr::addr_of!
153/// [read]: https://doc.rust-lang.org/core/primitive.pointer.html#method.read
154/// [add]: https://doc.rust-lang.org/core/primitive.pointer.html#method.add
155/// [sub]: https://doc.rust-lang.org/core/primitive.pointer.html#method.sub
156/// [byte_add]: https://doc.rust-lang.org/core/primitive.pointer.html#method.byte_add
157/// [byte_sub]: https://doc.rust-lang.org/core/primitive.pointer.html#method.byte_sub
158/// [`offset()`]: https://doc.rust-lang.org/core/primitive.pointer.html#method.offset
159/// [offsetreq]: https://doc.rust-lang.org/core/primitive.pointer.html#safety-2
160/// [readreq]: https://doc.rust-lang.org/core/ptr/fn.read.html#safety
161/// [cast::\<T>]: https://doc.rust-lang.org/core/primitive.pointer.html#method.cast
162/// [`*const T`]: https://doc.rust-lang.org/core/primitive.pointer.html
163/// [`*mut T`]: https://doc.rust-lang.org/core/primitive.pointer.html
164/// [`NonNull<T>`]: core::ptr::NonNull
165// #[cfg(not(doctest))] // just don't doctest any of these. Macros are way too hard to do.
166pub use element_ptr_macro::element_ptr;
167
168#[doc(hidden)]
169pub mod helper {
170    use core::{marker::PhantomData, mem::ManuallyDrop};
171
172    pub unsafe trait Mutability {
173        type Var<T: ?Sized>;
174        type Raw<T: ?Sized>: IsPtr<M = Self, T = T>;
175    }
176    pub unsafe trait IsPtr: Copy {
177        type M: Mutability;
178        type T: ?Sized;
179    }
180
181    pub enum Const {}
182    pub enum Mut {}
183    // NonNull is safe here because all of the methods on `Pointer`
184    // and related freestanding functions all require the pointer
185    // to stay within the bounds of the allocated object.
186    // Because the null address is not ever part of an allocated object,
187    // this means that as long as a pointer is created from an existing `NonNull`,
188    // all uses that would invalidate the `NonNull` would be UB regardless.
189    pub enum NonNull {}
190
191    unsafe impl Mutability for Const {
192        type Var<T: ?Sized> = fn() -> T;
193        type Raw<T: ?Sized> = *const T;
194    }
195    unsafe impl Mutability for Mut {
196        type Var<T: ?Sized> = fn(T) -> T;
197        type Raw<T: ?Sized> = *mut T;
198    }
199    unsafe impl Mutability for NonNull {
200        type Var<T: ?Sized> = fn() -> T;
201        type Raw<T: ?Sized> = core::ptr::NonNull<T>;
202    }
203
204    unsafe impl<T: ?Sized> IsPtr for *mut T {
205        type M = Mut;
206        type T = T;
207    }
208    unsafe impl<T: ?Sized> IsPtr for *const T {
209        type M = Const;
210        type T = T;
211    }
212    unsafe impl<T: ?Sized> IsPtr for core::ptr::NonNull<T> {
213        type M = NonNull;
214        type T = T;
215    }
216
217    // Store a const pointer to do the manipulations with.
218    #[repr(transparent)]
219    pub struct Pointer<M: Mutability, T: ?Sized>(*const T, PhantomData<(M, M::Var<T>)>);
220
221    impl<M: Mutability, T> Clone for Pointer<M, T> {
222        fn clone(&self) -> Self {
223            *self
224        }
225    }
226    impl<M: Mutability, T> Copy for Pointer<M, T> {}
227
228    #[inline(always)]
229    pub const fn new_pointer<P: IsPtr>(ptr: P) -> Pointer<P::M, P::T> {
230        // Safety
231        // `IsPtr` guarantees that `P` may be transmuted into `*const P::T`.
232        unsafe { Pointer(transmute_unchecked::<P, *const P::T>(ptr), PhantomData) }
233    }
234
235    impl<M: Mutability, T> Pointer<M, T> {
236        /// Copies the address and type of a pointer to this pointer, keeping
237        /// mutability intact.
238        ///
239        /// # Safety
240        /// * `ptr` must be within the same allocated object as `self`.
241        #[inline(always)]
242        pub const unsafe fn copy_addr<E: ?Sized>(self, ptr: *const E) -> Pointer<M, E> {
243            Pointer(ptr, PhantomData)
244        }
245        /// Returns the inner pointer type.
246        #[inline(always)]
247        pub const fn into_inner(self) -> M::Raw<T> {
248            // Safety
249            // `Pointer<M, T>` can only be created with from a `P: IsPtr`,
250            // an `IsPtr` guarantees that `*const T` may be cast to `M::Raw<T>`.
251            unsafe { transmute_unchecked(self.0) }
252        }
253        /// Returns a `*const T` that points to the same place as this pointer.
254        #[inline(always)]
255        pub const fn into_const(self) -> *const T {
256            self.0
257        }
258        /// Casts this pointer to another type.
259        #[inline(always)]
260        pub const fn cast<U>(self) -> Pointer<M, U> {
261            Pointer(self.0.cast(), PhantomData)
262        }
263        /// Calculates the offset of this pointer in units of `T`.
264        ///
265        /// This function is a wrapper around [`pointer::add()`].
266        /// See its documentation for more info including the safety requirements.
267        ///
268        /// [`pointer::add()`]: https://doc.rust-lang.org/core/primitive.pointer.html#method.add
269        #[inline(always)]
270        pub const unsafe fn add(mut self, count: usize) -> Self {
271            self.0 = self.0.add(count);
272            self
273        }
274        /// Calculates the offset of this pointer in units of `T`.
275        ///
276        /// This function is a wrapper around [`pointer::sub()`].
277        /// See its documentation for more info including the safety requirements.
278        ///
279        /// [`pointer::sub()`]: https://doc.rust-lang.org/core/primitive.pointer.html#method.sub
280        #[inline(always)]
281        pub const unsafe fn sub(mut self, count: usize) -> Self {
282            self.0 = self.0.sub(count);
283            self
284        }
285        /// Calculates the offset of this pointer in units of `T`.
286        ///
287        /// This function is a wrapper around [`pointer::offset()`].
288        /// See its documentation for more info including the safety requirements.
289        ///
290        /// [`pointer::offset()`]: https://doc.rust-lang.org/core/primitive.pointer.html#method.offset
291        #[inline(always)]
292        pub const unsafe fn offset(mut self, count: isize) -> Self {
293            self.0 = self.0.offset(count);
294            self
295        }
296        /// Calculates the offset of this pointer in bytes.
297        ///
298        /// This function is a wrapper around [`pointer::byte_add()`].
299        /// See its documentation for more info including the safety requirements.
300        ///
301        /// [`pointer::byte_add()`]: https://doc.rust-lang.org/core/primitive.pointer.html#method.byte_add
302        #[inline(always)]
303        pub const unsafe fn byte_add(mut self, count: usize) -> Self {
304            self.0 = self.0.byte_add(count);
305            self
306        }
307        /// Calculates the offset of this pointer in bytes.
308        ///
309        /// This function is a wrapper around [`pointer::byte_sub()`].
310        /// See its documentation for more info including the safety requirements.
311        ///
312        /// [`pointer::byte_sub()`]: https://doc.rust-lang.org/core/primitive.pointer.html#method.byte_sub
313        #[inline(always)]
314        pub const unsafe fn byte_sub(mut self, count: usize) -> Self {
315            self.0 = self.0.byte_sub(count);
316            self
317        }
318        /// Calculates the offset of this pointer in bytes.
319        ///
320        /// This function is a wrapper around [`pointer::byte_offset()`].
321        /// See its documentation for more info including the safety requirements.
322        ///
323        /// [`pointer::byte_offset()`]: https://doc.rust-lang.org/core/primitive.pointer.html#method.byte_offset
324        #[inline(always)]
325        pub const unsafe fn byte_offset(mut self, count: isize) -> Self {
326            self.0 = self.0.byte_offset(count);
327            self
328        }
329        /// Reads the value from behind this pointer.
330        ///
331        /// This function is a wrapper around [`pointer::read()`].
332        /// See its documentation for more info including the safety requirements.
333        ///
334        /// [`pointer::read()`]: https://doc.rust-lang.org/core/primitive.pointer.html#method.read
335        #[inline(always)]
336        pub const unsafe fn read(self) -> T {
337            self.0.read()
338        }
339    }
340
341    // This is a freestanding function to make the error message
342    // when T doesn't implement `CanIndex` slightly better.
343    #[inline(always)]
344    pub const unsafe fn index<M: Mutability, T>(
345        ptr: Pointer<M, T>,
346        index: usize,
347    ) -> Pointer<M, T::E>
348    where
349        T: CanIndex,
350    {
351        let base = ptr.into_const().cast::<T::E>();
352        let ptr = base.add(index);
353        Pointer(ptr, PhantomData)
354    }
355
356    /// Transmutes from `F` to `T`. All of the normal safety requirements
357    /// for transmutations hold here.
358    ///
359    /// This is just `transmute_copy` except by value.
360    pub const unsafe fn transmute_unchecked<F, T>(from: F) -> T {
361        #[repr(C)]
362        union Transmute<F, T> {
363            from: ManuallyDrop<F>,
364            to: ManuallyDrop<T>,
365        }
366        ManuallyDrop::into_inner(
367            Transmute {
368                from: ManuallyDrop::new(from),
369            }
370            .to,
371        )
372    }
373
374    /// A trait to mark which types may be trivially indexed with pointer arithmetic.
375    ///
376    /// # Safety
377    /// * `E` must be the element of the sequence.
378    /// * `Self` must be able to be transmuted to a pointer type.
379    ///     Specifically, a pointer must reside at offset 0 of `Self`,
380    ///     and it must point to a consecutive sequence of `E`s.
381    pub unsafe trait CanIndex {
382        type E;
383    }
384
385    unsafe impl<T, const L: usize> CanIndex for [T; L] {
386        type E = T;
387    }
388
389    unsafe impl<T> CanIndex for [T] {
390        type E = T;
391    }
392
393    /// Used to make element_ptr! unsafe and not give a million
394    /// different "needs an unsafe block" notification.
395    #[doc(hidden)]
396    #[inline(always)]
397    pub unsafe fn element_ptr_unsafe() {}
398}