SelfRef

Struct SelfRef 

Source
pub struct SelfRef<T: ?Sized + PointerRecomposition, I: Offset = isize>(/* private fields */);
Expand description

A pointer that stores offsets instead of addresses, enabling movable self-referential structures.

Unlike regular pointers that become invalid when data moves, SelfRef stores the relative distance to its target. This offset remains valid regardless of where the containing structure is moved in memory - stack, heap, or anywhere else.

The magic happens through the offset type I: use i8 for tiny 1-byte pointers with ±127 byte range, i16 for 2-byte pointers with ±32KB range, or larger types for bigger structures.

use movable_ref::SelfRef;

struct Node {
    value: String,
    self_ref: SelfRef<String, i16>,  // 2 bytes instead of 8
}

impl Node {
    fn new(value: String) -> Self {
        let mut node = Self {
            value,
            self_ref: SelfRef::null(),
        };
        node.self_ref.set(&mut node.value).unwrap();
        node
    }
}

// Works everywhere - stack, heap, vectors
let mut node = Node::new("test".into());
let boxed = Box::new(node);
let mut vec = vec![*boxed];
let base = &vec[0] as *const _ as *const u8;
let value = unsafe { vec[0].self_ref.get_ref_from_base_unchecked(base) };

§Safety Considerations

SelfRef uses unsafe internally but provides safe setup methods. The main safety requirement is that once set, the relative positions of the pointer and target must not change. Moving the entire structure is always safe - it’s only internal layout changes that cause issues.

Special care needed with packed structs: field reordering during drops can invalidate offsets.

Implementations§

Source§

impl<T: ?Sized + PointerRecomposition, I: Nullable> SelfRef<T, I>

Source

pub fn null() -> Self

Creates an unset relative pointer.

This is the starting point for most SelfRef usage - create a null pointer, then use set() to point it at your target data.

§Returns
  • SelfRef<T, I> - Pointer that must be initialised before use.
Source

pub fn is_null(&self) -> bool

Checks if the pointer is unset.

§Returns
  • bool - true when the pointer has not been initialised.
Source§

impl<T: ?Sized + PointerRecomposition, I: Offset> SelfRef<T, I>

Source

pub fn is_ready(&self) -> bool

Returns true once the pointer metadata has been populated.

§Returns
  • bool - true when initialisation has completed.
Source

pub fn components_if_ready(&self) -> Option<T::Components>

Provides the stored metadata when the pointer is initialised.

§Returns
  • Option<T::Components> - Metadata captured during initialisation.
Source

pub fn offset(&self) -> I

Returns the raw distance recorded for this pointer.

§Returns
  • I - Offset measured from this pointer to the target.
Source

pub fn from_parts(offset: I, components: T::Components) -> Self

Reconstructs a relative pointer from previously captured parts.

§Parameters
§Returns
  • SelfRef<T, I> - Pointer ready to be used at the current location.
Source

pub fn from_parts_with_target( offset: I, components: T::Components, target: Option<NonNull<T>>, ) -> Self

Reconstructs a relative pointer and optionally tracks a known absolute target.

The recorded pointer is only meaningful while the container remains at the same address; moves invalidate the stored absolute pointer and trigger debug assertions when the pointer is dereferenced.

§Parameters
  • offset - Relative distance between pointer and target when captured.
  • components - Metadata produced by PointerRecomposition::decompose.
  • target - Optional absolute pointer retained for debug verification.
§Returns
  • SelfRef<T, I> - Pointer configured with optional debug metadata.
Source

pub fn parts_if_ready(&self) -> Option<(I, T::Components)>

Returns the stored offset and metadata when initialised.

§Returns
  • Option<(I, T::Components)> - Offset and metadata if the pointer is ready.
Source

pub fn parts_with_target_if_ready( &self, ) -> Option<(I, T::Components, Option<NonNull<T>>)>

Returns offset, metadata, and any recorded absolute pointer when initialised.

§Returns
  • Option<(I, T::Components, Option<NonNull<T>>)> - Captured parts used for reconstruction along with the optional debug target.
Source

pub fn set(&mut self, value: &mut T) -> Result<(), I::Error>

Sets the pointer to target the given value.

Computes the offset from this SelfRef’s location to the target value. Returns an error if the distance is too large for the offset type I.

This is the safe way to establish the self-reference - it validates that the offset fits before storing it.

use movable_ref::SelfRef;
let mut data = "hello".to_string();
let mut ptr: SelfRef<String, i16> = SelfRef::null();
ptr.set(&mut data).unwrap();  // Now points to data
§Parameters
  • value - Target to be referenced by the pointer.
§Returns
  • Result<(), I::Error> - Ok when the offset fits in I, otherwise the conversion error.
Source

pub unsafe fn set_unchecked(&mut self, value: *mut T)

Sets the pointer without bounds checking.

Like set() but assumes the offset will fit in type I. Used when you’ve already validated the distance or are reconstructing a known-good pointer.

§Safety

The offset between value and self must be representable in I. value must not be null.

§Parameters
  • value - Raw pointer to the target value.
Source

pub unsafe fn as_raw_unchecked(&mut self) -> *mut T

Reconstructs the target as a mutable raw pointer.

§Safety

Same as as_raw_unchecked_impl.

§Returns
  • *mut T - Raw pointer to the target.
Source

pub unsafe fn as_non_null_unchecked(&mut self) -> NonNull<T>

Reconstructs the target as a NonNull pointer.

§Safety

Same as as_raw_unchecked_impl.

§Returns
  • NonNull<T> - Guaranteed non-null pointer to the target.
Source

pub unsafe fn as_ref_unchecked(&mut self) -> &T

Reconstructs the target as an immutable reference.

This is the most common way to access your self-referenced data.

§Safety

Same as as_raw_unchecked_impl. Standard reference aliasing rules apply.

§Returns
  • &T - Shared reference to the target.
Source

pub unsafe fn get_ref_from_base_unchecked<'a>(&self, base: *const u8) -> &'a T

Reconstructs a shared reference using a container base pointer.

§Safety
  • base must be the start address of the object that currently contains self.
  • The pointer must have been established with set and the relative positions must remain unchanged.
  • No mutable reference to the target may exist for the lifetime of the returned reference.
§Parameters
  • base - Address of the owning container currently holding the pointer.
§Returns
  • &'a T - Shared reference resolved relative to base.
Source

pub unsafe fn get_mut_from_base_unchecked<'a>(&self, base: *mut u8) -> &'a mut T

Reconstructs a mutable reference using a container base pointer.

§Safety
  • base must point to the start of the object that currently contains self.
  • The pointer must have been initialised with set and the relative positions must remain unchanged.
  • The caller must guarantee unique access to the target for the lifetime of the returned reference.
§Parameters
  • base - Address of the owning container currently holding the pointer.
§Returns
  • &'a mut T - Exclusive reference resolved relative to base.
Source

pub unsafe fn as_mut_unchecked(&mut self) -> &mut T

Reconstructs the target as a mutable reference.

§Safety

Same as as_raw_unchecked_impl. Standard reference aliasing rules apply.

§Returns
  • &mut T - Exclusive reference to the target.
Source§

impl<T: ?Sized + PointerRecomposition, I: Nullable> SelfRef<T, I>

Source

pub unsafe fn as_raw(&mut self) -> *mut T

Reconstructs the target as a raw pointer, returning null if unset.

§Safety

If the pointer was set, the relative positions must not have changed. For most pointer types this is safe, but may be undefined behavior for some exotic pointer representations.

§Returns
  • *mut T - Raw pointer to the target or null when unset.
Source

pub unsafe fn as_non_null(&mut self) -> Ptr<T>

Reconstructs the target as a NonNull pointer, returning None if unset.

§Safety

If the pointer was set, the relative positions must not have changed.

§Returns
  • Option<NonNull<T>> - Non-null pointer when initialised.
Source

pub unsafe fn as_ref(&mut self) -> Option<&T>

Reconstructs the target as an immutable reference, returning None if unset.

§Safety

Standard reference aliasing rules apply. If the pointer was set, the relative positions must not have changed.

§Returns
  • Option<&T> - Shared reference when initialised.
Source

pub unsafe fn as_mut(&mut self) -> Option<&mut T>

Reconstructs the target as a mutable reference, returning None if unset.

§Safety

Standard reference aliasing rules apply. If the pointer was set, the relative positions must not have changed.

§Returns
  • Option<&mut T> - Exclusive reference when initialised.

Trait Implementations§

Source§

impl<T: ?Sized + PointerRecomposition, I: Offset> Clone for SelfRef<T, I>

Source§

fn clone(&self) -> Self

Returns a duplicate of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl<T: ?Sized + PointerRecomposition, I: Debug + Offset> Debug for SelfRef<T, I>

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl<T: ?Sized + PointerRecomposition, I: Offset> PartialEq for SelfRef<T, I>

Source§

fn eq(&self, other: &Self) -> bool

Tests for self and other values to be equal, and is used by ==.
1.0.0 · Source§

fn ne(&self, other: &Rhs) -> bool

Tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
Source§

impl<T: ?Sized + PointerRecomposition, I: Debug + Offset> Pointer for SelfRef<T, I>

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl<T: ?Sized + PointerRecomposition, I: Offset> Copy for SelfRef<T, I>

Source§

impl<T: ?Sized + PointerRecomposition, I: Offset> Eq for SelfRef<T, I>

Auto Trait Implementations§

§

impl<T, I> Freeze for SelfRef<T, I>

§

impl<T, I> RefUnwindSafe for SelfRef<T, I>

§

impl<T, I = isize> !Send for SelfRef<T, I>

§

impl<T, I = isize> !Sync for SelfRef<T, I>

§

impl<T, I> Unpin for SelfRef<T, I>

§

impl<T, I> UnwindSafe for SelfRef<T, I>

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.