Skip to main content

nearest/
near.rs

1use std::{fmt, marker::PhantomData, num::NonZero, ops::Deref};
2
3use crate::{Flat, Patch, emitter::Pos};
4
5/// A self-relative pointer stored as a 4-byte `NonZero<i32>` offset.
6///
7/// # Layout
8///
9/// `#[repr(C)]` — 4 bytes, `align_of::<i32>()` alignment:
10///
11/// | Offset | Field | Type           |
12/// |--------|-------|----------------|
13/// | 0      | `off` | `NonZero<i32>` |
14///
15/// The offset is relative to the address of `off` itself (not the start of
16/// the region). Non-zero guarantee ensures `Near<T>` never points to itself.
17///
18/// `Near<T>` is **not** `Copy` or `Clone` — moving it would invalidate the
19/// self-relative offset. Use it only inside [`Region`](crate::Region) buffers
20/// built by the emitter.
21///
22/// # Soundness
23///
24/// **Provenance recovery**: [`get`](Self::get) computes the target address by
25/// adding the stored `i32` offset to the address of the offset field itself.
26/// Because `&self.off` has provenance over only 4 bytes (insufficient for the
27/// target `T`), the method uses `with_exposed_provenance` to recover the
28/// full allocation's provenance — previously exposed by `AlignedBuf::grow`.
29/// Miri validates this pattern with no UB detected.
30///
31/// **Non-zero invariant**: The offset is `NonZero<i32>`, so a `Near<T>` can
32/// never point to itself (offset 0). This is enforced by the emitter's
33/// `patch_near` method which panics on `target == at`.
34pub struct Near<T> {
35  off: NonZero<i32>,
36  _type: PhantomData<T>,
37}
38
39// SAFETY: Near contains only a NonZero<i32> and PhantomData — no Drop, no heap.
40// Unconditional impl: Near<T> is always Flat regardless of T, since it stores only
41// an offset, not an actual T. This avoids circular trait bounds in recursive types.
42unsafe impl<T> Flat for Near<T> {
43  unsafe fn deep_copy(&self, p: &mut impl Patch, at: Pos) {
44    // SAFETY: Caller guarantees `at` was allocated for `Near<T>`.
45    // Byte-copy the 4-byte offset. Containing struct's deep_copy handles pointer following.
46    unsafe {
47      p.write_bytes(at, std::ptr::from_ref(self).cast(), size_of::<Self>());
48    }
49  }
50}
51
52impl<T: Flat> Near<T> {
53  /// Resolve the self-relative offset to a reference.
54  ///
55  /// # Examples
56  ///
57  /// ```
58  /// use nearest::{Flat, Near, Region};
59  ///
60  /// #[derive(Flat, Debug)]
61  /// struct Wrapper { inner: Near<u32> }
62  ///
63  /// let region = Region::new(Wrapper::make(42u32));
64  /// assert_eq!(*region.inner.get(), 42);
65  ///
66  /// // Deref also works (Near<T> implements Deref<Target = T>).
67  /// assert_eq!(*region.inner, 42);
68  /// ```
69  #[must_use]
70  pub fn get(&self) -> &T {
71    // SAFETY: The offset was written by `Emitter::patch_near` which guarantees
72    // the target lies within the same `Region` buffer. The region keeps the
73    // buffer alive and properly aligned for `T`.
74    //
75    // Strict provenance is not possible here: `&self.off` has provenance over
76    // only 4 bytes, but `T` may live anywhere in the buffer. A derived pointer
77    // (e.g. `wrapping_byte_offset`) would fail Stacked Borrows retagging when
78    // the target `&T` is larger than 4 bytes.
79    //
80    // Instead, `with_exposed_provenance` recovers the full allocation's
81    // provenance (exposed by `AlignedBuf::grow`). This triggers Miri
82    // int-to-ptr cast warnings but is not UB.
83    unsafe {
84      let base = std::ptr::from_ref(&self.off).cast::<u8>();
85      let target = base.addr().wrapping_add_signed(self.off.get() as isize);
86      &*std::ptr::with_exposed_provenance::<T>(target)
87    }
88  }
89}
90
91impl<T: Flat> Deref for Near<T> {
92  type Target = T;
93
94  fn deref(&self) -> &T {
95    self.get()
96  }
97}
98
99impl<T: Flat + fmt::Debug> fmt::Debug for Near<T> {
100  fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
101    fmt::Debug::fmt(self.get(), f)
102  }
103}