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 node = Node::new("test".into());
let boxed = Box::new(node); // ✓ Moves to heap
let mut vec = vec![*boxed]; // ✓ Moves again
let value = unsafe { vec[0].self_ref.as_ref_unchecked() }; // ✓ Still valid
§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.
Using NonZero*
offset types with self-pointing (zero offset) is undefined behavior.
Implementations§
Source§impl<T: ?Sized + PointerRecomposition, I: Offset> SelfRef<T, I>
impl<T: ?Sized + PointerRecomposition, I: Offset> SelfRef<T, I>
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
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.
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(&self) -> &T
pub unsafe fn as_ref_unchecked(&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.
Sourcepub unsafe fn as_mut_unchecked(&mut self) -> &mut T
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.
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.
Sourcepub unsafe fn as_non_null(&mut self) -> Ptr<T>
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.
Trait Implementations§
Source§impl<T: ?Sized + PointerRecomposition, I: Offset> From<I> for SelfRef<T, I>
Convert an offset into a SelfRef
impl<T: ?Sized + PointerRecomposition, I: Offset> From<I> for SelfRef<T, I>
Convert an offset into a SelfRef