movable_ref/metadata/traits.rs
1use crate::offset::Ptr;
2
3/// The bridge that makes `SelfRef` work with any type, sized or unsized.
4///
5/// Rust has two kinds of types: sized ones like `i32` and `String` that have a known
6/// size at compile time, and unsized ones like `[T]`, `str`, and trait objects that
7/// need extra metadata to work with. This trait abstracts away that complexity,
8/// letting `SelfRef` handle both seamlessly.
9///
10/// Most users never need to implement this trait directly - it's already implemented
11/// for all the types you'd want to use. The magic happens behind the scenes when you
12/// create a `SelfRef<[u8]>` or `SelfRef<TraitObject<dyn Debug>>`.
13///
14/// ```rust
15/// use movable_ref::SelfRef;
16///
17/// // Works with sized types (metadata = ())
18/// let mut value = 42i32;
19/// let mut ptr: SelfRef<i32> = SelfRef::null();
20/// ptr.set(&mut value).unwrap();
21///
22/// // Also works with slices (metadata = length)
23/// let mut data = vec![1, 2, 3, 4, 5];
24/// let mut slice_ptr: SelfRef<[i32]> = SelfRef::null();
25/// slice_ptr.set(&mut data[1..4]).unwrap(); // Points to middle section
26/// ```
27///
28/// The trait handles the complex pointer arithmetic needed to reconstruct fat pointers
29/// from offset-based storage, making `SelfRef` truly universal across Rust's type system.
30///
31/// # Safety
32///
33/// Implementations must correctly reconstruct valid pointers. The `compose` method
34/// is the critical piece - it takes a raw data pointer and metadata, then builds
35/// a proper pointer to `Self`. Get this wrong and you'll have undefined behavior.
36pub unsafe trait PointerRecomposition {
37 /// The metadata type - `()` for sized types, `usize` for slices, vtables for trait objects.
38 ///
39 /// This is what gets stored alongside the offset to fully reconstruct the pointer later.
40 /// For a `String`, this is just `()` since the size is in the struct itself.
41 /// For a `[u8]`, this is the length. For trait objects, it's the vtable pointer.
42 type Components: Copy + Eq;
43
44 /// Extracts metadata from a live reference.
45 ///
46 /// When `SelfRef` stores a pointer, it calls this to capture whatever extra
47 /// information is needed to reconstruct the reference later. Think of it as
48 /// "what do I need to remember about this pointer besides its location?"
49 fn decompose(this: &Self) -> Self::Components;
50
51 /// Reconstructs a proper pointer from raw components.
52 ///
53 /// This is where the magic happens - takes a basic data pointer and the stored
54 /// metadata, then builds back the original fat pointer. For slices, this means
55 /// combining the data pointer with the length. For trait objects, it's data + vtable.
56 ///
57 /// # Safety
58 ///
59 /// The `ptr` must be a valid pointer to the start of the data, and `data` must be
60 /// valid metadata that was previously extracted from a valid pointer of type `Self`.
61 /// The resulting pointer will only be valid if both components are correct.
62 unsafe fn recompose(ptr: Ptr<u8>, data: Self::Components) -> Ptr<Self>;
63}