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}