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>
impl<T: ?Sized + PointerRecomposition, I: Nullable> SelfRef<T, I>
Source§impl<T: ?Sized + PointerRecomposition, I: Offset> SelfRef<T, I>
impl<T: ?Sized + PointerRecomposition, I: Offset> SelfRef<T, I>
Sourcepub fn is_ready(&self) -> bool
pub fn is_ready(&self) -> bool
Returns true once the pointer metadata has been populated.
§Returns
bool-truewhen initialisation has completed.
Sourcepub fn components_if_ready(&self) -> Option<T::Components>
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.
Sourcepub fn offset(&self) -> I
pub fn offset(&self) -> I
Returns the raw distance recorded for this pointer.
§Returns
I- Offset measured from this pointer to the target.
Sourcepub fn from_parts(offset: I, components: T::Components) -> Self
pub fn from_parts(offset: I, components: T::Components) -> Self
Reconstructs a relative pointer from previously captured parts.
§Parameters
offset- Relative distance between pointer and target when captured.components- Metadata produced byPointerRecomposition::decompose.
§Returns
SelfRef<T, I>- Pointer ready to be used at the current location.
Sourcepub fn from_parts_with_target(
offset: I,
components: T::Components,
target: Option<NonNull<T>>,
) -> Self
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 byPointerRecomposition::decompose.target- Optional absolute pointer retained for debug verification.
§Returns
SelfRef<T, I>- Pointer configured with optional debug metadata.
Sourcepub fn parts_if_ready(&self) -> Option<(I, T::Components)>
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.
Sourcepub fn parts_with_target_if_ready(
&self,
) -> Option<(I, T::Components, Option<NonNull<T>>)>
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.
Sourcepub fn set(&mut self, value: &mut T) -> Result<(), I::Error>
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>-Okwhen the offset fits inI, otherwise the conversion error.
Sourcepub unsafe fn set_unchecked(&mut self, value: *mut T)
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.
Sourcepub unsafe fn as_raw_unchecked(&mut self) -> *mut T
pub unsafe fn as_raw_unchecked(&mut self) -> *mut T
Sourcepub unsafe fn as_non_null_unchecked(&mut self) -> NonNull<T>
pub unsafe fn as_non_null_unchecked(&mut self) -> NonNull<T>
Sourcepub unsafe fn as_ref_unchecked(&mut self) -> &T
pub unsafe fn as_ref_unchecked(&mut self) -> &T
Sourcepub unsafe fn get_ref_from_base_unchecked<'a>(&self, base: *const u8) -> &'a T
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
basemust be the start address of the object that currently containsself.- The pointer must have been established with
setand 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 tobase.
Sourcepub unsafe fn get_mut_from_base_unchecked<'a>(&self, base: *mut u8) -> &'a mut T
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
basemust point to the start of the object that currently containsself.- The pointer must have been initialised with
setand 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 tobase.
Sourcepub unsafe fn as_mut_unchecked(&mut self) -> &mut T
pub unsafe fn as_mut_unchecked(&mut self) -> &mut T
Source§impl<T: ?Sized + PointerRecomposition, I: Nullable> SelfRef<T, I>
impl<T: ?Sized + PointerRecomposition, I: Nullable> SelfRef<T, I>
Sourcepub unsafe fn as_raw(&mut self) -> *mut T
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.